Merging in free energy, exp. ensemble, & andersen t-control to 4.6
authorMichael Shirts <michael.shirts@virginia.edu>
Tue, 17 Jan 2012 14:51:13 +0000 (09:51 -0500)
committerMichael Shirts <michael.shirts@virginia.edu>
Mon, 4 Jun 2012 22:32:25 +0000 (00:32 +0200)
Conflicts:
src/gmxlib/mvdata.c
src/gmxlib/txtdump.c
src/kernel/readir.c
src/mdlib/sim_util.c
src/tools/gmx_membed.c
include/mdrun.h
src/kernel/md.c
src/kernel/md_openmm.c
src/kernel/md_openmm.h
src/kernel/runner.c
src/mdlib/minimize.c
src/mdlib/tpi.c
src/tools/gmx_membed.c
src/kernel/md.c

Change-Id: Ide69a8dbfb96072d5c55d0a051dc9db788cbe144

89 files changed:
include/bondf.h
include/checkpoint.h
include/constr.h
include/dihre.h [deleted file]
include/force.h
include/mdebin.h
include/mdrun.h
include/names.h
include/nonbonded.h
include/ns.h
include/pull.h
include/tpxio.h
include/trnio.h
include/typedefs.h
include/types/enums.h
include/types/fcdata.h
include/types/forcerec.h
include/types/idef.h
include/types/inputrec.h
include/types/state.h
include/types/trx.h
include/update.h
share/README_FreeEnergyModifications.txt [new file with mode: 0644]
share/html/online/g_energy.html
share/html/online/mdp_opt.html
share/html/online/mdrun.html
src/gmxlib/bondfree.c
src/gmxlib/checkpoint.c
src/gmxlib/dihres.c [deleted file]
src/gmxlib/enxio.c
src/gmxlib/ifunc.c
src/gmxlib/inputrec.c
src/gmxlib/mvdata.c
src/gmxlib/names.c
src/gmxlib/nonbonded/nb_free_energy.c
src/gmxlib/nonbonded/nb_free_energy.h
src/gmxlib/nonbonded/nonbonded.c
src/gmxlib/nrnb.c
src/gmxlib/topsort.c
src/gmxlib/tpxio.c
src/gmxlib/trxio.c
src/gmxlib/txtdump.c
src/gmxlib/typedefs.c
src/kernel/compute_io.c
src/kernel/convparm.c
src/kernel/gmxcheck.c
src/kernel/grompp.c
src/kernel/md.c
src/kernel/md_openmm.c
src/kernel/md_openmm.h
src/kernel/mdrun.c
src/kernel/readir.c
src/kernel/readir.h
src/kernel/readpull.c
src/kernel/repl_ex.c
src/kernel/repl_ex.h
src/kernel/runner.c
src/kernel/tpbcmp.c
src/kernel/tpbconv.c
src/mdlib/constr.c
src/mdlib/coupling.c
src/mdlib/domdec.c
src/mdlib/domdec_top.c
src/mdlib/expanded.c [new file with mode: 0644]
src/mdlib/force.c
src/mdlib/forcerec.c
src/mdlib/init.c
src/mdlib/md_support.c
src/mdlib/mdebin.c
src/mdlib/mdebin_bar.c
src/mdlib/mdebin_bar.h
src/mdlib/minimize.c
src/mdlib/ns.c
src/mdlib/partdec.c
src/mdlib/pull.c
src/mdlib/shellfc.c
src/mdlib/sim_util.c
src/mdlib/stat.c
src/mdlib/tgroup.c
src/mdlib/tpi.c
src/mdlib/update.c
src/mdlib/wall.c
src/tools/addconf.c
src/tools/calcpot.c
src/tools/expfit.c
src/tools/gmx_bar.c
src/tools/gmx_disre.c
src/tools/gmx_energy.c
src/tools/mk_angndx.c

index db28fd376f2490c95ebbd4726ea319af2bf225ed..5ea6cd26a60c5607ba8f26ecf223dcc0f9c8da09 100644 (file)
@@ -59,7 +59,7 @@ void calc_bonds(FILE *fplog,const gmx_multisim_t *ms,
                 rvec x[],history_t *hist,
                 rvec f[],t_forcerec *fr,
                 const t_pbc *pbc,const t_graph *g,
-                gmx_enerdata_t *enerd,t_nrnb *nrnb,real lambda,
+                gmx_enerdata_t *enerd,t_nrnb *nrnb,real *lambda,
                 const t_mdatoms *md,
                 t_fcdata *fcd,int *ddgatindex,
                 t_atomtypes *atype, gmx_genborn_t *born,
@@ -96,7 +96,7 @@ void calc_bonds_lambda(FILE *fplog,
                              t_forcerec *fr,
                              const t_pbc *pbc,const t_graph *g,
                              gmx_enerdata_t *enerd,t_nrnb *nrnb,
-                             real lambda,
+                             real *lambda,
                              const t_mdatoms *md,
                              t_fcdata *fcd,int *global_atom_index);
 /* As calc_bonds, but only determines the potential energy
@@ -132,6 +132,9 @@ void do_dih_fup(int i,int j,int k,int l,real ddphi,
                       const rvec *x,int t1,int t2,int t3);
 /* Do an update of the forces for dihedral potentials */
 
+void make_dp_periodic(real *dp);
+/* make a dihedral fall in the range (-pi,pi) */
+
 /*************************************************************************
  *
  *  Bonded force functions
@@ -141,7 +144,8 @@ void do_dih_fup(int i,int j,int k,int l,real ddphi,
   t_ifunc angles,g96angles,cross_bond_bond,cross_bond_angle,urey_bradley,quartic_angles,linear_angles;
   t_ifunc pdihs,idihs,rbdihs;
   t_ifunc tab_bonds,tab_angles,tab_dihs;
-  t_ifunc polarize,anharm_polarize,water_pol,thole_pol,angres,angresz,unimplemented;
+  t_ifunc polarize,anharm_polarize,water_pol,thole_pol,angres,angresz,dihres,unimplemented;
+
 
 #ifdef __cplusplus
 }
index d1f1ce48dc25d410cce6517e37c3f0db33f11cc9..eb31d258651c4b6feab3d9e71d31e63dd8e8e201 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 
+ *
  *                This source code is part of
- * 
+ *
  *                 G   R   O   M   A   C   S
- * 
+ *
  *          GROningen MAchine for Chemical Simulations
- * 
+ *
  *                        VERSION 3.2.0
  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * If you want to redistribute modifications, please consider that
  * scientific software is very special. Version control is crucial -
  * bugs must be traceable. We will be happy to consider code for
  * inclusion in the official distribution, but derived work must not
  * be called official GROMACS. Details are found in the README & COPYING
  * files - if they are missing, get the official version at www.gromacs.org.
- * 
+ *
  * To help us fund GROMACS development, we humbly ask that you cite
  * the papers on the package - you can find them in the top README file.
- * 
+ *
  * For more info, check our website at http://www.gromacs.org
- * 
+ *
  * And Hey:
  * Gromacs Runs On Most of All Computer Systems
  */
@@ -52,10 +52,11 @@ extern "C" {
  * otherwise moves the previous <fn>.cpt to <fn>_prev.cpt
  */
 void write_checkpoint(const char *fn,gmx_bool bNumberAndKeep,
-                            FILE *fplog,t_commrec *cr,
-                            int eIntegrator,int simulation_part,
-                            gmx_large_int_t step,double t,
-                            t_state *state);
+                     FILE *fplog,t_commrec *cr,
+                     int eIntegrator, int simulation_part,
+                     gmx_bool bExpanded, int elamstats,
+                     gmx_large_int_t step,double t,
+                     t_state *state);
 
 /* Loads a checkpoint from fn for run continuation.
  * Generates a fatal error on system size mismatch.
@@ -68,10 +69,9 @@ void write_checkpoint(const char *fn,gmx_bool bNumberAndKeep,
  * support file locking.
  */
 void load_checkpoint(const char *fn,FILE **fplog,
-                           t_commrec *cr,gmx_bool bPartDecomp,ivec dd_nc,
-                           t_inputrec *ir,t_state *state,gmx_bool *bReadRNG, 
-                           gmx_bool *bReadEkin,
-                    gmx_bool bAppend,gmx_bool bForceAppend);
+                    t_commrec *cr,gmx_bool bPartDecomp,ivec dd_nc,
+                    t_inputrec *ir,t_state *state,gmx_bool *bReadRNG,
+             gmx_bool *bReadEkin,gmx_bool bAppend,gmx_bool bForceAppend);
 
 /* Read the state from checkpoint file.
  * Arrays in state that are NULL are allocated.
index 92d4cb520ca119f60d6606a7a7d01aabfdd66c39..a45b58d25f2a922a4edd6e23b541685b1855b724 100644 (file)
@@ -252,6 +252,15 @@ gmx_bool constrain_lincs(FILE *log,gmx_bool bLog,gmx_bool bEner,
                            int maxwarn,int *warncount);
 /* Returns if the constraining succeeded */
 
+
+/* helper functions for andersen temperature control, because the
+ * gmx_constr construct is only defined in constr.c. Return the list
+ * of blocks (get_sblock) and the number of blocks (get_nblocks).  */
+
+int *get_sblock(struct gmx_constr *constr);
+
+int get_nblocks(struct gmx_constr *constr);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/dihre.h b/include/dihre.h
deleted file mode 100644 (file)
index c3fb97d..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gromacs Runs On Most of All Computer Systems
- */
-
-#ifndef _dihre_h
-#define _dihre_h
-
-#include "sysstuff.h"
-#include "typedefs.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-  void init_dihres(FILE *fplog,gmx_mtop_t *mtop,t_inputrec *ir,t_fcdata *fcd);
-
-
-t_ifunc ta_dihres;
-/* Calculate the distance restraint forces, return the potential */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _disre_h */
index 4f7f08ab4be6164c16e4e07f70e43d5b2c81e2a2..05d585bc29a122ce57f31a3a1f74ccb234e8386b 100644 (file)
@@ -87,9 +87,7 @@ void make_wall_tables(FILE *fplog,const output_env_t oenv,
                             t_forcerec *fr);
 
 real do_walls(t_inputrec *ir,t_forcerec *fr,matrix box,t_mdatoms *md,
-                    rvec x[],rvec f[],real lambda,real Vlj[],t_nrnb *nrnb);
-
-
+             rvec x[],rvec f[],real lambda,real Vlj[],t_nrnb *nrnb);
 
 t_forcerec *mk_forcerec(void);
 
@@ -158,7 +156,7 @@ void init_forcerec(FILE       *fplog,
  * print_force >= 0: print forces for atoms with force >= print_force
  */
 
-void init_enerdata(int ngener,int n_flambda,gmx_enerdata_t *enerd);
+void init_enerdata(int ngener,int n_lambda,gmx_enerdata_t *enerd);
 /* Intializes the energy storage struct */
 
 void destroy_enerdata(gmx_enerdata_t *enerd);
@@ -173,7 +171,7 @@ void reset_enerdata(t_grpopts *opts,
 void sum_epot(t_grpopts *opts,gmx_enerdata_t *enerd);
 /* Locally sum the non-bonded potential energy terms */
 
-void sum_dhdl(gmx_enerdata_t *enerd,double lambda,t_inputrec *ir);
+void sum_dhdl(gmx_enerdata_t *enerd,real *lambda,t_lambda *fepvals);
 /* Sum the free energy contributions */
 
 void update_forcerec(FILE *fplog,t_forcerec *fr,matrix box);
@@ -217,7 +215,7 @@ void do_force(FILE *log,t_commrec *cr,
                     tensor vir_force,
                     t_mdatoms *mdatoms,
                     gmx_enerdata_t *enerd,t_fcdata *fcd,
-                    real lambda,t_graph *graph,
+                    real *lambda,t_graph *graph,
                     t_forcerec *fr,gmx_vsite_t *vsite,rvec mu_tot,
                     double t,FILE *field,gmx_edsam_t ed,
                     gmx_bool bBornRadii,
@@ -241,7 +239,7 @@ void ns(FILE       *fplog,
               t_mdatoms  *md,
               t_commrec  *cr,
               t_nrnb     *nrnb,
-              real       lambda,
+              real       *lambda,
               real       *dvdlambda,
               gmx_grppairener_t *grppener,
               gmx_bool       bFillGrid,
@@ -271,7 +269,8 @@ void do_force_lowlevel(FILE         *fplog,
                              t_atomtypes  *atype,
                              gmx_bool         bBornRadii,
                              matrix       box,
-                             real         lambda,
+                             t_lambda     *fepvals,
+                             real         *lambda,
                              t_graph      *graph,
                              t_blocka     *excl,
                              rvec         mu_tot[2],
index 2abb12e5b1731713513c4874afd907b2205c1174..02351844878f79a367222e90094df1e25313fadb 100644 (file)
@@ -72,6 +72,7 @@ typedef struct {
   gmx_bool   bTricl;
   gmx_bool   bDynBox;
   gmx_bool   bNHC_trotter;
+  gmx_bool   bPrintNHChains;
   gmx_bool   bMTTK;
   gmx_bool   bDiagPres;
   gmx_bool   bVir;
@@ -88,8 +89,8 @@ typedef struct {
   char   **print_grpnms;
 
   FILE   *fp_dhdl; /* the dhdl.xvg output file */
-  gmx_bool dhdl_derivatives; /* whether to write the derivatives to dhdl.xvg */
-  t_mde_delta_h_coll *dhc; /* the BAR delta U (raw data + histogram) */
+  t_mde_delta_h_coll *dhc; /* the delta U components (raw data + histogram) */
+  real *temperatures;
 } t_mdebin;
 
 t_mdebin *init_mdebin(ener_file_t fp_ene,
@@ -105,20 +106,22 @@ FILE *open_dhdl(const char *filename,const t_inputrec *ir,
 /* update the averaging structures. Called every time 
    the energies are evaluated. */
 void upd_mdebin(t_mdebin *md, 
-                       gmx_bool write_dhdl,
-                      gmx_bool bSum,
-                      double time,
-                      real tmass,
-                      gmx_enerdata_t *enerd,
-                      t_state *state,
-                      matrix  lastbox,
-                      tensor svir,
-                      tensor fvir,
-                      tensor vir,
-                      tensor pres,
-                      gmx_ekindata_t *ekind,
-                      rvec mu_tot,
-                      gmx_constr_t constr);
+        gmx_bool bDoDHDL,
+        gmx_bool bSum,
+        double time,
+        real tmass,
+        gmx_enerdata_t *enerd,
+        t_state *state,
+        t_lambda *fep,
+        t_expanded *expand,
+        matrix  lastbox,
+        tensor svir,
+        tensor fvir,
+        tensor vir,
+        tensor pres,
+        gmx_ekindata_t *ekind,
+        rvec mu_tot,
+        gmx_constr_t constr);
 
 void upd_mdebin_step(t_mdebin *md);
 /* Updates only the step count in md */
index 81080968bae7bdf6798dcfe09150d7ecf1963866..db7923a571f9b12b5e3d588d02c2afc933c889ed 100644 (file)
@@ -134,6 +134,8 @@ typedef struct {
   const char *fn_cpt;
   gmx_bool bKeepAndNumCPT;
   int  eIntegrator;
+  gmx_bool  bExpanded;
+  int elamstats;
   int  simulation_part;
   FILE *fp_dhdl;
   FILE *fp_field;
@@ -168,7 +170,7 @@ typedef double gmx_integrator_t(FILE *log,t_commrec *cr,
                                t_nrnb *nrnb,gmx_wallcycle_t wcycle,
                                gmx_edsam_t ed, 
                                t_forcerec *fr,
-                               int repl_ex_nst,int repl_ex_seed,
+                               int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
                                 gmx_membed_t membed,
                                real cpt_period,real max_hours,
                                const char *deviceOptions,
@@ -229,6 +231,10 @@ void rerun_parallel_comm(t_commrec *cr,t_trxframe *fr,
 real compute_conserved_from_auxiliary(t_inputrec *ir, t_state *state,           
                                       t_extmass *MassQ);
 
+/* set the lambda values at each step of mdrun when they change */
+void set_current_lambdas(gmx_large_int_t step, t_lambda *fepvals, gmx_bool bRerunMD,
+                         t_trxframe *rerun_fr, t_state *state_global, t_state *state, double lam0[]);
+
 /* reset all cycle and time counters. */
 void reset_all_counters(FILE *fplog,t_commrec *cr,
                         gmx_large_int_t step,
@@ -332,9 +338,26 @@ void finish_run(FILE *log,t_commrec *cr,const char *confout,
 void calc_enervirdiff(FILE *fplog,int eDispCorr,t_forcerec *fr);
 
 void calc_dispcorr(FILE *fplog,t_inputrec *ir,t_forcerec *fr,
-                         gmx_large_int_t step, int natoms, 
-                         matrix box,real lambda,tensor pres,tensor virial,
-                         real *prescorr, real *enercorr, real *dvdlcorr);
+                   gmx_large_int_t step, int natoms,
+                   matrix box,real lambda,tensor pres,tensor virial,
+                   real *prescorr, real *enercorr, real *dvdlcorr);
+
+void initialize_lambdas(FILE *fplog,t_inputrec *ir,int *fep_state,real *lambda,double *lam0);
+
+void init_npt_masses(t_inputrec *ir, t_state *state, t_extmass *MassQ, gmx_bool bInit);
+
+int ExpandedEnsembleDynamics(FILE *log,t_inputrec *ir, gmx_enerdata_t *enerd,
+                             t_state *state, t_extmass *MassQ, df_history_t *dfhist,
+                             gmx_large_int_t step, gmx_rng_t mcrng,
+                             rvec *v, t_mdatoms *mdatoms);
+
+void PrintFreeEnergyInfoToFile(FILE *outfile, t_lambda *fep, t_expanded *expand, t_simtemp *simtemp, df_history_t *dfhist,
+                               int nlam, int frequency, gmx_large_int_t step);
+
+void get_mc_state(gmx_rng_t rng,t_state *state);
+
+void set_mc_state(gmx_rng_t rng,t_state *state);
+
 
 typedef enum
 {
@@ -408,7 +431,7 @@ int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
              gmx_bool bCompact, int nstglobalcomm, ivec ddxyz,int dd_node_order,
              real rdd, real rconstr, const char *dddlb_opt,real dlb_scale,
             const char *ddcsx,const char *ddcsy,const char *ddcsz,
-            int nstepout, int resetstep, int nmultisim, int repl_ex_nst,
+            int nstepout, int resetstep, int nmultisim, int repl_ex_nst, int repl_ex_nex,
              int repl_ex_seed, real pforce,real cpt_period,real max_hours,
             const char *deviceOptions, unsigned long Flags);
 /* Driver routine, that calls the different methods */
@@ -421,7 +444,7 @@ void md_print_warning(const t_commrec *cr,FILE *fplog,const char *buf);
 void init_md(FILE *fplog,
                    t_commrec *cr,t_inputrec *ir, const output_env_t oenv, 
                    double *t,double *t0,
-                   real *lambda,double *lam0,
+                   real *lambda,int *fep_state, double *lam0,
                    t_nrnb *nrnb,gmx_mtop_t *mtop,
                    gmx_update_t *upd,
                    int nfile,const t_filenm fnm[],
index 671280ca5cc7cca91108b84399acf9ec7abf8328..057995ea9c64d24067d5e57afaadb8d3b731d4f3 100644 (file)
@@ -67,10 +67,14 @@ extern const char *edisreweighting_names[edrwNR+1];
 extern const char *enbf_names[eNBF_NR+1];
 extern const char *ecomb_names[eCOMB_NR+1];
 extern const char *gtypes[egcNR+1];
+extern const char *esimtemp_names[esimtempNR+1];
 extern const char *efep_names[efepNR+1];
-extern const char *separate_dhdl_file_names[efepNR+1];
-extern const char *dhdl_derivatives_names[efepNR+1];
-extern const char *efep_names[efepNR+1];
+extern const char *efpt_names[efptNR+1];
+extern const char *elamstats_names[elamstatsNR+1];
+extern const char *elmcmove_names[elmcmoveNR+1];
+extern const char *elmceq_names[elmceqNR+1];
+extern const char *separate_dhdl_file_names[esepdhdlfileNR+1];
+extern const char *dhdl_derivatives_names[edhdlderivativesNR+1];
 extern const char *esol_names[esolNR+1];
 extern const char *enlist_names[enlistNR+1];
 extern const char *edispc_names[edispcNR+1];
@@ -113,9 +117,10 @@ extern const char *eAdressSITEtype_names[eAdressSITENR+1];
 #define EDISREWEIGHTING(e)  ENUM_NAME(e,edrwNR,edisreweighting_names)
 #define ENBFNAME(e)    ENUM_NAME(e,eNBF_NR,enbf_names)
 #define ECOMBNAME(e)   ENUM_NAME(e,eCOMB_NR,ecomb_names)
+#define ESIMTEMP(e)    ENUM_NAME(e,esimtempNR,esimtemp_names)
 #define EFEPTYPE(e)    ENUM_NAME(e,efepNR,efep_names)
-#define SEPDHDLFILETYPE(e) ENUM_NAME(e,sepdhdlfileNR,separate_dhdl_file_names)
-#define DHDLDERIVATIVESTYPE(e) ENUM_NAME(e,dhdlderivativesNR,dhdl_derivatives_names)
+#define SEPDHDLFILETYPE(e) ENUM_NAME(e,esepdhdlfileNR,separate_dhdl_file_names)
+#define DHDLDERIVATIVESTYPE(e) ENUM_NAME(e,edhdlderivativesNR,dhdl_derivatives_names)
 #define ESOLTYPE(e)    ENUM_NAME(e,esolNR,esol_names)
 #define ENLISTTYPE(e)  ENUM_NAME(e,enlistNR,enlist_names)
 #define EDISPCORR(e)   ENUM_NAME(e,edispcNR,edispc_names)
index b9956761943f95c580b28f1c7f348f75f0749bb2..cb75f0cd9e3a944160ff87abf3b5bb5cc7b68b35 100644 (file)
@@ -57,7 +57,7 @@ void
 do_nonbonded(t_commrec *cr,t_forcerec *fr,
              rvec x[],rvec f[],t_mdatoms *md,t_blocka *excl,
              real egnb[],real egcoul[],real egb[],rvec box_size,
-             t_nrnb *nrnb,real lambda,real *dvdlambda,
+             t_nrnb *nrnb,real *lambda,real dvdlambda[],
              int nls,int eNL,int flags);
 
 /* Calculate VdW/charge pair interactions (usually 1-4 interactions).
@@ -68,7 +68,7 @@ do_listed_vdw_q(int ftype,int nbonds,
                const t_iatom iatoms[],const t_iparams iparams[],
                const rvec x[],rvec f[],rvec fshift[],
                const t_pbc *pbc,const t_graph *g,
-               real lambda,real *dvdlambda,
+               real *lambda,real *dvdlambda,
                const t_mdatoms *md,
                const t_forcerec *fr,gmx_grppairener_t *grppener,
                int *global_atom_index);
index 526b926c597829df8d596b7fcd4d0de98278b5cd..bfe9b4c9af96bb7ed3d158b53874cf054161d596 100644 (file)
@@ -86,7 +86,7 @@ int search_neighbours(FILE *log,t_forcerec *fr,
                             gmx_groups_t *groups,
                             t_commrec *cr,
                             t_nrnb *nrnb,t_mdatoms *md,
-                            real lambda,real *dvdlambda,
+                            real *lambda,real *dvdlambda,
                             gmx_grppairener_t *grppener,
                             gmx_bool bFillGrid,
                             gmx_bool bDoLongRange,
index b9008b8aa23c5ac20fb180ab19f6e391695e4c2d..a7bbed3cb26a4ce4979dafaab60e76880dc36751 100644 (file)
@@ -81,6 +81,7 @@ void init_pull(FILE *fplog,
                       gmx_mtop_t *mtop, /* the topology of the whole system */
                       t_commrec * cr, /* struct for communication info */
                       const output_env_t oenv,  /* output options */
+                      real lambda, /* FEP lambda */
                       gmx_bool bOutFile,   /* open output files */
                       unsigned long Flags);
 
index f4a5c8cdcd5cdc68424b856f123dd16f9b7ec565..34b20acda4dc821045d07f24bf1e4ccf8f383c67 100644 (file)
@@ -64,6 +64,13 @@ typedef struct
   int  natoms;         /* The total number of atoms                    */
   int   ngtc;           /* The number of temperature coupling groups    */
   real lambda;         /* Current value of lambda                      */
+  int   fep_state;      /* Current value of the alchemical state --
+                         * not yet printed out.  */
+  /*a better decision will eventually (5.0 or later) need to be made
+    on how to treat the alchemical state of the system, which can now
+    vary through a simulation, and cannot be completely described
+    though a single lambda variable, or even a single state
+    index. Eventually, should probably be a vector. MRS*/
 } t_tpxheader;
 
 /* 
index 192f4b19a56efd8f1507e67090e7d38c82bef744..91d0de9646aec0365b7c39213217589e45551a23 100644 (file)
@@ -78,6 +78,7 @@ typedef struct                /* This struct describes the order and the      */
   int  nre;            /* Backward compatibility                       */
   real t;              /* Current time                                 */
   real lambda;         /* Current value of lambda                      */
+  int  fep_state;  /* Current value of alchemical state */
 } t_trnheader;
 
 t_fileio *open_trn(const char *fn,const char *mode);
index 3a0007e0ba0afb6da6e007d418ba4fb8e7b3999b..7b01ff14de1f6e42bbd239a7526cbe07f63167b6 100644 (file)
@@ -138,7 +138,9 @@ void init_inputrec(t_inputrec *ir);
 void init_energyhistory(energyhistory_t * enerhist);
 void done_energyhistory(energyhistory_t * enerhist);
 void init_gtc_state(t_state *state,int ngtc, int nnhpres, int nhchainlength);
-void init_state(t_state *state,int natoms,int ngtc, int nnhpres, int nhchainlength);
+void init_state(t_state *state,int natoms,int ngtc, int nnhpres, int nhchainlength, int nlambda);
+void init_df_history(df_history_t *dfhist, int nlambda, real wl_delta);
+void copy_df_history(df_history_t * df_dest, df_history_t *df_source);
 
 void copy_blocka(const t_blocka *src,t_blocka *dest);
 
index 5b05f748b93b3933c0805899ab09ce388197a461..e081177f3668a00e6e611f464c6d6173bfff8818 100644 (file)
@@ -44,9 +44,11 @@ enum {
 };
 
 enum {
-  etcNO, etcBERENDSEN, etcNOSEHOOVER, etcYES, etcANDERSEN, etcANDERSENINTERVAL, etcVRESCALE, etcNR
+  etcNO, etcBERENDSEN, etcNOSEHOOVER, etcYES, etcANDERSEN, etcANDERSENMASSIVE, etcVRESCALE, etcNR
 }; /* yes is an alias for berendsen */
 
+#define ETC_ANDERSEN(e) (((e) == etcANDERSENMASSIVE) || ((e) == etcANDERSEN))
+
 enum {
   epcNO, epcBERENDSEN, epcPARRINELLORAHMAN, epcISOTROPIC, epcMTTK, epcNR
 }; /* isotropic is an alias for berendsen */
@@ -150,23 +152,76 @@ enum {
   eNBF_NONE, eNBF_LJ, eNBF_BHAM, eNBF_NR 
 };
 
+/* simulated tempering methods */
+enum {
+  esimtempGEOMETRIC, esimtempEXPONENTIAL, esimtempLINEAR, esimtempNR
+};
 /* FEP selection */
 enum {
-  efepNO, efepYES, efepNR
+  efepNO, efepYES, efepSTATIC, efepSLOWGROWTH, efepEXPANDED, efepNR
+};
+  /* if efepNO, there are no evaluations at other states.
+     if efepYES, treated equivalently to efepSTATIC.
+     if efepSTATIC, then lambdas do not change during the simulation.
+     if efepSLOWGROWTH, then the states change monotonically throughout the simulation.
+     if efepEXPANDED, then expanded ensemble simulations are occuring.
+  */
+
+/* FEP coupling types */
+enum {
+  efptFEP,efptMASS,efptCOUL,efptVDW,efptBONDED,efptRESTRAINT,efptTEMPERATURE,efptNR
+};
+
+/* How the lambda weights are calculated:
+   elamstatsMETROPOLIS = using the metropolis criteria
+   elamstatsBARKER = using the Barker critera for transition weights - also called unoptimized Bennett
+   elamstatsMINVAR = using Barker + minimum variance for weights
+   elamstatsWL = Wang-Landu (using visitation counts)
+   elamstatsWWL = Weighted Wang-Landau (using optimized gibbs weighted visitation counts)
+*/
+enum {
+  elamstatsNO, elamstatsMETROPOLIS, elamstatsBARKER, elamstatsMINVAR, elamstatsWL, elamstatsWWL, elamstatsNR
+};
+
+#define ELAMSTATS_EXPANDED(e) ((e) > elamstatsNO)
+
+#define EWL(e) ((e) == elamstatsWL || (e) == elamstatsWWL)
+
+/* How moves in lambda are calculated:
+   elmovemcMETROPOLIS - using the Metropolis criteria, and 50% up and down
+   elmovemcBARKER - using the Barker criteria, and 50% up and down
+   elmovemcGIBBS - computing the transition using the marginalized probabilities of the lambdas
+   elmovemcMETGIBBS - computing the transition using the metropolized version of Gibbs (Monte Carlo Strategies in Scientific computing, Liu, p. 134)
+*/
+enum {
+  elmcmoveNO,elmcmoveMETROPOLIS, elmcmoveBARKER, elmcmoveGIBBS, elmcmoveMETGIBBS, elmcmoveNR
+};
+
+/* how we decide whether weights have reached equilibrium
+   elmceqNO - never stop, weights keep going
+   elmceqYES - fix the weights from the beginning; no movement
+   elmceqWLDELTA - stop when the WL-delta falls below a certain level
+   elmceqNUMATLAM - stop when we have a certain number of samples at every step
+   elmceqSTEPS - stop when we've run a certain total number of steps
+   elmceqSAMPLES - stop when we've run a certain total number of samples
+   elmceqRATIO - stop when the ratio of samples (lowest to highest) is sufficiently large
+*/
+enum {
+  elmceqNO,elmceqYES,elmceqWLDELTA,elmceqNUMATLAM,elmceqSTEPS,elmceqSAMPLES,elmceqRATIO,elmceqNR
 };
 
 /* separate_dhdl_file selection */
 enum
 {
-    /* NOTE: YES is the first one. Do NOT interpret this one as a gmx_bool */
-    sepdhdlfileYES, sepdhdlfileNO, sepdhdlfileNR
+  /* NOTE: YES is the first one. Do NOT interpret this one as a gmx_bool */
+  esepdhdlfileYES, esepdhdlfileNO, esepdhdlfileNR
 };
 
 /* dhdl_derivatives selection */
 enum
 {
-    /* NOTE: YES is the first one. Do NOT interpret this one as a gmx_bool */
-    dhdlderivativesYES, dhdlderivativesNO, dhdlderivativesNR
+  /* NOTE: YES is the first one. Do NOT interpret this one as a gmx_bool */
+  edhdlderivativesYES, edhdlderivativesNO, edhdlderivativesNR
 };
 
 /* Solvent model */
@@ -196,7 +251,7 @@ enum {
 
 /* Implicit solvent algorithms */
 enum { 
-       eisNO, eisGBSA, eisNR 
+  eisNO, eisGBSA, eisNR
 };
 
 /* Algorithms for calculating GB radii */
index 634a477245a6c7bc94e36692be3bd5a45731fb24..0c94ba67d8aa749bd241588fba800ce8d1715ac3 100644 (file)
@@ -111,7 +111,6 @@ typedef struct {
 
   t_disresdata disres;
   t_oriresdata orires;
-  real         dihre_fc;
 } t_fcdata;
 
 #ifdef __cplusplus
index b9facea258d46775a1e1ba8e2746459f3108673e..e96a9c1c32910bf1512af5fe05fdc6fa6ee4563e 100644 (file)
@@ -95,6 +95,10 @@ typedef struct {
  */
 #define GMX_CUTOFF_INF 1E+18
 
+/* enums for the neighborlist type */
+enum { enbvdwNONE,enbvdwLJ,enbvdwBHAM,enbvdwTAB,enbvdwNR};
+/* OOR is "one over r" -- standard coul */
+enum { enbcoulNONE,enbcoulOOR,enbcoulRF,enbcoulTAB,enbcoulGB,enbcoulFEWALD,enbcoulNR};
 
 enum { egCOULSR, egLJSR, egBHAMSR, egCOULLR, egLJLR, egBHAMLR,
        egCOUL14, egLJ14, egGB, egNR };
@@ -107,9 +111,10 @@ typedef struct {
 typedef struct {
   real term[F_NRE];    /* The energies for all different interaction types */
   gmx_grppairener_t grpp;
-  double dvdl_lin;     /* Contributions to dvdl with linear lam-dependence */
-  double dvdl_nonlin;  /* Idem, but non-linear dependence                  */
+  double dvdl_lin[efptNR];       /* Contributions to dvdl with linear lam-dependence */
+  double dvdl_nonlin[efptNR];    /* Idem, but non-linear dependence                  */
   int    n_lambda;
+  int    fep_state;              /*current fep state -- just for printing */
   double *enerpart_lambda; /* Partial energy for lambda and flambda[] */
 } gmx_enerdata_t;
 /* The idea is that dvdl terms with linear lambda dependence will be added
@@ -200,10 +205,12 @@ typedef struct {
   real rvdw_switch,rvdw;
   real bham_b_max;
 
-  /* Free energy */
+  /* Free energy */
   int  efep;
-  real sc_alpha;
+  real sc_alphavdw;
+  real sc_alphacoul;
   int  sc_power;
+  real sc_r_power;
   real sc_sigma6_def;
   real sc_sigma6_min;
   gmx_bool bSepDVDL;
index 20180956454e2c7c6be60d5f4077005e85e9059f..0fa9a1b19fc98c57e91f4697a3f9a7def65fd0d3 100644 (file)
@@ -133,12 +133,19 @@ enum {
   F_VTEMP,
   F_PDISPCORR,
   F_PRES,
+  F_DHDL_CON,
   F_DVDL,
   F_DKDL,
-  F_DHDL_CON,
+  F_DVDL_COUL,
+  F_DVDL_VDW,
+  F_DVDL_BONDED,
+  F_DVDL_RESTRAINT,
+  F_DVDL_TEMPERATURE, /* not calculated for now, but should just be the energy (NVT) or enthalpy (NPT), or 0 (NVE) */
   F_NRE                /* This number is for the total number of energies      */
 };
-  
+
+#define IS_RESTRAINT_TYPE(ifunc) (((ifunc==F_POSRES) || (ifunc==F_DISRES) || (ifunc==F_RESTRBONDS) || (ifunc==F_DISRESVIOL) || (ifunc==F_ORIRES) || (ifunc==F_ORIRESDEV) || (ifunc==F_ANGRES) || (ifunc == F_ANGRESZ) || (ifunc==F_DIHRES)))
+
 typedef union
 {
   /* Some parameters have A and B values for free energy calculations.
@@ -156,7 +163,7 @@ typedef union
   struct {real bm,kb;                                      } fene;
   struct {real r1e,r2e,krr;                                } cross_bb;
   struct {real r1e,r2e,r3e,krt;                            } cross_ba;
-  struct {real theta,ktheta,r13,kUB;                       } u_b;
+  struct {real thetaA,kthetaA,r13A,kUBA,thetaB,kthetaB,r13B,kUBB;} u_b;
   struct {real theta,c[5];                                 } qangle; 
   struct {real alpha;                                      } polarize;
   struct {real alpha,drcut,khyp;                           } anharm_polarize;
@@ -176,15 +183,14 @@ typedef union
    * Use shake (or lincs) instead if you have to change the water bonds.
    */
   struct {real doh,dhh;                                   } settle;
-  /* No free energy supported for morse bonds */ 
-  struct {real b0,cb,beta;                               } morse;
+  struct {real b0A,cbA,betaA,b0B,cbB,betaB;               } morse;
   struct {real pos0A[DIM],fcA[DIM],pos0B[DIM],fcB[DIM];   } posres;
   struct {real rbcA[NR_RBDIHS], rbcB[NR_RBDIHS];          } rbdihs;
   struct {real a,b,c,d,e,f;                               } vsite;   
   struct {int  n; real a;                                 } vsiten;   
   /* NOTE: npair is only set after reading the tpx file */
   struct {real low,up1,up2,kfac;int type,label,npair;     } disres; 
-  struct {real phi,dphi,kfac;int label,power;             } dihres;  
+  struct {real phiA,dphiA,kfacA,phiB,dphiB,kfacB;         } dihres;
   struct {int  ex,power,label; real c,obs,kfac;           } orires;
   struct {int  table;real kA;real kB;                     } tab;
   struct {real sar,st,pi,gbr,bmlt;                        } gb;
index 0b487a46e19b01cda3d63ca9339cdc3bddcf6d74..c7deddf4f7fe7a8106dfc3437513d349b27c7e28 100644 (file)
@@ -121,6 +121,67 @@ typedef struct {
   dvec       f;        /* force due to the pulling/constraining */
 } t_pullgrp; 
 
+typedef struct {
+  int  eSimTempScale;   /* simulated temperature scaling; linear or exponential */
+  real simtemp_low;     /* the low temperature for simulated tempering  */
+  real simtemp_high;    /* the high temperature for simulated tempering */
+  real *temperatures;   /* the range of temperatures used for simulated tempering */
+} t_simtemp;
+
+typedef struct {
+  int  nstdhdl;          /* The frequency for calculating dhdl           */
+  double init_lambda;    /* fractional value of lambda (usually will use init_fep_state, this will only be for slow growth, and for legacy free energy code)   */
+  int init_fep_state;    /* the initial number of the state                   */
+  double delta_lambda;  /* change of lambda per time step (fraction of (0.1) */
+  gmx_bool bPrintEnergy; /* Whether to print the energy in the dhdl           */
+  int  n_lambda;         /* The number of foreign lambda points               */
+  double **all_lambda;   /* The array of all lambda values                    */
+  real sc_alpha;         /* free energy soft-core parameter                   */
+  int  sc_power;         /* lambda power for soft-core interactions           */
+  real sc_r_power;          /* r power for soft-core interactions                */
+  real sc_sigma;         /* free energy soft-core sigma when c6 or c12=0      */
+  real sc_sigma_min;     /* free energy soft-core sigma for ?????             */
+  gmx_bool bScCoul;      /* use softcore for the coulomb portion as well (default FALSE) */
+  gmx_bool separate_dvdl[efptNR]; /* whether to print the dvdl term associated with
+                                     this term; if it is not specified as separate,
+                                     it is lumped with the FEP term */
+  int separate_dhdl_file;    /* whether to write a separate dhdl.xvg file
+                                note: NOT a gmx_bool, but an enum */
+  int  dhdl_derivatives;     /* whether to calculate+write dhdl derivatives
+                                note: NOT a gmx_bool, but an enum */
+  int dh_hist_size;         /* The maximum table size for the dH histogram */
+  double dh_hist_spacing;   /* The spacing for the dH histogram */
+} t_lambda;
+
+typedef struct {
+  int nstexpanded;           /* The frequency of expanded ensemble state changes */
+  int elamstats;             /* which type of move updating do we use for lambda monte carlo (or no for none) */
+  int elmcmove;              /* what move set will be we using for state space moves */
+  int elmceq;                /* the method we use to decide of we have equilibrated the weights */
+  int equil_n_at_lam;        /* the minumum number of samples at each lambda for deciding whether we have reached a minimum */
+  real equil_wl_delta;       /* WL delta at which we stop equilibrating weights */
+  real equil_ratio;          /* use the ratio of weights (ratio of minimum to maximum) to decide when to stop equilibrating */
+  int equil_steps;           /* after equil_steps steps we stop equilibrating the weights */
+  int equil_samples;         /* after equil_samples total samples (steps/nstfep), we stop equilibrating the weights */
+  int lmc_seed;               /* random number seed for lambda mc switches */
+  gmx_bool minvar;               /* whether to use minumum variance weighting */
+  int minvarmin;             /* the number of samples needed before kicking into minvar routine */
+  real minvar_const;         /* the offset for the variance in MinVar */
+  int c_range;               /* range of cvalues used for BAR */
+  gmx_bool bSymmetrizedTMatrix;  /* whether to print symmetrized matrices */
+  int  nstTij;                /* How frequently to print the transition matrices */
+  int  lmc_repeats;          /* number of repetitions in the MC lambda jumps */  /*MRS -- VERIFY THIS */
+  int  lmc_forced_nstart;    /* minimum number of samples for each state before free sampling */ /* MRS -- VERIFY THIS! */
+  int  gibbsdeltalam;        /* distance in lambda space for the gibbs interval */
+  real  wl_scale;            /* scaling factor for wang-landau */
+  real  wl_ratio;            /* ratio between largest and smallest number for freezing the weights */
+  real  init_wl_delta;       /* starting delta for wang-landau */
+  gmx_bool bWLoneovert;      /* use one over t convergece for wang-landau when the delta get sufficiently small */
+  gmx_bool bInit_weights;    /* did we initialize the weights? */
+  real mc_temp;              /* To override the main temperature, or define it if it's not defined */
+  real *init_lambda_weights; /* user-specified initial weights to start with  */
+} t_expanded;
+
 typedef struct {
   int        ngrp;        /* number of groups */
   int        eGeom;       /* pull geometry */
@@ -238,6 +299,7 @@ typedef struct {
   gmx_bool bContinuation;   /* Continuation run: starting state is correct     */
   int  etc;            /* temperature coupling                         */
   int  nsttcouple;      /* interval in steps for temperature coupling   */
+  gmx_bool bPrintNHChains; /* whether to print nose-hoover chains        */
   int  epc;            /* pressure coupling                            */
   int  epct;           /* pressure coupling type                       */
   int  nstpcouple;      /* interval in steps for pressure coupling      */
@@ -247,7 +309,7 @@ typedef struct {
   int  refcoord_scaling;/* How to scale absolute reference coordinates  */
   rvec posres_com;      /* The COM of the posres atoms                  */
   rvec posres_comB;     /* The B-state COM of the posres atoms          */
-  int  andersen_seed;   /* Random seed for Andersen thermostat.         */
+  int  andersen_seed;   /* Random seed for Andersen thermostat (obsolete) */
   real rlist;          /* short range pairlist cut-off (nm)            */
   real rlistlong;      /* long range pairlist cut-off (nm)             */
   real rtpi;            /* Radius for test particle insertion           */
@@ -275,22 +337,12 @@ typedef struct {
   real tabext;          /* Extension of the table beyond the cut-off,   *
                         * as well as the table length for 1-4 interac. */
   real shake_tol;      /* tolerance for shake                          */
-  int  efep;                   /* free energy interpolation no/yes             */
-  double init_lambda;  /* initial value for perturbation variable      */
-  double delta_lambda; /* change of lambda per time step (1/dt)        */
-  int  n_flambda;       /* The number of foreign lambda points          */
-  double *flambda;      /* The foreign lambda values                    */
-  real sc_alpha;        /* free energy soft-core parameter              */
-  int  sc_power;        /* lambda power for soft-core interactions      */
-  real sc_sigma;        /* free energy soft-core sigma when c6 or c12=0 */
-  real sc_sigma_min;    /* minimum FE sc sigma (default: =sg_sigma)     */
-  int  nstdhdl;         /* The frequency for writing to dhdl.xvg        */
-  int  separate_dhdl_file; /* whether to write a separate dhdl.xvg file 
-                              note: NOT a gmx_bool, but an enum */
-  int  dhdl_derivatives;/* whether to calculate+write dhdl derivatives 
-                              note: NOT a gmx_bool, but an enum */
-  int  dh_hist_size;    /* The maximum size for the dH histogram        */
-  double dh_hist_spacing; /* The spacing for the dH histogram           */
+  int  efep;                   /* free energy calculations                     */ 
+  t_lambda *fepvals;    /* Data for the FEP state                       */
+  gmx_bool bSimTemp;    /* Whether to do simulated tempering            */
+  t_simtemp *simtempvals;/* Variables for simulated tempering            */
+  gmx_bool bExpanded;   /* Whether expanded ensembles are used          */
+  t_expanded *expandedvals; /* Expanded ensemble parameters              */
   int  eDisre;          /* Type of distance restraining                 */
   real dr_fc;              /* force constant for ta_disre                      */
   int  eDisreWeighting; /* type of weighting of pairs in one restraints        */
@@ -300,7 +352,7 @@ typedef struct {
   real orires_fc;          /* force constant for orientational restraints  */
   real orires_tau;         /* time constant for memory function in orires      */
   int  nstorireout;     /* frequency of writing tr(SD) to enx           */ 
-  real dihre_fc;        /* force constant for dihedral restraints      */
+  real dihre_fc;        /* force constant for dihedral restraints (obsolete)   */
   real em_stepsize;        /* The stepsize for updating                        */
   real em_tol;             /* The tolerance                            */
   int  niter;           /* Number of iterations for convergence of      */
@@ -363,9 +415,11 @@ typedef struct {
 
 #define IR_EXCL_FORCES(ir) (EEL_FULL((ir).coulombtype) || (EEL_RF((ir).coulombtype) && (ir).coulombtype != eelRF_NEC) || (ir).implicit_solvent != eisNO)
 /* use pointer definitions of ir here, since that's what's usually used in the code */
-#define IR_NVT_TROTTER(ir) ((((ir)->eI == eiVV) || ((ir)->eI == eiVVAK)) && ((ir)->etc == etcNOSEHOOVER))
+#define IR_NPT_TROTTER(ir) ((((ir)->eI == eiVV) || ((ir)->eI == eiVVAK)) && (((ir)->epc == epcMTTK) && ((ir)->etc == etcNOSEHOOVER)))
+
+#define IR_NVT_TROTTER(ir) ((((ir)->eI == eiVV) || ((ir)->eI == eiVVAK)) && ((!((ir)->epc == epcMTTK)) && ((ir)->etc == etcNOSEHOOVER)))
 
-#define IR_NPT_TROTTER(ir) ((((ir)->eI == eiVV) || ((ir)->eI == eiVVAK)) && ((ir)->epc == epcMTTK))
+#define IR_NPH_TROTTER(ir) ((((ir)->eI == eiVV) || ((ir)->eI == eiVVAK)) && (((ir)->epc == epcMTTK) && (!(((ir)->etc == etcNOSEHOOVER)))))
 
 #ifdef __cplusplus
 }
index 4e753e7efe863855fba335cd782cea4d15ff5b86..b4256a1206358a7896607de233d16c2731587450 100644 (file)
@@ -50,22 +50,24 @@ extern "C" {
 
 /* for now, define the length of the NH chains here */
 #define NHCHAINLENGTH 10
+#define MAXLAMBDAS 1024
 
 /* These enums are used in flags as (1<<est...).
  * The order of these enums should not be changed,
  * since that affects the checkpoint (.cpt) file format.
  */
-enum { estLAMBDA,
-       estBOX, estBOX_REL, estBOXV, estPRES_PREV, estNH_XI,  estTC_INT,
-       estX,   estV,       estSDX,  estCGP,       estLD_RNG, estLD_RNGI,
-       estDISRE_INITF, estDISRE_RM3TAV,
-       estORIRE_INITF, estORIRE_DTAV,
-       estSVIR_PREV, estNH_VXI, estVETA, estVOL0, estNHPRES_XI, estNHPRES_VXI,estFVIR_PREV,
-       estNR };
-
-#define EST_DISTR(e) (!(((e) >= estLAMBDA && (e) <= estTC_INT) || ((e) >= estSVIR_PREV && (e) <= estFVIR_PREV)))
-
-/* The names of the state entries, defined in src/gmxib/checkpoint.c */
+  enum { estLAMBDA,
+         estBOX, estBOX_REL, estBOXV, estPRES_PREV, estNH_XI,  estTC_INT,
+         estX,   estV,       estSDX,  estCGP,       estLD_RNG, estLD_RNGI, 
+         estDISRE_INITF, estDISRE_RM3TAV,
+         estORIRE_INITF, estORIRE_DTAV,
+         estSVIR_PREV, estNH_VXI, estVETA, estVOL0, estNHPRES_XI, estNHPRES_VXI, estFVIR_PREV,
+         estFEPSTATE, estMC_RNG, estMC_RNGI,
+         estNR };
+
+#define EST_DISTR(e) (!(((e) >= estLAMBDA && (e) <= estTC_INT) || ((e) >= estSVIR_PREV && (e) <= estMC_RNGI)))
+
+/* The names of the state entries, defined in src/gmxlib/checkpoint.c */
 extern const char *est_names[estNR];
 
 typedef struct
@@ -113,6 +115,29 @@ typedef struct
                                   For backward-compatibility. */
 } delta_h_history_t; 
 
+typedef struct
+{
+  int nlambda;               /* total number of lambda states - for history*/
+
+  gmx_bool bEquil;           /* reached equilibration */
+  int  *n_at_lam;            /* number of points observed at each lambda */
+  real *wl_histo;            /* histogram for WL flatness determination */
+  real wl_delta;             /* current wang-landau delta */
+
+  real *sum_weights;         /* weights of the states */
+  real *sum_dg;              /* free energies of the states -- not actually used for weighting, but informational */
+  real *sum_minvar;          /* corrections to weights for minimum variance */
+  real *sum_variance;        /* variances of the states */
+
+  real **accum_p;            /* accumulated bennett weights for n+1 */
+  real **accum_m;            /* accumulated bennett weights for n-1 */
+  real **accum_p2;           /* accumulated squared bennett weights for n+1 */
+  real **accum_m2;           /* accumulated squared bennett weights for n-1 */
+
+  real **Tij;                /* transition matrix */
+  real **Tij_empirical;      /* Empirical transition matrix */
+} df_history_t;
+
 typedef struct
 {
   gmx_large_int_t nsteps;       /* The number of steps in the history            */
@@ -133,11 +158,12 @@ typedef struct
   int           natoms;
   int           ngtc;
   int           nnhpres;
-  int           nhchainlength; /* length of each nose-hoover chain      */
+  int           nhchainlength; /* number of nose-hoover chains               */
   int           nrng;
   int           nrngi;
   int           flags;  /* Flags telling which entries are present      */
-  real          lambda; /* the free energy switching parameter          */
+  int           fep_state; /* indicates which of the alchemical states we are in                 */
+  real          *lambda; /* lambda vector                               */
   matrix       box;    /* box vector coordinates                       */
   matrix       box_rel; /* Relitaive box vectors to preserve shape     */
   matrix       boxv;   /* box velocitites for Parrinello-Rahman pcoupl */
@@ -160,12 +186,17 @@ typedef struct
   unsigned int  *ld_rng;  /* RNG random state                           */
   int           *ld_rngi; /* RNG index                                  */
 
+  int           nmcrng;   /* number of RNG states                       */
+  unsigned int  *mc_rng;  /* lambda MC RNG random state                 */
+  int           *mc_rngi; /* lambda MC RNG index                        */
+
   history_t     hist;   /* Time history for restraints                  */
 
   ekinstate_t   ekinstate; /* The state of the kinetic energy data      */
 
   energyhistory_t  enerhist; /* Energy history for statistics           */
-       
+  df_history_t  dfhist; /*Free energy history for free energy analysis  */
+
   int           ddp_count; /* The DD partitioning count for this state  */
   int           ddp_count_cg_gl; /* The DD part. count for index_gl     */
   int           ncg_gl; /* The number of local charge groups            */
index 8661ce228e402c66a6594b30ca5f1edb0f83ae51..85239578099ee54383cc81f0d936ecfc0f68c04e 100644 (file)
@@ -69,7 +69,9 @@ typedef struct trxframe
   gmx_bool bTime;
   real time;      /* time of the frame                */
   gmx_bool bLambda;
+  gmx_bool bFepState; /* does it contain fep_state?       */
   real lambda;    /* free energy perturbation lambda  */
+  int  fep_state; /* which fep state are we in? */
   gmx_bool bAtoms;
   t_atoms *atoms; /* atoms struct (natoms)            */
   gmx_bool bPrec;
index 618fda7cbebb01e40030d9f41e7be690d4a5282c..4f8ae204a20ace64548e9e62cb822066f86518a9 100644 (file)
@@ -110,6 +110,8 @@ void update_coords(FILE         *fplog,
 
 /* Return TRUE if OK, FALSE in case of Shake Error */
 
+extern gmx_bool update_randomize_velocities(t_inputrec *ir, gmx_large_int_t step, t_mdatoms *md, t_state *state, gmx_update_t upd, t_idef *idef, gmx_constr_t constr);
+
 void update_constraints(FILE         *fplog,
                               gmx_large_int_t   step,
                               real         *dvdlambda, /* FEP stuff */
@@ -168,6 +170,7 @@ void calc_ke_part(t_state *state,t_grpopts *opts,t_mdatoms *md,
  *
  */
 
+
 void
 init_ekinstate(ekinstate_t *ekinstate,const t_inputrec *ir);
 
@@ -180,6 +183,8 @@ restore_ekinstate_from_state(t_commrec *cr,
 
 void berendsen_tcoupl(t_inputrec *ir,gmx_ekindata_t *ekind,real dt);
 
+void andersen_tcoupl(t_inputrec *ir,t_mdatoms *md,t_state *state, gmx_rng_t rng, real rate, t_idef *idef, int nblocks, int *sblock,gmx_bool *randatom, int *randatom_list, gmx_bool *randomize, real *boltzfac);
+
 void nosehoover_tcoupl(t_grpopts *opts,gmx_ekindata_t *ekind,real dt,
                              double xi[],double vxi[],t_extmass *MassQ);
 
diff --git a/share/README_FreeEnergyModifications.txt b/share/README_FreeEnergyModifications.txt
new file mode 100644 (file)
index 0000000..347b43d
--- /dev/null
@@ -0,0 +1,254 @@
+======== GROMACS 4.5 Free Energy Modifications ===================
+
+New with this version:
+
+- coulombic, vdw, bonded, and restraint transformation lambdas all decoupled
+  from each other -- any specified pathway can be taken.
+- extended ensemble MC, with a number of different move choices
+- Supports either fixed weights, or dynamically adjusted weights
+- free energy dependent dihedral, angle, and distance restraints
+
+=== BASIC DOCUMENTATION ===
+
+Important options that may have changed behavior in this version: --
+defaults listed first, other options in [ ], then parenthetical
+comments.
+
+free-energy              = no [yes,mutate,decouple]
+
+lmc-stats            = no [metropolis-transition,barker-transition,wang-landau,gibbs-wang-landau,minvar]  (the
+method used to update the weights)
+
+nst-transition-matrix    = 0 [nonnegativeinteger] frequency at which the transition-matrix is output to the log
+lmc-mc-move          = gibbs [metropolis,barker,gibbs,metropolized-gibbs] (the method used to for lambda MC moves)
+
+lmc-seed                 = -1 [for lambda mc transformations, -1 means it's taken from the process number]
+mc-temperature          = [positive real] [If omitted, set to the same as the ref_t for the 0th system, if there is one]
+
+lmc-gibbsdelta          = -1 [any integer] (the interval [lambda-1,lambda+1] for moves for gibbs sampling on the lambdas.  -1,
+the default, means the entire interval [0,1] will be sampled)
+
+initial-wl-delta        = 1.0 [any positive real] (the initial delta factor for Wang-Landau, in kT)
+wl-scale                = 0.8 [real between 0 and 1] (the scaling factor for Wang-Landau)
+wl-ratio                = 0.8 [real between 0 and 1] ratio of lowest to highest occupancies for Wang-Landau being seen as flat)    
+symmetrized-transition-matrix=no [yes/no]  Whether to compute a symmetrized version of the transition matrix, by averaging the transpose with the matrix.
+
+lmc-forced-nstart       = 0 [any positive integer] (the number of equilibration steps at each lambda when 
+                           'forcing through', essentially peforming slow growth, to initialize weights
+
+mininum-var-min        = 100 [any positive integer] must have this many samples in each state before reweighting to 
+                                get the number of states per state that minimizes variace.  Preferable to make it 
+                         something decent so that it the initial weights don't get swallowed up in noise, 
+                        as it is using an asymptotic theory.
+
+weight-c-range          = 0 when using minvar, uses the C that is closest to the G*(ln n0/n1).  
+                         0 means it defaults to C=0. Otherwise, it computes the free energies 
+                         along +/- c-range, with kT spacing.  Should eventually be used for 
+                          BAR as well.
+
+lmc-weights-equil       = no [weight-equil-wl-delta,weight-equil-number-all-lambda,weight-equil-number-steps,weight-equil-number-samples,weight-equil-count-ratio]
+                        The condition to set when we stop updating the weights and start to equilibrate.
+
+lmc-weights-equil       = no [wl-delta,number-all-lambda,number-steps,number-samples,count-ratio]
+weight-equil-wl-delta           =  [positive real] stop when wl-delta drops below this value, if lmc-weights-equil  = wl-delta
+weight-equil-number-all-lambda  =  [positive integer] stop when we've got this number of samples at all lambda, if lmc-weights-equil  = number-all-lambda
+weight-equil-number-steps       =  [positive integer] stop when we've done this number of steps, if lmc-weights-equil  = number-steps
+weight-equil-number-samples     =  [positive integer] stop when we've done this number of samples, if lmc-weights-equil  = number-samples
+weight-equil-count-ratio        =  [positive real] stop when the ratio of min to max value is greater than this, if lmc-weights-equil  = count-ratio
+
+fep-lambdas         = 0.0 0.2 0.3 0.4 0.5 0.6 0.7 0.8 1.0 (array of lambdas)
+mass-lambdas        = 0.0 0.2 0.3 0.4 0.5 0.6 0.7 0.8 1.0 (array of lambdas)
+coul-lambdas        = 0.0 0.2 0.3 0.4 0.5 0.6 0.7 0.8 1.0 (array of lambdas)
+vdw-lambdas         = 0.0 0.2 0.3 0.4 0.5 0.6 0.7 0.8 1.0 (array of lambdas)
+bonded-lambdas      = 0.0 0.2 0.3 0.4 0.5 0.6 0.7 0.8 1.0 (array of lambdas)
+restraint-lambdas   = 0.0 0.2 0.3 0.4 0.5 0.6 0.7 0.8 1.0 (array of lambdas)
+init-lambda-weights = 0.0 0.2 0.3 0.4 0.5 0.6 0.7 0.8 1.0 (initial weights for each lambda)
+
+sc-alpha            = 0.5  [any positive real] (soft core alpha - now, only operates on vdw)
+sc-coul             = no [yes/no] -  Controls whether coulomb is also softocore 
+
+nstfep              = 20 [any integer multiple of nlist] (the
+frequency at which the other energies are determined, and the lambdas are updated.
+nstdgdl             = 200 [any integer multiple of nstfep] (the rate at which
+the dE terms are output to the dgdl file, per step)
+dhdl-print-energy   = Whether to print the energies as well as the energy differences (helps for some analysis codes --
+                      for example, required when doing umbrella sampling with different temperatures)
+Notes on non-self-explanatory terms:
+
+Weight methods:
+*barker-transition -- computes <alpha>_forward/<alpha>_reverse, with
+alpha being the Fermi function.  Like Bennett, but without self
+consistent iteration.  More efficient than metropolis transition
+*metropolis-transition, same as above but with the Metropolis function
+(min{1,exp(dE}) instead of the Fermi function
+*wang-landau- implements standard wang-landau
+*gibbs-wang-landau -- uses p(k)delta for nonlocal updating of weights, instead of delta
+*mbar.  Highly experimental, recommend against using.
+*minvar - optimizes the number of samples at each states with weights that lower the variance, as described
+by Escobedo (ref #???)
+
+weight-equilibration criteria options:
+
+*weight-equil-wl-delta - stop when wl-delta drops below this value set in 'weight-equil-wl-delta'.
+*weight-equil-number-all-lambda - stop when all the lambdas are equal or greater than 'weight-equil-number-all-lambda'
+*weight-equil-number-steps - stop when we've done the number of steps set in 'weight-equil-number-steps'
+*weight-equil-number-samples - stop when we've done the number of samples set in 'weight-equil-number-samples'
+*weight-equil-count-ratio - stop when the ratio of top to bottom value is greater than the value set in 'weight-equil-count-ratio'
+
+wl-ratio -- For Wang-Landau, scaling is done when everything is
+within mc-ratio of the mean.
+
+Right now, nstfep must be an integer multiple of nslist -- this can
+possibly be fixed later.  For now, since we update all the other
+energies every nstfep steps, it probably would be too slow if done
+more frequently.  Previously, I though if it was too fast, you could
+get an unlucky run to an unstable configuration, if it does not
+equilibrate the momenta at the new level.  I think I fixed a bug that
+was causing this problem.  It might be possible to go down to 10,
+though at that point, the cost starts to be large (takes about 20%
+longer with nstfep = 10 vs. 20 in my sample system).
+
+This does bring up a point that perhaps for strict detailed balance, the
+momenta need to be resampled from a Boltzmann distribution at each
+transition.  This would slow down dynamics a lot, though -- is it
+necessary for complete detailed balance?  (Answer seems to be that if 
+the velocity distribution function is equal in both states, as it is
+if the temperature is the same for both, then we're OK).
+
+fep-lambdas is the default lambda array.  All the other four lambda
+arrays (except the serial tempering temperatures) use the values in
+this array if they are not specified.  If not specificed, it is
+assumed to be zero throughout.
+
+For example, if you wanted to first to change coul, then vdw, while
+changing bonded at the same time as vdw, but the restraints throughout
+the first two thirds of the simulation, then you'd do something like:
+
+init-lambda-state      = 0
+coul-lambdas           = 0.0 0.2 0.5 1.0 1.0 1.0 1.0 1.0 1.0 1.0
+vdw-lambdas            = 0.0 0.0 0.0 0.0 0.4 0.5 0.6 0.7 0.8 1.0
+bonded-lambdas         = 0.0 0.0 0.0 0.0 0.4 0.5 0.6 0.7 0.8 1.0
+restraint-lambdas      = 0.0 0.0 0.1 0.2 0.3 0.5 0.7 1.0 1.0 1.0
+
+This is equivalent to:
+
+init-lambda-state      = 0 
+fep-lambdas            = 0.0 0.0 0.0 0.0 0.4 0.5 0.6 0.7 0.8 1.0
+coul-lambdas           = 0.0 0.2 0.5 1.0 1.0 1.0 1.0 1.0 1.0 1.0
+restraint-lambdas      = 0.0 0.0 0.1 0.2 0.3 0.5 0.7 1.0 1.0 1.0
+
+The fep-lambda array, in this case, is being used as the default to
+fill in the bonded and vdw lambda arrays.  Usually, it's best to fill
+in all array explicitly, just to make sure things are properly
+assigned.
+
+If you want to turn on only restraints going from A to B, then it would be:
+
+init-lambda-state      = 1
+restraint-lambdas      = 0.0 0.1 0.2 0.4 0.6 1.0
+
+The current weights are written out to the logfile every nstlog steps,
+in units of kT.
+
+You can load in weights using init-lambda-weights.  Use 0.00 for the first
+(zero because it's the reference) entries, then the rest of the weights,
+like:
+
+init-lambda-weights =  0.00  0.54  1.45 3.45 6.78
+
+However, most of the update methods don't do a good job with using
+given weights if there is no data added in previously.  So, it's best
+to use this for entering the weights for a subsequent equilibrium
+simulation.  I'll try to figure out if there is a better way.
+
+Make sure you make the spacing in lambda sufficiently close.  It needs
+to be close in order to have good overlap.  I'd keep the free energy
+between states less that 5 kT or so, perhaps more like 2-3 kT.
+
+ ============ Coding ====================
+
+The expanded ensemble changes (other than keeping track of global
+variables) are almost mostly contained in src/mdlib/sim_util.c, with
+additional changes in readir.c and mdebin.c
+
+Things that would be nice to address:
+
+  -nstdgdl not necessarily a multiple of nslist (especially with nstlist = -1)
+Test to do:
+
+ - throw a number of systems on to find an bugs.
+
+Let me know if there is anything else I should be adding. . .
+
+There's a very large number combinations of different parameters and
+approaches that could be adjusted in order to study what works best.
+
+======== Implementation Notes====
+
+I'm still playing around trying to figure out the best combination of
+methods to use.  If the weights are poor, equilibration to a flat
+histogram in weights can be very slow.  Right now, I think that the
+Gibbs Wang-Landau method might be the fastest to equilibrate for less
+overlap.  In the limit of large numbers of samples, it probably
+doesn't matter very much.  
+
+
+======Notes on topologies for restraints=======
+******This section is old, and may have some issues *****
+For distance and dihedral restraints, you need entries like this in
+the mdp -- for angle restraints, you don't.  This is a strange gromacs
+convention.
+
+Dihedral restraint entries look like this -- note the A->B state, the
+A state and the B state (last two commented).
+
+[ dihedral_restraints ]
+;  i    j    k    l type label power phiA dphiA  kfacA  phiB  dphiB   kfacB
+;mixed state
+1410 1393 1391 2610    1     0     2    38    0    0.00     38     0    41.84
+1393 1391 2610 2604    1     1     2   111    0    0.00    111     0    41.84
+1391 2610 2604 2606    1     2     2   -39    0    0.00    -39     0    41.84
+; zero state
+;1410 1393 1391 2610    1     0     2   38    0    0.00
+;1393 1391 2610 2604    1     1     2  111    0    0.00
+;1391 2610 2604 2606    1     2     2  -39    0    0.00
+; one state
+;1410 1393 1391 2610    1     0     2   38    0   41.84
+;1393 1391 2610 2604    1     1     2  111    0   41.84
+;1391 2610 2604 2606    1     2     2  -39    0   41.84
+
+Free energy dependent angle restraints look like this:
+
+[ angle_restraints ]
+;  i    j    k    l type theta0A fcA mult  theta0B    fcB
+;mixed state  -- need to have MULT listed twice!!!
+1393 1391 2610 1391    1   62      0.0  1     62    41.84    1
+1391 2610 2604 2610    1   79      0.0  1     79    41.84    1
+; zero state
+;1393 1391 2610 1391   1   62      0.0  1
+;1391 2610 2604 2610   1   79      0.0  1
+; one state
+;1393 1391 2610 1391   1   62    41.84  1
+;1391 2610 2604 2610   1   79    41.84  1
+
+Note particularly that even though the multiplicity can't actually be
+changed in free energy perturbation, you need to have the multiplicity
+listed in both the A and B states.  This is a strange effect of using
+proper dihedral codes to do the angle restraints -- I tried to find a
+way to fix it, but gave up after a few hours -- it works using this
+topology framework.
+
+Free energy dependent harmonic distance restraints are implemented as
+follows -- R2 is a ridiculously large number in order to obtain purely
+harmonic restraints -- otherwise, it becomes linear outside of R2.
+
+[ distance_restraints ]
+;  i    j type label typeprime    r0A   r1A   r2A    fcA  r0B   r1B
+r2B      fcB
+;mixed state
+1391 2610     1     0         1   0.61  0.61   10.0     0.0  0.61  0.61 10.0  4184.0 ;zero state
+;1391 2610    1     0         1   0.61  0.61   10.0     0.0 ;one state
+;1391 2610    1     0         1   0.61  0.61    0.81 4184.0
+
+
index b04e15650046497842fc0846b8579e01c789b7c7..d2c6b065d11854f6b3be9a80031d00c963e0b9e9 100644 (file)
@@ -88,7 +88,16 @@ difference is calculated dF = -kT ln &lt; e ^ -(EB-EA)/kT &gt;A ,
 where EA and EB are the energies from the first and second energy
 files, and the average is over the ensemble A. <b>NOTE</b> that
 the energies must both be calculated from the same trajectory.
+Generally, this estimate is not particularly accurate unless the
+state is very similar to the ideal gas state (i.e. the potential energies
+are very low), and more accurate free energy calculations can be performed
+using the free energy features.
 <P>
+<p><tt>-odh</tt>Regenerates the dhdl.xvg from the .edr file if the separate-dhdl-file
+is chosen as no in the .mdp file the .edr was generated from. This can allow more
+flexiblity in scripting as the additional dhdl.xvg file does not need to be handled
+until the analysis phase.  It can also save some space by avoiding the presence of a large ASCII file.
+<p>
 <H3>Files</H3>
 <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=2>
 <TR><TH>option</TH><TH>filename</TH><TH>type</TH><TH>description</TH></TR>
@@ -104,6 +113,7 @@ the energies must both be calculated from the same trajectory.
 <TR><TD ALIGN=RIGHT> <b><tt>-odr</tt></b> </TD><TD ALIGN=RIGHT> <tt><a href="xvg.html"> oridevr.xvg</a></tt> </TD><TD> Output, Opt. </TD><TD> xvgr/xmgr file </TD></TR>
 <TR><TD ALIGN=RIGHT> <b><tt>-odt</tt></b> </TD><TD ALIGN=RIGHT> <tt><a href="xvg.html"> oridevt.xvg</a></tt> </TD><TD> Output, Opt. </TD><TD> xvgr/xmgr file </TD></TR>
 <TR><TD ALIGN=RIGHT> <b><tt>-oten</tt></b> </TD><TD ALIGN=RIGHT> <tt><a href="xvg.html">  oriten.xvg</a></tt> </TD><TD> Output, Opt. </TD><TD> xvgr/xmgr file </TD></TR>
+<TR><TD ALIGN=RIGHT> <b><tt>-odh</tt></b> </TD><TD ALIGN=RIGHT> <tt><a href="xvg.html">  dhdl.xvg</a></tt> </TD><TD> Output, Opt. </TD><TD> xvgr/xmgr file </TD></TR>
 <TR><TD ALIGN=RIGHT> <b><tt>-corr</tt></b> </TD><TD ALIGN=RIGHT> <tt><a href="xvg.html"> enecorr.xvg</a></tt> </TD><TD> Output, Opt. </TD><TD> xvgr/xmgr file </TD></TR>
 <TR><TD ALIGN=RIGHT> <b><tt>-vis</tt></b> </TD><TD ALIGN=RIGHT> <tt><a href="xvg.html">   visco.xvg</a></tt> </TD><TD> Output, Opt. </TD><TD> xvgr/xmgr file </TD></TR>
 <TR><TD ALIGN=RIGHT> <b><tt>-ravg</tt></b> </TD><TD ALIGN=RIGHT> <tt><a href="xvg.html">runavgdf.xvg</a></tt> </TD><TD> Output, Opt. </TD><TD> xvgr/xmgr file </TD></TR>
index bf9057abd752b8279fe8e2f7bb6c62908d676d88..179398cf08e4e0c34a5d85ba23d884f1f32fcd17 100644 (file)
@@ -51,7 +51,8 @@ IF YOU'RE NOT SURE ABOUT WHAT YOU'RE DOING, DON'T DO IT!
 wall-density, wall-ewald-zfac)
 <li><A HREF="#pull"><b>COM pulling</b></A> (pull, ...)
 <li><A HREF="#nmr"><b>NMR refinement</b></A> (disre, disre-weighting, disre-mixed, disre-fc, disre-tau, nstdisreout, orire, orire-fc, orire-tau, orire-fitgrp, nstorireout)
-<li><A HREF="#free"><b>Free Energy calculations</b></A> (free-energy, init-lambda, delta-lambda, sc-alpha, sc-power, sc-sigma, couple-moltype, couple-lambda0, couple-lambda1, couple-intramol)
+<li><A HREF="#free"><b>Free energy calculations</b></A> (free-energy, nstfep, nstdgdl, dhdl-print-energy, init-lambda, delta-lambda, fep-lambdas, coul-lambdas, vdw-lambdas, bonded-lambdas, restraint-lambdas, mass-lambdas, sc-alpha, sc-coul, sc-power, sc-r-power, sc-sigma, couple-moltype, couple-lambda0, couple-lambda1, couple-intramol)
+<li><A HREF="#free"><b>Expanded ensemble simulation</b></A> (lmc-stats, lmc-mc-move, lmc-seed, lmc-gibbsdelta, mc-temperature, nst-transition-matrix,init-lambda-weights,initial-wl-delta,wl-scale,wl-ratio,symmetrized-transition-matrix,lmc-forced-nstart,weight-c-range,mininum-var-min,lmc-weights-equil,weight-equil-wl-delta,weight-equil-number-all-lambda,weight-equil-number-steps,weight-equil-number-samples,weight-equil-count-ratio,simulated-tempering,simulated-tempering-scaling,sim-temp-low,sim-temp-high)
 <li><A HREF="#neq"><b>Non-equilibrium MD</b></A> (acc-grps, accelerate, freezegrps, freezedim, cos-acceleration, deform)
 <li><A HREF="#ef"><b>Electric fields</b></A> (E-x, E-xt, E-y, E-yt, E-z, E-zt )
 <li><A HREF="#qmmm"><b>Mixed quantum/classical dynamics</b></A> (QMMM, QMMM-grps, QMMMscheme, QMmethod, QMbasis, QMcharge, Qmmult, CASorbitals, CASelectrons, SH)
@@ -1379,19 +1380,52 @@ described in the manual. When <b>sc-alpha</b> is larger than zero, soft-core
 potentials are used for the LJ and Coulomb interactions.</dd>
 </dl></dd>
 <dt><b>init-lambda: (0)</b></dt>
-<dd>starting value for lambda</dd>
+<dd>starting value for lambda (float).  Generally, this should only be used with slow growth.  In other cases, <b>init-lambda-state</b> should be specified instead.</dd>
+<dt><b>init-lambda-state: (0)</b></dt>
+<dd>starting value for the lambda state (integer).  Specified which columm of the lambda vector should be used.</dd>
 <dt><b>delta-lambda: (0)</b></dt>
 <dd>increment per time step for lambda</dd>
-<dt><b>foreign-lambda: ()</b></dt>
+<dt><b>coul-lambdas: ()</b></dt>
+<dd>Zero, one or more lambda values for which Delta H values will
+be determined and written to dhdl.xvg every <b>nstdhdl</b> steps.
+Only the electrostatic interactions are controlled with this component of the lambda vector.</dd>
+<dt><b>vdw-lambdas: ()</b></dt>
+<dd>Zero, one or more lambda values for which Delta H values will
+be determined and written to dhdl.xvg every <b>nstdhdl</b> steps.
+Only the van der Waals interactions are controlled with this component of the lambda vector.</dd>
+<dt><b>bonded-lambdas: ()</b></dt>
+<dd>Zero, one or more lambda values for which Delta H values will
+be determined and written to dhdl.xvg every <b>nstdhdl</b> steps.
+Only the bonded interactions are controlled with this component of the lambda vector.</dd>
+<dt><b>restraint-lambdas: ()</b></dt>
+<dd>Zero, one or more lambda values for which Delta H values will
+be determined and written to dhdl.xvg every <b>nstdhdl</b> steps.
+Only the restraint interactions are controlled with this component of the lambda vector.</dd>
+<dt><b>mass-lambdas: ()</b></dt>
+<dd>Zero, one or more lambda values for which Delta H values will
+be determined and written to dhdl.xvg every <b>nstdhdl</b> steps.
+Only the particle masses are controlled with this component of the lambda vector.</dd>
+<dt><b>temperature-lambdas: ()</b></dt>
+<dd>Zero, one or more lambda values for which Delta H values will
+be determined and written to dhdl.xvg every <b>nstdhdl</b> steps.
+Only the temperatures controlled with this component of the lambda vector.
+Note that these lambdas should not be used for replica exchange, only for simulated tempering.</dd>
+<dt><b>fep-lambdas: ()</b></dt>
 <dd>Zero, one or more lambda values for which Delta H values will
 be determined and written to dhdl.xvg every <b>nstdhdl</b> steps.
 Free energy differences between different lambda values can then
-be determined with <tt>g_bar</tt>.</dd>
+be determined with <tt>g_bar</tt>. <b>fep-lambdas</b> is different from the other -lambdas keywords because
+all components of the lambda vector that are not specified will use <b>fep-lambdas</b>.</dd>
 <dt><b>dhdl-derivatives: (yes)</b></dt>
 <dd>If yes (the default), the derivatives of the Hamiltonian with respect to lambda at each <b>nstdhdl</b> step are written out. These values are needed for interpolation of linear energy differences with <tt>g_bar</tt> (although the same can also be achieved with the right <b>foreign lambda</b> setting, that may not be as flexible), or with thermodynamic integration</dd>
 <dt><b>sc-alpha: (0)</b></dt>
 <dd>the soft-core parameter, a value of 0 results in linear interpolation of
 the LJ and Coulomb interactions</dd>
+<dt><b>sc-r-power: (6)</b></dt>
+<dd>the power of the radial term in the soft-core equation.  Possible values are 6 and 48. 6 is more standard, and is the default.  When 48 is used, then sc-alpha should generally be much lower (between 0.001 and 0.003).</dd>
+<dt><b>sc-coul: (no)</b></dt>
+<dd>Whether to apply the soft core free energy interations to the Columbic interaction. Default is no, as it is generally
+more efficient to turn of the Coulomic interactions linearly before turning off electrostatic interactions.</dd>
 <dt><b>sc-power: (0)</b></dt>
 <dd>the power for lambda in the soft-core function,
 only the values 1 and 2 are supported</dd>
@@ -1432,7 +1466,9 @@ the molecule definition in the topology.</dd>
 </dl>
 <dt><b>nstdhdl: (10)</b></dt>
 <dd>the frequency for writing dH/dlambda and possibly Delta H to dhdl.xvg,
-0 means no ouput, should be a multiple of <b>nstcalcenergy</b></dd>
+0 means no ouput, should be a multiple of <b>nstcalcenergy</b>and <b>nstfep</b></dd>
+<dt><b>nstfep: (10)</b></dt>
+<dd>the frequency at which energies at other values of lambda are calculated.  If not specified, set to be the same as <b>nstdhdl</b>. Should be a multiple of <b>nstcalcenergy</b>.  If replica exchange is chosen, then -replex must also be a multiple of <b>nstfep</b></dd>
 <dt><b>separate-dhdl-file: (yes)</b></dt>
 <dd><dl compact>
 <dt><b>yes</b></dt>
@@ -1445,7 +1481,73 @@ the molecule definition in the topology.</dd>
 <dt><b>dh-hist-spacing (0.1)</b></dt>
 <dd>Specifies the bin width of the histograms, in energy units. Used in conjunction with <b>dh-hist-size</b>. This size limits the accuracy with which free energies can be calculated.  Do not use histograms unless you're certain you need it.</dd>
 </dl>
+<A NAME="expanded"><br>
+<hr>
+<h3><!--Idx-->Expanded Ensemble calculations<!--EIdx--></h3>
+
+<dl>
+<dt><b>nstexpanded</b></dt> The frequency to peform expanded ensemble
+simulations.  Must be a multiple of <b>nstfep</b>.
+<dt><b>lmc-stats:</b></dt>
+<dd><dl compact>
+<dt><b>no</b></dt>
+<dd>No Monte Carlo in state space</dd>
+<dt><b>metropolis-transition</b></dt>
+<dd> Uses the Metropolis weights to update the expanded ensemble weight of the state.
+Min{1,exp(-(beta_new u_new - beta_old u_old)}</dd>
+<dt><b>barker-transition</b></dt>
+<dd> Uses the Barker transition critera to update the expanded ensemble weight of the state.</dd>
+<dt><b>wang-landau</b></dt>
+<dd>Uses the Wang-Landau algorithm (in state space) to update the expanded ensemble weights.</dd>
+<dt><b>min-variance</b></dt>
+<dd>Uses the minimum variance updating method of Escobedo et al to update the expanded ensemble weights. Weights
+will not be the free energies, but will rather emphasize states that need more sampling to give even uncertainty.
+</dl>
+<dt><b>lmc-mc-move:</b></dt>
+<dd><dl compact>
+<dt><b>no</b></dt>
+<dd>No Monte Carlo in state space is performed.</dd>
+<dt><b>metropolis-transition</b></dt>
+<dd> Randomly chooses a new state up or down, then uses the Metropolis critera to decide whether to accept or reject:
+Min{1,exp(-(beta_new u_new - beta_old u_old)}</dd>
+<dt><b>barker-transition</b></dt>
+<dd> Randomly chooses a new state up or down, then uses the Barker transition critera to decide whether to accept or reject: exp(-beta_new u_new)/[exp(-beta_new u_new)+exp(-beta_old u_old)] </dd>
+<dt><b>gibbs</b></dt>
+<dd> Uses the conditional weights of the state given the coordinate (exp(-beta_i u_i) / sum_k exp(beta_i u_i) to
+decide which state to move to.</dd>
+<dt><b>metropolized-gibbs</b></dt>
+<dd>
+<dd> Uses the conditional weights of the state given the coordinate (exp(-beta_i u_i) / sum_k exp(beta_i u_i) to
+decide which state to move to, EXCLUDING the current state, then uses a rejection step to ensure detailed
+balance. Always more efficient that Gibbs, though marginally so in many situations.</dd>
+</dl>
 
+<dt><b>lmc-seed:</b></dt>
+<dd> random seed to use for Monte Carlo moves in state space.  If not specified, <b>ld-seed</b> is used instead. </dd>
+<dt><b>mc-temperature:</b></dt>
+<dd> Temperature used for acceptance/rejection for Monte Carlo moves. If not specified, the temperature of the
+simulation specified in the first group of <b>ref_t</b> is used.</dd>
+
+<dt><b>wl-scale: (0.8)</b></dt>
+<dt><b>wl-ratio: (0.8)</b></dt>
+<dt><b>init-wl-delta: (1.0) </b></dt>
+<dt><b>wl-oneovert: (no) </b></dt>
+<dt><b>lmc-repeats: (1)</b></dt>
+<dt><b>lmc-gibbsdelta: (-1) </b></dt>
+<dt><b>lmc-forced-nstart: (0) </b></dt>
+<dt><b>nst-transition-matrix: (-1)</b></dt>
+<dd>Frequency of outputting the expanded ensemble transition matrix.  A negative number means it will only be printed at the end of the simulation.<dd>
+<dt><b>symmetrized-transition-matrix: (no) </b></dt>
+<dd>Whether to symmetrize the empirical transition matrix</dd>
+<dt><b>mininum-var-min</b></dt>
+<dt><b>weight-c-range</b></dt>
+
+<dt><b>simulated-tempering: (no)</b></dt>
+<dt><b>simulated-tempering-scaling: ()</b></dt>
+<dt><b>sim-temp-low: (300):</b></dt>
+<dd>Low temperature for simulated tempering</dd>
+<dt><b>sim-temp-high: (300):</b></dt>
+<dd>High temperature for simulated tempering</dd>
 
 <A NAME="neq"><br>
 <hr>
index fc9e7a9f914a9fbc7fa8c6ecd38342991cb9d7f7..f0dfc5c72cb6abe54d5884752e3697ea340c4471 100644 (file)
@@ -156,7 +156,9 @@ or orientation restraints are present these can be ensemble averaged
 over all the systems.<p>
 With <tt>-replex</tt> replica exchange is attempted every given number
 of steps. The number of replicas is set with the <tt>-multi</tt> option,
-see above.
+see above. The <tt>-nex</tt> option turns on Gibbs sampling replica exchange. N^3, where
+N is the number of replicas indicated by <tt>-multi</tt> appears to work relatively well.
+
 All run input files should use a different coupling temperature,
 the order of the files is not important. The random seed is set with
 <tt>-reseed</tt>. The velocities are scaled and neighbor searching
@@ -286,6 +288,7 @@ When mdrun is started with MPI, it does not run niced by default.
 <TR><TD ALIGN=RIGHT> <b><tt>-maxh</tt></b> </TD><TD ALIGN=RIGHT> real </TD><TD ALIGN=RIGHT> <tt>-1    </tt> </TD><TD> Terminate after 0.99 times this time (hours) </TD></TD>
 <TR><TD ALIGN=RIGHT> <b><tt>-multi</tt></b> </TD><TD ALIGN=RIGHT> int </TD><TD ALIGN=RIGHT> <tt>0</tt> </TD><TD> Do multiple simulations in parallel </TD></TD>
 <TR><TD ALIGN=RIGHT> <b><tt>-replex</tt></b> </TD><TD ALIGN=RIGHT> int </TD><TD ALIGN=RIGHT> <tt>0</tt> </TD><TD> Attempt replica exchange every # steps </TD></TD>
+<TR><TD ALIGN=RIGHT> <b><tt>-nex</tt></b> </TD><TD ALIGN=RIGHT> int </TD><TD ALIGN=RIGHT> <tt>0</tt> </TD><TD> Attempt $N$ Gibbs sampling replica exchanges at every exchange interval. $N^3$ is a suggested frequency. </TD></TD>
 <TR><TD ALIGN=RIGHT> <b><tt>-reseed</tt></b> </TD><TD ALIGN=RIGHT> int </TD><TD ALIGN=RIGHT> <tt>-1</tt> </TD><TD> Seed for replica exchange, -1 is generate a seed </TD></TD>
 <TR><TD ALIGN=RIGHT> <b><tt>-[no]ionize</tt></b> </TD><TD ALIGN=RIGHT> gmx_bool </TD><TD ALIGN=RIGHT> <tt>no    </tt> </TD><TD> Do a simulation including the effect of an X-Ray bombardment on your system </TD></TD>
 </TABLE>
index 7f70a27256a55dd48c8127a42a0449f80f9ad8d4..789702a9ca51df7399bf6131f9e392b73c1e8f3f 100644 (file)
@@ -120,13 +120,14 @@ real morse_bonds(int nbonds,
                 const t_iatom forceatoms[],const t_iparams forceparams[],
                 const rvec x[],rvec f[],rvec fshift[],
                 const t_pbc *pbc,const t_graph *g,
-                real lambda,real *dvdl,
+                real lambda,real *dvdlambda,
                 const t_mdatoms *md,t_fcdata *fcd,
                 int *global_atom_index)
 {
   const real one=1.0;
   const real two=2.0;
-  real  dr,dr2,temp,omtemp,cbomtemp,fbond,vbond,fij,b0,be,cb,vtot;
+  real  dr,dr2,temp,omtemp,cbomtemp,fbond,vbond,fij,vtot;
+  real  b0,be,cb,b0A,beA,cbA,b0B,beB,cbB,L1;
   rvec  dx;
   int   i,m,ki,type,ai,aj;
   ivec  dt;
@@ -137,9 +138,18 @@ real morse_bonds(int nbonds,
     ai   = forceatoms[i++];
     aj   = forceatoms[i++];
     
-    b0   = forceparams[type].morse.b0;
-    be   = forceparams[type].morse.beta;
-    cb   = forceparams[type].morse.cb;
+    b0A   = forceparams[type].morse.b0A;
+    beA   = forceparams[type].morse.betaA;
+    cbA   = forceparams[type].morse.cbA;
+
+    b0B   = forceparams[type].morse.b0B;
+    beB   = forceparams[type].morse.betaB;
+    cbB   = forceparams[type].morse.cbB;
+
+    L1 = one-lambda;                      /* 1 */
+    b0 = L1*b0A + lambda*b0B;             /* 3 */
+    be = L1*beA + lambda*beB;             /* 3 */
+    cb = L1*cbA + lambda*cbB;             /* 3 */
 
     ki   = pbc_rvec_sub(pbc,x[ai],x[aj],dx);            /*   3          */
     dr2  = iprod(dx,dx);                            /*   5          */
@@ -147,13 +157,19 @@ real morse_bonds(int nbonds,
     temp = exp(-be*(dr-b0));                        /*  12          */
     
     if (temp == one)
-      continue;
+    {
+        /* bonds are constrainted. This may _not_ include bond constraints if they are lambda dependent */
+        *dvdlambda = cbB-cbA;
+        continue;
+    }
 
     omtemp   = one-temp;                               /*   1          */
     cbomtemp = cb*omtemp;                              /*   1          */
     vbond    = cbomtemp*omtemp;                        /*   1          */
-    fbond    = -two*be*temp*cbomtemp*gmx_invsqrt(dr2);      /*   9          */
-    vtot    += vbond;       /* 1 */
+    fbond    = -two*be*temp*cbomtemp*gmx_invsqrt(dr2); /*   9          */
+    vtot     += vbond;                                 /*   1          */
+
+    *dvdlambda += (cbB - cbA) * omtemp * omtemp - (2-2*omtemp)*omtemp * cb * ((b0B-b0A)*be - (beB-beA)*(dr-b0)); /* 15 */
     
     if (g) {
       ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
@@ -167,7 +183,7 @@ real morse_bonds(int nbonds,
       fshift[ki][m]+=fij;
       fshift[CENTRAL][m]-=fij;
     }
-  }                                           /*  58 TOTAL    */
+  }                                           /*  83 TOTAL    */
   return vtot;
 }
 
@@ -175,7 +191,7 @@ real cubic_bonds(int nbonds,
                 const t_iatom forceatoms[],const t_iparams forceparams[],
                 const rvec x[],rvec f[],rvec fshift[],
                 const t_pbc *pbc,const t_graph *g,
-                real lambda,real *dvdl,
+                real lambda,real *dvdlambda,
                 const t_mdatoms *md,t_fcdata *fcd,
                 int *global_atom_index)
 {
@@ -232,7 +248,7 @@ real FENE_bonds(int nbonds,
                const t_iatom forceatoms[],const t_iparams forceparams[],
                const rvec x[],rvec f[],rvec fshift[],
                const t_pbc *pbc,const t_graph *g,
-               real lambda,real *dvdl,
+               real lambda,real *dvdlambda,
                const t_mdatoms *md,t_fcdata *fcd,
                int *global_atom_index)
 {
@@ -295,24 +311,24 @@ real harmonic(real kA,real kB,real xA,real xB,real x,real lambda,
 {
   const real half=0.5;
   real  L1,kk,x0,dx,dx2;
-  real  v,f,dvdl;
+  real  v,f,dvdlambda;
   
   L1    = 1.0-lambda;
   kk    = L1*kA+lambda*kB;
   x0    = L1*xA+lambda*xB;
-  
+
   dx    = x-x0;
   dx2   = dx*dx;
-  
+
   f     = -kk*dx;
   v     = half*kk*dx2;
-  dvdl  = half*(kB-kA)*dx2 + (xA-xB)*kk*dx;
-  
+  dvdlambda  = half*(kB-kA)*dx2 + (xA-xB)*kk*dx;
+
   *F    = f;
   *V    = v;
-  
-  return dvdl;
-  
+
+  return dvdlambda;
+
   /* That was 19 flops */
 }
 
@@ -341,10 +357,10 @@ real bonds(int nbonds,
     dr   = dr2*gmx_invsqrt(dr2);                       /*  10          */
 
     *dvdlambda += harmonic(forceparams[type].harmonic.krA,
-                          forceparams[type].harmonic.krB,
-                          forceparams[type].harmonic.rA,
-                          forceparams[type].harmonic.rB,
-                          dr,lambda,&vbond,&fbond);  /*  19  */
+                           forceparams[type].harmonic.krB,
+                           forceparams[type].harmonic.rA,
+                           forceparams[type].harmonic.rB,
+                           dr,lambda,&vbond,&fbond);  /*  19  */
 
     if (dr2 == 0.0)
       continue;
@@ -871,13 +887,12 @@ real linear_angles(int nbonds,
 {
   int  i,m,ai,aj,ak,t1,t2,type;
   rvec f_i,f_j,f_k;
-  real L1,kA,kB,aA,aB,dr,dr2,va,vtot,a,b,klin,dvdl;
+  real L1,kA,kB,aA,aB,dr,dr2,va,vtot,a,b,klin;
   ivec jt,dt_ij,dt_kj;
   rvec r_ij,r_kj,r_ik,dx;
     
   L1   = 1-lambda;
   vtot = 0.0;
-  dvdl = 0.0;
   for(i=0; (i<nbonds); ) {
     type = forceatoms[i++];
     ai   = forceatoms[i++];
@@ -911,7 +926,7 @@ real linear_angles(int nbonds,
         f[ak][m] += f_k[m];
     }
     va    = 0.5*klin*dr2;
-    dvdl += 0.5*(kB-kA)*dr2 + klin*(aB-aA)*iprod(dx,r_ik); 
+    *dvdlambda += 0.5*(kB-kA)*dr2 + klin*(aB-aA)*iprod(dx,r_ik); 
             
     vtot += va;
     
@@ -927,7 +942,6 @@ real linear_angles(int nbonds,
     rvec_inc(fshift[CENTRAL],f_j);
     rvec_inc(fshift[t2],f_k);
   }                                           /* 57 TOTAL      */
-  *dvdlambda = dvdl;
   return vtot;
 }
 
@@ -942,7 +956,8 @@ real urey_bradley(int nbonds,
   int  i,m,ai,aj,ak,t1,t2,type,ki;
   rvec r_ij,r_kj,r_ik;
   real cos_theta,cos_theta2,theta;
-  real dVdt,va,vtot,kth,th0,kUB,r13,dr,dr2,vbond,fbond,fik;
+  real dVdt,va,vtot,dr,dr2,vbond,fbond,fik;
+  real kthA,th0A,kUBA,r13A,kthB,th0B,kUBB,r13B;
   ivec jt,dt_ij,dt_kj,dt_ik;
   
   vtot = 0.0;
@@ -951,22 +966,26 @@ real urey_bradley(int nbonds,
     ai   = forceatoms[i++];
     aj   = forceatoms[i++];
     ak   = forceatoms[i++];
-    th0  = forceparams[type].u_b.theta*DEG2RAD;
-    kth  = forceparams[type].u_b.ktheta;
-    r13  = forceparams[type].u_b.r13;
-    kUB  = forceparams[type].u_b.kUB;
+    th0A  = forceparams[type].u_b.thetaA*DEG2RAD;
+    kthA  = forceparams[type].u_b.kthetaA;
+    r13A  = forceparams[type].u_b.r13A;
+    kUBA  = forceparams[type].u_b.kUBA;
+    th0B  = forceparams[type].u_b.thetaB*DEG2RAD;
+    kthB  = forceparams[type].u_b.kthetaB;
+    r13B  = forceparams[type].u_b.r13B;
+    kUBB  = forceparams[type].u_b.kUBB;
     
     theta  = bond_angle(x[ai],x[aj],x[ak],pbc,
                        r_ij,r_kj,&cos_theta,&t1,&t2);  /*  41          */
   
-    *dvdlambda += harmonic(kth,kth,th0,th0,theta,lambda,&va,&dVdt);  /*  21  */
+    *dvdlambda += harmonic(kthA,kthB,th0A,th0B,theta,lambda,&va,&dVdt);  /*  21  */
     vtot += va;
     
     ki   = pbc_rvec_sub(pbc,x[ai],x[ak],r_ik); /*   3          */
     dr2  = iprod(r_ik,r_ik);                   /*   5          */
     dr   = dr2*gmx_invsqrt(dr2);                       /*  10          */
 
-    *dvdlambda += harmonic(kUB,kUB,r13,r13,dr,lambda,&vbond,&fbond); /*  19  */
+    *dvdlambda += harmonic(kUBA,kUBB,r13A,r13B,dr,lambda,&vbond,&fbond); /*  19  */
 
     cos_theta2 = sqr(cos_theta);                /*   1         */
     if (cos_theta2 < 1) {
@@ -1201,7 +1220,7 @@ void do_dih_fup(int i,int j,int k,int l,real ddphi,
 real dopdihs(real cpA,real cpB,real phiA,real phiB,int mult,
             real phi,real lambda,real *V,real *F)
 {
-  real v,dvdl,mdphi,v1,sdphi,ddphi;
+  real v,dvdlambda,mdphi,v1,sdphi,ddphi;
   real L1   = 1.0 - lambda;
   real ph0  = (L1*phiA + lambda*phiB)*DEG2RAD;
   real dph0 = (phiB - phiA)*DEG2RAD;
@@ -1213,12 +1232,12 @@ real dopdihs(real cpA,real cpB,real phiA,real phiB,int mult,
   v1    = 1.0 + cos(mdphi);
   v     = cp*v1;
   
-  dvdl  = (cpB - cpA)*v1 + cp*dph0*sdphi;
+  dvdlambda  = (cpB - cpA)*v1 + cp*dph0*sdphi;
   
   *V = v;
   *F = ddphi;
   
-  return dvdl;
+  return dvdlambda;
   
   /* That was 40 flops */
 }
@@ -1228,7 +1247,7 @@ static real dopdihs_min(real cpA,real cpB,real phiA,real phiB,int mult,
      /* similar to dopdihs, except for a minus sign  *
       * and a different treatment of mult/phi0       */
 {
-  real v,dvdl,mdphi,v1,sdphi,ddphi;
+  real v,dvdlambda,mdphi,v1,sdphi,ddphi;
   real L1   = 1.0 - lambda;
   real ph0  = (L1*phiA + lambda*phiB)*DEG2RAD;
   real dph0 = (phiB - phiA)*DEG2RAD;
@@ -1240,12 +1259,12 @@ static real dopdihs_min(real cpA,real cpB,real phiA,real phiB,int mult,
   v1    = 1.0-cos(mdphi);
   v     = cp*v1;
   
-  dvdl  = (cpB-cpA)*v1 + cp*dph0*sdphi;
+  dvdlambda  = (cpB-cpA)*v1 + cp*dph0*sdphi;
   
   *V = v;
   *F = ddphi;
   
-  return dvdl;
+  return dvdlambda;
   
   /* That was 40 flops */
 }
@@ -1274,13 +1293,12 @@ real pdihs(int nbonds,
     
     phi=dih_angle(x[ai],x[aj],x[ak],x[al],pbc,r_ij,r_kj,r_kl,m,n,
                   &sign,&t1,&t2,&t3);                  /*  84          */
-
     *dvdlambda += dopdihs(forceparams[type].pdihs.cpA,
-                         forceparams[type].pdihs.cpB,
-                         forceparams[type].pdihs.phiA,
-                         forceparams[type].pdihs.phiB,
-                         forceparams[type].pdihs.mult,
-                         phi,lambda,&vpd,&ddphi);
+                          forceparams[type].pdihs.cpB,
+                          forceparams[type].pdihs.phiA,
+                          forceparams[type].pdihs.phiB,
+                          forceparams[type].pdihs.mult,
+                          phi,lambda,&vpd,&ddphi);
 
     vtot += vpd;
     do_dih_fup(ai,aj,ak,al,ddphi,r_ij,r_kj,r_kl,m,n,
@@ -1295,6 +1313,19 @@ real pdihs(int nbonds,
   return vtot;
 }
 
+void make_dp_periodic(real *dp)  /* 1 flop? */
+{
+    /* dp cannot be outside (-pi,pi) */
+    if (*dp >= M_PI)
+    {
+        *dp -= 2*M_PI;
+    }
+    else if (*dp < -M_PI)
+    {
+        *dp += 2*M_PI;
+    }
+    return;
+}
 
 
 real idihs(int nbonds,
@@ -1309,11 +1340,10 @@ real idihs(int nbonds,
   int  t1,t2,t3;
   real phi,phi0,dphi0,ddphi,sign,vtot;
   rvec r_ij,r_kj,r_kl,m,n;
-  real L1,kk,dp,dp2,kA,kB,pA,pB,dvdl;
+  real L1,kk,dp,dp2,kA,kB,pA,pB,dvdl_term;
 
   L1 = 1.0-lambda;
-  dvdl = 0;
-
+  dvdl_term = 0;
   vtot = 0.0;
   for(i=0; (i<nbonds); ) {
     type = forceatoms[i++];
@@ -1341,24 +1371,20 @@ real idihs(int nbonds,
     phi0  = (L1*pA + lambda*pB)*DEG2RAD;
     dphi0 = (pB - pA)*DEG2RAD;
 
-    /* dp = (phi-phi0), modulo (-pi,pi) */
     dp = phi-phi0;  
-    /* dp cannot be outside (-2*pi,2*pi) */
-    if (dp >= M_PI)
-      dp -= 2*M_PI;
-    else if(dp < -M_PI)
-      dp += 2*M_PI;
+
+    make_dp_periodic(&dp);
     
     dp2 = dp*dp;
 
     vtot += 0.5*kk*dp2;
     ddphi = -kk*dp;
     
-    dvdl += 0.5*(kB - kA)*dp2 - kk*dphi0*dp;
+    dvdl_term += 0.5*(kB - kA)*dp2 - kk*dphi0*dp;
 
     do_dih_fup(ai,aj,ak,al,(real)(-ddphi),r_ij,r_kj,r_kl,m,n,
               f,fshift,pbc,g,x,t1,t2,t3);                      /* 112          */
-    /* 217 TOTAL       */
+    /* 218 TOTAL       */
 #ifdef DEBUG
     if (debug)
       fprintf(debug,"idih: (%d,%d,%d,%d) phi=%g\n",
@@ -1366,7 +1392,7 @@ real idihs(int nbonds,
 #endif
   }
   
-  *dvdlambda += dvdl;
+  *dvdlambda += dvdl_term;
   return vtot;
 }
 
@@ -1384,6 +1410,11 @@ real posres(int nbonds,
     real vtot,kk,fm;
     real posA,posB,ref=0;
     rvec comA_sc,comB_sc,rdist,dpdl,pos,dx;
+    gmx_bool bForceValid = TRUE;
+
+    if ((f==NULL) || (vir_diag==NULL)) {  /* should both be null together! */
+        bForceValid = FALSE;
+    }
 
     npbcdim = ePBC2npbcdim(ePBC);
 
@@ -1471,14 +1502,16 @@ real posres(int nbonds,
         {
             kk          = L1*pr->posres.fcA[m] + lambda*pr->posres.fcB[m];
             fm          = -kk*dx[m];
-            f[ai][m]   += fm;
             vtot       += 0.5*kk*dx[m]*dx[m];
             *dvdlambda +=
                 0.5*(pr->posres.fcB[m] - pr->posres.fcA[m])*dx[m]*dx[m]
                 -fm*dpdl[m];
 
             /* Here we correct for the pbc_dx which included rdist */
-            vir_diag[m] -= 0.5*(dx[m] + rdist[m])*fm;
+            if (bForceValid) {
+                f[ai][m]   += fm;
+                vir_diag[m] -= 0.5*(dx[m] + rdist[m])*fm;
+            }
         }
     }
 
@@ -1522,11 +1555,11 @@ static real low_angres(int nbonds,
     phi     = acos(cos_phi);                    /* 10           */
 
     *dvdlambda += dopdihs_min(forceparams[type].pdihs.cpA,
-                             forceparams[type].pdihs.cpB,
-                             forceparams[type].pdihs.phiA,
-                             forceparams[type].pdihs.phiB,
-                             forceparams[type].pdihs.mult,
-                             phi,lambda,&vid,&dVdphi); /*  40  */
+                              forceparams[type].pdihs.cpB,
+                              forceparams[type].pdihs.phiA,
+                              forceparams[type].pdihs.phiB,
+                              forceparams[type].pdihs.mult,
+                              phi,lambda,&vid,&dVdphi); /*  40  */
     
     vtot += vid;
 
@@ -1593,7 +1626,101 @@ real angresz(int nbonds,
             int *global_atom_index)
 {
   return low_angres(nbonds,forceatoms,forceparams,x,f,fshift,pbc,g,
-                   lambda,dvdlambda,TRUE);
+                    lambda,dvdlambda,TRUE);
+}
+
+real dihres(int nbonds,
+            const t_iatom forceatoms[],const t_iparams forceparams[],
+            const rvec x[],rvec f[],rvec fshift[],
+            const t_pbc *pbc,const t_graph *g,
+            real lambda,real *dvdlambda,
+            const t_mdatoms *md,t_fcdata *fcd,
+            int *global_atom_index)
+{
+    real vtot = 0;
+    int  ai,aj,ak,al,i,k,type,t1,t2,t3;
+    real phi0A,phi0B,dphiA,dphiB,kfacA,kfacB,phi0,dphi,kfac;
+    real phi,ddphi,ddp,ddp2,dp,sign,d2r,fc,L1;
+    rvec r_ij,r_kj,r_kl,m,n;
+
+    L1 = 1.0-lambda;
+
+    d2r = DEG2RAD;
+    k   = 0;
+
+    for (i=0; (i<nbonds); )
+    {
+        type = forceatoms[i++];
+        ai   = forceatoms[i++];
+        aj   = forceatoms[i++];
+        ak   = forceatoms[i++];
+        al   = forceatoms[i++];
+
+        phi0A  = forceparams[type].dihres.phiA*d2r;
+        dphiA  = forceparams[type].dihres.dphiA*d2r;
+        kfacA  = forceparams[type].dihres.kfacA;
+
+        phi0B  = forceparams[type].dihres.phiB*d2r;
+        dphiB  = forceparams[type].dihres.dphiB*d2r;
+        kfacB  = forceparams[type].dihres.kfacB;
+
+        phi0  = L1*phi0A + lambda*phi0B;
+        dphi  = L1*dphiA + lambda*dphiB;
+        kfac = L1*kfacA + lambda*kfacB;
+
+        phi = dih_angle(x[ai],x[aj],x[ak],x[al],pbc,r_ij,r_kj,r_kl,m,n,
+                        &sign,&t1,&t2,&t3);
+        /* 84 flops */
+
+        if (debug)
+        {
+            fprintf(debug,"dihres[%d]: %d %d %d %d : phi=%f, dphi=%f, kfac=%f\n",
+                    k++,ai,aj,ak,al,phi0,dphi,kfac);
+        }
+        /* phi can jump if phi0 is close to Pi/-Pi, which will cause huge
+         * force changes if we just apply a normal harmonic.
+         * Instead, we first calculate phi-phi0 and take it modulo (-Pi,Pi).
+         * This means we will never have the periodicity problem, unless
+         * the dihedral is Pi away from phiO, which is very unlikely due to
+         * the potential.
+         */
+        dp = phi-phi0;
+        make_dp_periodic(&dp);
+
+        if (dp > dphi)
+        {
+            ddp = dp-dphi;
+        }
+        else if (dp < -dphi)
+        {
+            ddp = dp+dphi;
+        }
+        else
+        {
+            ddp = 0;
+        }
+
+        if (ddp != 0.0)
+        {
+            ddp2 = ddp*ddp;
+            vtot += 0.5*kfac*ddp2;
+            ddphi = kfac*ddp;
+
+            *dvdlambda += 0.5*(kfacB - kfacA)*ddp2;
+            /* lambda dependence from changing restraint distances */
+            if (ddp > 0)
+            {
+                *dvdlambda -= kfac*ddp*((dphiB - dphiA)+(phi0B - phi0A));
+            }
+            else if (ddp < 0)
+            {
+                *dvdlambda += kfac*ddp*((dphiB - dphiA)-(phi0B - phi0A));
+            }
+            do_dih_fup(ai,aj,ak,al,ddphi,r_ij,r_kj,r_kl,m,n,
+                       f,fshift,pbc,g,x,t1,t2,t3);             /* 112          */
+        }
+    }
+    return vtot;
 }
 
 
@@ -1629,7 +1756,7 @@ real rbdihs(int nbonds,
   real v,sign,ddphi,sin_phi;
   real cosfac,vtot;
   real L1   = 1.0-lambda;
-  real dvdl=0;
+  real dvdl_term=0;
 
   vtot = 0.0;
   for(i=0; (i<nbonds); ) {
@@ -1662,7 +1789,7 @@ real rbdihs(int nbonds,
     /* Calculate the derivative */
 
     v       = parm[0];
-    dvdl   += (parmB[0]-parmA[0]);
+    dvdl_term   += (parmB[0]-parmA[0]);
     ddphi   = c0;
     cosfac  = c1;
     
@@ -1671,31 +1798,31 @@ real rbdihs(int nbonds,
     ddphi  += rbp*cosfac;
     cosfac *= cos_phi;
     v      += cosfac*rbp;
-    dvdl   += cosfac*rbpBA;
+    dvdl_term   += cosfac*rbpBA;
     rbp     = parm[2];
     rbpBA   = parmB[2]-parmA[2];    
     ddphi  += c2*rbp*cosfac;
     cosfac *= cos_phi;
     v      += cosfac*rbp;
-    dvdl   += cosfac*rbpBA;
+    dvdl_term   += cosfac*rbpBA;
     rbp     = parm[3];
     rbpBA   = parmB[3]-parmA[3];
     ddphi  += c3*rbp*cosfac;
     cosfac *= cos_phi;
     v      += cosfac*rbp;
-    dvdl   += cosfac*rbpBA;
+    dvdl_term   += cosfac*rbpBA;
     rbp     = parm[4];
     rbpBA   = parmB[4]-parmA[4];
     ddphi  += c4*rbp*cosfac;
     cosfac *= cos_phi;
     v      += cosfac*rbp;
-    dvdl   += cosfac*rbpBA;
+    dvdl_term   += cosfac*rbpBA;
     rbp     = parm[5];
     rbpBA   = parmB[5]-parmA[5];
     ddphi  += c5*rbp*cosfac;
     cosfac *= cos_phi;
     v      += cosfac*rbp;
-    dvdl   += cosfac*rbpBA;
+    dvdl_term   += cosfac*rbpBA;
    
     ddphi = -ddphi*sin_phi;                            /*  11          */
     
@@ -1703,7 +1830,7 @@ real rbdihs(int nbonds,
               f,fshift,pbc,g,x,t1,t2,t3);              /* 112          */
     vtot += v;
   }  
-  *dvdlambda += dvdl;
+  *dvdlambda += dvdl_term;
 
   return vtot;
 }
@@ -1787,7 +1914,7 @@ real cmap_dihs(int nbonds,
        ivec jt2,dt2_ij,dt2_kj,dt2_lj;
 
     const real *cmapd;
-       
+
        int loop_index[4][4] = {
                {0,4,8,12},
                {1,5,9,13},
@@ -1811,7 +1938,7 @@ real cmap_dihs(int nbonds,
                /* Which CMAP type is this */
                cmapA = forceparams[type].cmap.cmapA;
         cmapd = cmap_grid->cmapdata[cmapA].cmap;
-               
+
                /* First torsion */
                a1i   = ai;
                a1j   = aj;
@@ -1967,7 +2094,7 @@ real cmap_dihs(int nbonds,
                pos2    = ip1p1*cmap_grid->grid_spacing+iphi2;
                pos3    = ip1p1*cmap_grid->grid_spacing+ip2p1;
                pos4    = iphi1*cmap_grid->grid_spacing+ip2p1;
-               
+
                ty[0]   = cmapd[pos1*4];
                ty[1]   = cmapd[pos2*4];
                ty[2]   = cmapd[pos3*4];
@@ -2166,7 +2293,7 @@ real g96harmonic(real kA,real kB,real xA,real xB,real x,real lambda,
 {
   const real half=0.5;
   real  L1,kk,x0,dx,dx2;
-  real  v,f,dvdl;
+  real  v,f,dvdlambda;
   
   L1    = 1.0-lambda;
   kk    = L1*kA+lambda*kB;
@@ -2177,12 +2304,12 @@ real g96harmonic(real kA,real kB,real xA,real xB,real x,real lambda,
   
   f     = -kk*dx;
   v     = half*kk*dx2;
-  dvdl  = half*(kB-kA)*dx2 + (xA-xB)*kk*dx;
+  dvdlambda  = half*(kB-kA)*dx2 + (xA-xB)*kk*dx;
   
   *F    = f;
   *V    = v;
   
-  return dvdl;
+  return dvdlambda;
   
   /* That was 21 flops */
 }
@@ -2210,10 +2337,10 @@ real g96bonds(int nbonds,
     dr2  = iprod(dx,dx);                               /*   5          */
       
     *dvdlambda += g96harmonic(forceparams[type].harmonic.krA,
-                             forceparams[type].harmonic.krB,
-                             forceparams[type].harmonic.rA,
-                             forceparams[type].harmonic.rB,
-                             dr2,lambda,&vbond,&fbond);
+                              forceparams[type].harmonic.krB,
+                              forceparams[type].harmonic.rA,
+                              forceparams[type].harmonic.rB,
+                              dr2,lambda,&vbond,&fbond);
 
     vtot  += 0.5*vbond;                             /* 1*/
 #ifdef DEBUG
@@ -2277,10 +2404,10 @@ real g96angles(int nbonds,
     cos_theta  = g96bond_angle(x[ai],x[aj],x[ak],pbc,r_ij,r_kj,&t1,&t2);
 
     *dvdlambda += g96harmonic(forceparams[type].harmonic.krA,
-                             forceparams[type].harmonic.krB,
-                             forceparams[type].harmonic.rA,
-                             forceparams[type].harmonic.rB,
-                             cos_theta,lambda,&va,&dVdt);
+                              forceparams[type].harmonic.krB,
+                              forceparams[type].harmonic.rA,
+                              forceparams[type].harmonic.rB,
+                              cos_theta,lambda,&va,&dVdt);
     vtot    += va;
     
     rij_1    = gmx_invsqrt(iprod(r_ij,r_ij));
@@ -2476,7 +2603,7 @@ static real bonded_tab(const char *type,int table_nr,
 {
   real k,tabscale,*VFtab,rt,eps,eps2,Yt,Ft,Geps,Heps2,Fp,VV,FF;
   int  n0,nnn;
-  real v,f,dvdl;
+  real v,f,dvdlambda;
 
   k = (1.0 - lambda)*kA + lambda*kB;
 
@@ -2502,9 +2629,9 @@ static real bonded_tab(const char *type,int table_nr,
   
   *F    = -k*FF*tabscale;
   *V    = k*VV;
-  dvdl  = (kB - kA)*VV;
+  dvdlambda  = (kB - kA)*VV;
   
-  return dvdl;
+  return dvdlambda;
   
   /* That was 22 flops */
 }
@@ -2535,10 +2662,10 @@ real tab_bonds(int nbonds,
     table = forceparams[type].tab.table;
 
     *dvdlambda += bonded_tab("bond",table,
-                            &fcd->bondtab[table],
-                            forceparams[type].tab.kA,
-                            forceparams[type].tab.kB,
-                            dr,lambda,&vbond,&fbond);  /*  22 */
+                             &fcd->bondtab[table],
+                             forceparams[type].tab.kA,
+                             forceparams[type].tab.kB,
+                             dr,lambda,&vbond,&fbond);  /*  22 */
 
     if (dr2 == 0.0)
       continue;
@@ -2592,10 +2719,10 @@ real tab_angles(int nbonds,
     table = forceparams[type].tab.table;
   
     *dvdlambda += bonded_tab("angle",table,
-                            &fcd->angletab[table],
-                            forceparams[type].tab.kA,
-                            forceparams[type].tab.kB,
-                            theta,lambda,&va,&dVdt);  /*  22  */
+                             &fcd->angletab[table],
+                             forceparams[type].tab.kA,
+                             forceparams[type].tab.kB,
+                             theta,lambda,&va,&dVdt);  /*  22  */
     vtot += va;
     
     cos_theta2 = sqr(cos_theta);                /*   1         */
@@ -2672,10 +2799,10 @@ real tab_dihs(int nbonds,
 
     /* Hopefully phi+M_PI never results in values < 0 */
     *dvdlambda += bonded_tab("dihedral",table,
-                            &fcd->dihtab[table],
-                            forceparams[type].tab.kA,
-                            forceparams[type].tab.kB,
-                            phi+M_PI,lambda,&vpd,&ddphi);
+                             &fcd->dihtab[table],
+                             forceparams[type].tab.kA,
+                             forceparams[type].tab.kB,
+                             phi+M_PI,lambda,&vpd,&ddphi);
                       
     vtot += vpd;
     do_dih_fup(ai,aj,ak,al,-ddphi,r_ij,r_kj,r_kl,m,n,
@@ -2690,178 +2817,291 @@ real tab_dihs(int nbonds,
   return vtot;
 }
 
-void calc_bonds(FILE *fplog,const gmx_multisim_t *ms,
-               const t_idef *idef,
-               rvec x[],history_t *hist,
-               rvec f[],t_forcerec *fr,
-               const t_pbc *pbc,const t_graph *g,
-               gmx_enerdata_t *enerd,t_nrnb *nrnb,
-               real lambda,
-               const t_mdatoms *md,
-               t_fcdata *fcd,int *global_atom_index,
-               t_atomtypes *atype, gmx_genborn_t *born,
-               gmx_bool bPrintSepPot,gmx_large_int_t step)
+real calc_one_bond(FILE *fplog,int ftype, const t_idef *idef,
+                   rvec x[], rvec f[], t_forcerec *fr,
+                   const t_pbc *pbc,const t_graph *g,
+                   gmx_enerdata_t *enerd, t_nrnb *nrnb,
+                   real *lambda, real *dvdl,
+                   const t_mdatoms *md,t_fcdata *fcd,
+                   int *global_atom_index, gmx_bool bPrintSepPot)
 {
-  int    ftype,nbonds,ind,nat1;
-  real   *epot,v,dvdl;
-  const  t_pbc *pbc_null;
-  char   buf[22];
+    int ind,nat1,nbonds,efptFTYPE;
+    real v=0;
+    t_iatom *iatoms;
 
-  if (fr->bMolPBC)
-    pbc_null = pbc;
-  else
-    pbc_null = NULL;
+    if (IS_RESTRAINT_TYPE(ftype))
+    {
+        efptFTYPE = efptRESTRAINT;
+    }
+    else
+    {
+        efptFTYPE = efptBONDED;
+    }
 
-  if (bPrintSepPot)
-    fprintf(fplog,"Step %s: bonded V and dVdl for this node\n",
-           gmx_step_str(step,buf));
+    if (ftype<F_GB12 || ftype>F_GB14)
+    {
+        if (interaction_function[ftype].flags & IF_BOND &&
+            !(ftype == F_CONNBONDS || ftype == F_POSRES))
+        {
+            ind  = interaction_function[ftype].nrnb_ind;
+            nat1 = interaction_function[ftype].nratoms+1;
+            nbonds    = idef->il[ftype].nr;
+            iatoms    = idef->il[ftype].iatoms;
+            if (nbonds > 0)
+            {
+                if (ftype < F_LJ14 || ftype > F_LJC_PAIRS_NB)
+                {
+                    if(ftype==F_CMAP)
+                    {
+                        v = cmap_dihs(nbonds,iatoms,
+                                      idef->iparams,&idef->cmap_grid,
+                                      (const rvec*)x,f,fr->fshift,
+                                      pbc,g,lambda[efptFTYPE],&(dvdl[efptFTYPE]),
+                                      md,fcd,global_atom_index);
+                    }
+                    else
+                    {
+                        v =        interaction_function[ftype].ifunc(nbonds,iatoms,
+                                                                  idef->iparams,
+                                                                  (const rvec*)x,f,fr->fshift,
+                                                                  pbc,g,lambda[efptFTYPE],&(dvdl[efptFTYPE]),
+                                                                  md,fcd,global_atom_index);
+                    }
+                    enerd->dvdl_nonlin[efptFTYPE] += dvdl[efptFTYPE];
+                    if (bPrintSepPot)
+                    {
+                        fprintf(fplog,"  %-23s #%4d  V %12.5e  dVdl %12.5e\n",
+                                interaction_function[ftype].longname,
+                                nbonds/nat1,v,lambda[efptFTYPE]);
+                    }
+                }
+                else
+                {
+                    v = do_listed_vdw_q(ftype,nbonds,iatoms,
+                                        idef->iparams,
+                                        (const rvec*)x,f,fr->fshift,
+                                        pbc,g,lambda,dvdl,
+                                        md,fr,&enerd->grpp,global_atom_index);
+                    enerd->dvdl_nonlin[efptCOUL] += dvdl[efptCOUL];
+                    enerd->dvdl_nonlin[efptVDW] += dvdl[efptVDW];
+
+                    if (bPrintSepPot)
+                    {
+                        fprintf(fplog,"  %-5s + %-15s #%4d                  dVdl %12.5e\n",
+                                interaction_function[ftype].longname,
+                                interaction_function[F_LJ14].longname,nbonds/nat1,dvdl[efptVDW]);
+                        fprintf(fplog,"  %-5s + %-15s #%4d                  dVdl %12.5e\n",
+                                interaction_function[ftype].longname,
+                                interaction_function[F_COUL14].longname,nbonds/nat1,dvdl[efptCOUL]);
+                    }
+                }
+                if (ind != -1)
+                {
+                    inc_nrnb(nrnb,ind,nbonds/nat1);
+                }
+            }
+        }
+    }
+    return v;
+}
+
+/* WARNING!  THIS FUNCTION MUST EXACTLY TRACK THE calc_one_bond
+   function, or horrible things will happen when doing free energy
+   calculations!  In a good coding world, this would not be a
+   different function, but for speed reasons, it needs to be made a
+   separate function.  TODO for 5.0 - figure out a way to reorganize
+   to reduce duplication.
+*/
+
+real calc_one_bond_foreign(FILE *fplog,int ftype, const t_idef *idef,
+                           rvec x[], rvec f[], t_forcerec *fr,
+                           const t_pbc *pbc,const t_graph *g,
+                           gmx_enerdata_t *enerd, t_nrnb *nrnb,
+                           real *lambda, real *dvdl,
+                           const t_mdatoms *md,t_fcdata *fcd,
+                           int *global_atom_index, gmx_bool bPrintSepPot)
+{
+    int ind,nat1,nbonds,efptFTYPE,nbonds_np;
+    real v=0;
+    t_iatom *iatoms;
+
+    if (IS_RESTRAINT_TYPE(ftype))
+    {
+        efptFTYPE = efptRESTRAINT;
+    }
+    else
+    {
+        efptFTYPE = efptBONDED;
+    }
+
+    if (ftype<F_GB12 || ftype>F_GB14)
+    {
+        if (interaction_function[ftype].flags & IF_BOND &&
+            !(ftype == F_CONNBONDS || ftype == F_POSRES))
+        {
+            ind  = interaction_function[ftype].nrnb_ind;
+            nat1 = interaction_function[ftype].nratoms+1;
+            nbonds_np = idef->il[ftype].nr_nonperturbed;
+            nbonds    = idef->il[ftype].nr - nbonds_np;
+            iatoms    = idef->il[ftype].iatoms + nbonds_np;
+            if (nbonds > 0)
+            {
+                if (ftype < F_LJ14 || ftype > F_LJC_PAIRS_NB)
+                {
+                    if(ftype==F_CMAP)
+                    {
+                        v = cmap_dihs(nbonds,iatoms,
+                                      idef->iparams,&idef->cmap_grid,
+                                      (const rvec*)x,f,fr->fshift,
+                                      pbc,g,lambda[efptFTYPE],&(dvdl[efptFTYPE]),md,fcd,
+                                      global_atom_index);
+                    }
+                    else
+                    {
+                        v =        interaction_function[ftype].ifunc(nbonds,iatoms,
+                                                                  idef->iparams,
+                                                                  (const rvec*)x,f,fr->fshift,
+                                                                  pbc,g,lambda[efptFTYPE],&dvdl[efptFTYPE],
+                                                                  md,fcd,global_atom_index);
+                    }
+                }
+                else
+                {
+                    v = do_listed_vdw_q(ftype,nbonds,iatoms,
+                                        idef->iparams,
+                                        (const rvec*)x,f,fr->fshift,
+                                        pbc,g,lambda,dvdl,
+                                        md,fr,&enerd->grpp,global_atom_index);
+                }
+                if (ind != -1)
+                {
+                    inc_nrnb(nrnb,ind,nbonds/nat1);
+                }
+            }
+        }
+    }
+    return v;
+}
+
+void calc_bonds(FILE *fplog,const gmx_multisim_t *ms,
+                const t_idef *idef,
+                rvec x[],history_t *hist,
+                rvec f[],t_forcerec *fr,
+                const t_pbc *pbc,const t_graph *g,
+                gmx_enerdata_t *enerd,t_nrnb *nrnb,
+                real *lambda,
+                const t_mdatoms *md,
+                t_fcdata *fcd,int *global_atom_index,
+                t_atomtypes *atype, gmx_genborn_t *born,
+                gmx_bool bPrintSepPot,gmx_large_int_t step)
+{
+    int    i,ftype,nbonds,ind,nat;
+    real   v,dvdl[efptNR],dvdl_dum[efptNR]; /* The dummy array is to have a place to store the dhdl at other values
+                                               of lambda, which will be thrown away in the end*/
+    real   *epot;
+    const  t_pbc *pbc_null;
+    char   buf[22];
+
+    for (i=0;i<efptNR;i++)
+    {
+        dvdl[i] = 0.0;
+    }
+    if (fr->bMolPBC)
+    {
+        pbc_null = pbc;
+    }
+    else
+    {
+        pbc_null = NULL;
+    }
+    if (bPrintSepPot)
+    {
+        fprintf(fplog,"Step %s: bonded V and dVdl for this node\n",
+                gmx_step_str(step,buf));
+    }
 
 #ifdef DEBUG
-  if (g && debug)
-    p_graph(debug,"Bondage is fun",g);
+    if (g && debug)
+    {
+        p_graph(debug,"Bondage is fun",g);
+    }
 #endif
-  
-  epot = enerd->term;
-
-  /* Do pre force calculation stuff which might require communication */
-  if (idef->il[F_ORIRES].nr) {
-    epot[F_ORIRESDEV] = calc_orires_dev(ms,idef->il[F_ORIRES].nr,
-                                       idef->il[F_ORIRES].iatoms,
-                                       idef->iparams,md,(const rvec*)x,
-                                       pbc_null,fcd,hist);
-  }
-  if (idef->il[F_DISRES].nr) {
-    calc_disres_R_6(ms,idef->il[F_DISRES].nr,
-                   idef->il[F_DISRES].iatoms,
-                   idef->iparams,(const rvec*)x,pbc_null,
-                   fcd,hist);
-  }
-  
-  /* Loop over all bonded force types to calculate the bonded forces */
-  for(ftype=0; (ftype<F_NRE); ftype++) {
-         if(ftype<F_GB12 || ftype>F_GB14) {
-    if ((interaction_function[ftype].flags & IF_BOND) &&
-       !(ftype == F_CONNBONDS || ftype == F_POSRES)) {
-      nbonds=idef->il[ftype].nr;
-      if (nbonds > 0) {
-       ind  = interaction_function[ftype].nrnb_ind;
-       nat1 = interaction_function[ftype].nratoms + 1;
-       dvdl = 0;
-       if (ftype < F_LJ14 || ftype > F_LJC_PAIRS_NB) {
-               if(ftype==F_CMAP)
-               {
-                       v = cmap_dihs(nbonds,idef->il[ftype].iatoms,
-                                                 idef->iparams,&idef->cmap_grid,
-                                                 (const rvec*)x,f,fr->fshift,
-                                                 pbc_null,g,lambda,&dvdl,md,fcd,
-                                                 global_atom_index);
-               }
-               else
-               {
-                       v =
-           interaction_function[ftype].ifunc(nbonds,idef->il[ftype].iatoms,
-                                             idef->iparams,
-                                             (const rvec*)x,f,fr->fshift,
-                                             pbc_null,g,lambda,&dvdl,md,fcd,
-                                             global_atom_index);
-               }
 
-         if (bPrintSepPot) {
-           fprintf(fplog,"  %-23s #%4d  V %12.5e  dVdl %12.5e\n",
-                   interaction_function[ftype].longname,nbonds/nat1,v,dvdl);
-         }
-       } else {
-         v = do_listed_vdw_q(ftype,nbonds,idef->il[ftype].iatoms,
-                             idef->iparams,
-                             (const rvec*)x,f,fr->fshift,
-                             pbc_null,g,
-                             lambda,&dvdl,
-                             md,fr,&enerd->grpp,global_atom_index);
-         if (bPrintSepPot) {
-           fprintf(fplog,"  %-5s + %-15s #%4d                  dVdl %12.5e\n",
-                   interaction_function[ftype].longname,
-                   interaction_function[F_COUL14].longname,nbonds/nat1,dvdl);
-         }
-       }
-       if (ind != -1)
-         inc_nrnb(nrnb,ind,nbonds/nat1);
-       epot[ftype]        += v;
-       enerd->dvdl_nonlin += dvdl;
-      }
+    epot = enerd->term;
+
+    /* Do pre force calculation stuff which might require communication */
+    if (idef->il[F_ORIRES].nr) {
+        epot[F_ORIRESDEV] = calc_orires_dev(ms,idef->il[F_ORIRES].nr,
+                                            idef->il[F_ORIRES].iatoms,
+                                            idef->iparams,md,(const rvec*)x,
+                                            pbc_null,fcd,hist);
+    }
+    if (idef->il[F_DISRES].nr) {
+        calc_disres_R_6(ms,idef->il[F_DISRES].nr,
+                        idef->il[F_DISRES].iatoms,
+                        idef->iparams,(const rvec*)x,pbc_null,
+                        fcd,hist);
+    }
+
+    /* Loop over all bonded force types to calculate the bonded forces */
+    for(ftype=0; (ftype<F_NRE); ftype++) 
+    {
+        v = calc_one_bond(fplog,ftype,idef,x, 
+                          f,fr,pbc_null,g,enerd,nrnb,lambda,dvdl,
+                          md,fcd,global_atom_index,bPrintSepPot);
+        epot[ftype]        += v;
+    }
+    /* Copy the sum of violations for the distance restraints from fcd */
+    if (fcd)
+    {
+        epot[F_DISRESVIOL] = fcd->disres.sumviol;
     }
-  }
-  }
-  /* Copy the sum of violations for the distance restraints from fcd */
-  if (fcd)
-    epot[F_DISRESVIOL] = fcd->disres.sumviol;
 }
 
 void calc_bonds_lambda(FILE *fplog,
-                      const t_idef *idef,
-                      rvec x[],
-                      t_forcerec *fr,
-                      const t_pbc *pbc,const t_graph *g,
-                      gmx_enerdata_t *enerd,t_nrnb *nrnb,
-                      real lambda,
-                      const t_mdatoms *md,
-                      t_fcdata *fcd,int *global_atom_index)
+                       const t_idef *idef,
+                       rvec x[],
+                       t_forcerec *fr,
+                       const t_pbc *pbc,const t_graph *g,
+                       gmx_enerdata_t *enerd,t_nrnb *nrnb,
+                       real *lambda,
+                       const t_mdatoms *md,
+                       t_fcdata *fcd,
+                       int *global_atom_index)
 {
-    int    ftype,nbonds_np,nbonds,ind, nat1;
-  real   *epot,v,dvdl;
-  rvec   *f,*fshift_orig;
-  const  t_pbc *pbc_null;
-  t_iatom *iatom_fe;
-
-  if (fr->bMolPBC)
-    pbc_null = pbc;
-  else
-    pbc_null = NULL;
-  
-  epot = enerd->term;
-  
-  snew(f,fr->natoms_force);
-  /* We want to preserve the fshift array in forcerec */
-  fshift_orig = fr->fshift;
-  snew(fr->fshift,SHIFTS);
-
-  /* Loop over all bonded force types to calculate the bonded forces */
-  for(ftype=0; (ftype<F_NRE); ftype++) {
-      if(ftype<F_GB12 || ftype>F_GB14) {
-          
-          if ((interaction_function[ftype].flags & IF_BOND) &&
-              !(ftype == F_CONNBONDS || ftype == F_POSRES)) 
-          {
-              nbonds_np = idef->il[ftype].nr_nonperturbed;
-              nbonds    = idef->il[ftype].nr - nbonds_np;
-              nat1 = interaction_function[ftype].nratoms + 1;
-              if (nbonds > 0) {
-                  ind  = interaction_function[ftype].nrnb_ind;
-                  iatom_fe = idef->il[ftype].iatoms + nbonds_np;
-                  dvdl = 0;
-                  if (ftype < F_LJ14 || ftype > F_LJC_PAIRS_NB) {
-                      v =
-                          interaction_function[ftype].ifunc(nbonds,iatom_fe,
-                                                            idef->iparams,
-                                                            (const rvec*)x,f,fr->fshift,
-                                                            pbc_null,g,lambda,&dvdl,md,fcd,
-                                                            global_atom_index);
-                  } else {
-                      v = do_listed_vdw_q(ftype,nbonds,iatom_fe,
-                                          idef->iparams,
-                                          (const rvec*)x,f,fr->fshift,
-                                          pbc_null,g,
-                                          lambda,&dvdl,
-                                          md,fr,&enerd->grpp,global_atom_index);
-                  }
-                  if (ind != -1)
-                      inc_nrnb(nrnb,ind,nbonds/nat1);
-                  epot[ftype] += v;
-              }
-          }
-      }
-  }
+    int    i,ftype,nbonds_np,nbonds,ind,nat;
+    real   v,dr,dr2,*epot;
+    real   dvdl_dum[efptNR];
+    rvec   *f,*fshift_orig;
+    const  t_pbc *pbc_null;
+    t_iatom *iatom_fe;
+
+    if (fr->bMolPBC)
+    {
+        pbc_null = pbc;
+    }
+    else
+    {
+        pbc_null = NULL;
+    }
+
+    epot = enerd->term;
+
+    snew(f,fr->natoms_force);
+    /* We want to preserve the fshift array in forcerec */
+    fshift_orig = fr->fshift;
+    snew(fr->fshift,SHIFTS);
+
+    /* Loop over all bonded force types to calculate the bonded forces */
+    for(ftype=0; (ftype<F_NRE); ftype++) 
+    {
+        v = calc_one_bond_foreign(fplog,ftype,idef,x, 
+                                  f,fr,pbc_null,g,enerd,nrnb,lambda,dvdl_dum,
+                                  md,fcd,global_atom_index,FALSE);
+        epot[ftype] += v;
+    }
 
-  sfree(fr->fshift);
-  fr->fshift = fshift_orig;
-  sfree(f);
+    sfree(fr->fshift);
+    fr->fshift = fshift_orig;
+    sfree(f);
 }
index a22263dac04f4023abc4865bee59e1eea614f806..3d732370cfe39b9cadb7e7a793b3d7565b3f6eb4 100644 (file)
@@ -49,6 +49,7 @@
 #include "statutil.h"
 #include "txtdump.h"
 #include "vec.h"
+#include "mdrun.h"
 #include "network.h"
 #include "gmx_random.h"
 #include "checkpoint.h"
@@ -69,6 +70,7 @@ gmx_ctime_r(const time_t *clock,char *buf, int n);
 
 #define CPT_MAGIC1 171817
 #define CPT_MAGIC2 171819
+#define CPTSTRLEN 1024
 
 #ifdef GMX_DOUBLE
 #define GMX_CPT_BUILD_DP 1
@@ -93,7 +95,7 @@ const char *est_names[estNR]=
     "x", "v", "SDx", "CGp", "LD-rng", "LD-rng-i",
     "disre_initf", "disre_rm3tav",
     "orire_initf", "orire_Dtav",
-    "svir_prev", "nosehoover-vxi", "v_eta", "vol0", "nhpres_xi", "nhpres_vxi", "fvir_prev",
+    "svir_prev", "nosehoover-vxi", "v_eta", "vol0", "nhpres_xi", "nhpres_vxi", "fvir_prev","fep_state", "MC-rng", "MC-rng-i"
 };
 
 enum { eeksEKIN_N, eeksEKINH, eeksDEKINDL, eeksMVCOS, eeksEKINF, eeksEKINO, eeksEKINSCALEF, eeksEKINSCALEH, eeksVSCALE, eeksEKINTOTAL, eeksNR };
@@ -124,7 +126,15 @@ const char *eenh_names[eenhNR]=
     "energy_delta_h_start_lambda"
 };
 
-
+/* free energy history variables -- need to be preserved over checkpoint */
+enum { edfhBEQUIL,edfhNATLAMBDA,edfhWLHISTO,edfhWLDELTA,edfhSUMWEIGHTS,edfhSUMDG,edfhSUMMINVAR,edfhSUMVAR,
+       edfhACCUMP,edfhACCUMM,edfhACCUMP2,edfhACCUMM2,edfhTIJ,edfhTIJEMP,edfhNR };
+/* free energy history variable names  */
+const char *edfh_names[edfhNR]=
+{
+    "bEquilibrated","N_at_state", "Wang-Landau_Histogram", "Wang-Landau-delta", "Weights", "Free Energies", "minvar","variance",
+    "accumulated_plus", "accumulated_minus", "accumulated_plus_2",  "accumulated_minus_2", "Tij", "Tij_empirical"
+};
 
 #ifdef GMX_NATIVE_WINDOWS
 static int
@@ -152,13 +162,23 @@ gmx_wintruncate(const char *filename, __int64 size)
 
 enum { ecprREAL, ecprRVEC, ecprMATRIX };
 
+enum { cptpEST, cptpEEKS, cptpEENH, cptpEDFH };
+/* enums for the different components of checkpoint variables, replacing the hard coded ones.
+   cptpEST - state variables.
+   cptpEEKS - Kinetic energy state variables.
+   cptpEENH - Energy history state variables.
+   cptpEDFH - free energy history variables.
+*/
+
+
 static const char *st_names(int cptp,int ecpt)
 {
     switch (cptp)
     {
-    case 0: return est_names [ecpt]; break;
-    case 1: return eeks_names[ecpt]; break;
-    case 2: return eenh_names[ecpt]; break;
+    case cptpEST: return est_names [ecpt]; break;
+    case cptpEEKS: return eeks_names[ecpt]; break;
+    case cptpEENH: return eenh_names[ecpt]; break;
+    case cptpEDFH: return edfh_names[ecpt]; break;
     }
 
     return NULL;
@@ -176,7 +196,6 @@ static void cp_error()
 
 static void do_cpt_string_err(XDR *xd,gmx_bool bRead,const char *desc,char **s,FILE *list)
 {
-#define CPTSTRLEN 1024
     bool_t res=0;
     
     if (bRead)
@@ -619,6 +638,38 @@ static int do_cpte_matrix(XDR *xd,int cptp,int ecpt,int sflags,
     return ret;
 }
 
+
+static int do_cpte_nmatrix(XDR *xd,int cptp,int ecpt,int sflags,
+                           int n, real **v,FILE *list)
+{
+    int i;
+    real *vr;
+    real ret,reti;
+    char name[CPTSTRLEN];
+
+    ret = 0;
+    if (v==NULL)
+    {
+        snew(v,n);
+    }
+    for (i=0;i<n;i++)
+    {
+        reti = 0;
+        vr = v[i];
+        reti = do_cpte_reals_low(xd,cptp,ecpt,sflags,n,NULL,&(v[i]),NULL,ecprREAL);
+        if (list && reti == 0)
+        {
+            sprintf(name,"%s[%d]",st_names(cptp,ecpt),i);
+            pr_reals(list,0,name,v[i],n);
+        }
+        if (reti == 0)
+        {
+            ret = 0;
+        }
+    }
+    return ret;
+}
+
 static int do_cpte_matrices(XDR *xd,int cptp,int ecpt,int sflags,
                             int n,matrix **v,FILE *list)
 {
@@ -699,7 +750,8 @@ static void do_cpt_header(XDR *xd,gmx_bool bRead,int *file_version,
                           gmx_large_int_t *step,double *t,
                           int *nnodes,int *dd_nc,int *npme,
                           int *natoms,int *ngtc, int *nnhpres, int *nhchainlength,
-                          int *flags_state,int *flags_eks,int *flags_enh,
+                          int *nlambda, int *flags_state,
+                          int *flags_eks,int *flags_enh, int *flags_dfh,
                           FILE *list)
 {
     bool_t res=0;
@@ -785,6 +837,14 @@ static void do_cpt_header(XDR *xd,gmx_bool bRead,int *file_version,
     {
         *nnhpres = 0;
     }
+    if (*file_version >= 12)
+    {
+        do_cpt_int_err(xd,"# of total lambda states ",nlambda,list);
+    }
+    else
+    {
+        *nlambda = 0;
+    }
     do_cpt_int_err(xd,"integrator"        ,eIntegrator,list);
        if (*file_version >= 3)
        {
@@ -824,6 +884,12 @@ static void do_cpt_header(XDR *xd,gmx_bool bRead,int *file_version,
                                          (1<<(estORIRE_DTAV+2)) |
                                          (1<<(estORIRE_DTAV+3))));
     }
+       if (*file_version >= 12)
+    {
+        do_cpt_int_err(xd,"df history flags",flags_dfh,list);
+    } else {
+        *flags_dfh = 0;
+    }
 }
 
 static int do_cpt_footer(XDR *xd,gmx_bool bRead,int file_version)
@@ -874,6 +940,7 @@ static int do_cpt_state(XDR *xd,gmx_bool bRead,
         rng_p  = NULL;
         rngi_p = NULL;
     }
+    /* We want the MC_RNG the same across all the notes for now -- lambda MC is global */
 
     sflags = state->flags;
     for(i=0; (i<estNR && ret == 0); i++)
@@ -882,29 +949,32 @@ static int do_cpt_state(XDR *xd,gmx_bool bRead,
         {
             switch (i)
             {
-            case estLAMBDA:  ret = do_cpte_real(xd,0,i,sflags,&state->lambda,list); break;
-            case estBOX:     ret = do_cpte_matrix(xd,0,i,sflags,state->box,list); break;
-            case estBOX_REL: ret = do_cpte_matrix(xd,0,i,sflags,state->box_rel,list); break;
-            case estBOXV:    ret = do_cpte_matrix(xd,0,i,sflags,state->boxv,list); break;
-            case estPRES_PREV: ret = do_cpte_matrix(xd,0,i,sflags,state->pres_prev,list); break;
-            case estSVIR_PREV:  ret = do_cpte_matrix(xd,0,i,sflags,state->svir_prev,list); break;
-            case estFVIR_PREV:  ret = do_cpte_matrix(xd,0,i,sflags,state->fvir_prev,list); break;
-            case estNH_XI:   ret = do_cpte_doubles(xd,0,i,sflags,nnht,&state->nosehoover_xi,list); break;
-            case estNH_VXI:  ret = do_cpte_doubles(xd,0,i,sflags,nnht,&state->nosehoover_vxi,list); break;
-            case estNHPRES_XI:   ret = do_cpte_doubles(xd,0,i,sflags,nnhtp,&state->nhpres_xi,list); break;
-            case estNHPRES_VXI:  ret = do_cpte_doubles(xd,0,i,sflags,nnhtp,&state->nhpres_vxi,list); break;
-            case estTC_INT:  ret = do_cpte_doubles(xd,0,i,sflags,state->ngtc,&state->therm_integral,list); break;
-            case estVETA:    ret = do_cpte_real(xd,0,i,sflags,&state->veta,list); break;
-            case estVOL0:    ret = do_cpte_real(xd,0,i,sflags,&state->vol0,list); break;
-            case estX:       ret = do_cpte_rvecs(xd,0,i,sflags,state->natoms,&state->x,list); break;
-            case estV:       ret = do_cpte_rvecs(xd,0,i,sflags,state->natoms,&state->v,list); break;
-            case estSDX:     ret = do_cpte_rvecs(xd,0,i,sflags,state->natoms,&state->sd_X,list); break;
-            case estLD_RNG:  ret = do_cpte_ints(xd,0,i,sflags,state->nrng,rng_p,list); break;
-            case estLD_RNGI: ret = do_cpte_ints(xd,0,i,sflags,state->nrngi,rngi_p,list); break;
-            case estDISRE_INITF:  ret = do_cpte_real (xd,0,i,sflags,&state->hist.disre_initf,list); break;
-            case estDISRE_RM3TAV: ret = do_cpte_n_reals(xd,0,i,sflags,&state->hist.ndisrepairs,&state->hist.disre_rm3tav,list); break;
-            case estORIRE_INITF:  ret = do_cpte_real (xd,0,i,sflags,&state->hist.orire_initf,list); break;
-            case estORIRE_DTAV:   ret = do_cpte_n_reals(xd,0,i,sflags,&state->hist.norire_Dtav,&state->hist.orire_Dtav,list); break;
+            case estLAMBDA:  ret = do_cpte_reals(xd,cptpEST,i,sflags,efptNR,&(state->lambda),list); break;
+            case estFEPSTATE: ret = do_cpte_int (xd,cptpEST,i,sflags,&state->fep_state,list); break;
+            case estBOX:     ret = do_cpte_matrix(xd,cptpEST,i,sflags,state->box,list); break;
+            case estBOX_REL: ret = do_cpte_matrix(xd,cptpEST,i,sflags,state->box_rel,list); break;
+            case estBOXV:    ret = do_cpte_matrix(xd,cptpEST,i,sflags,state->boxv,list); break;
+            case estPRES_PREV: ret = do_cpte_matrix(xd,cptpEST,i,sflags,state->pres_prev,list); break;
+            case estSVIR_PREV:  ret = do_cpte_matrix(xd,cptpEST,i,sflags,state->svir_prev,list); break;
+            case estFVIR_PREV:  ret = do_cpte_matrix(xd,cptpEST,i,sflags,state->fvir_prev,list); break;
+            case estNH_XI:   ret = do_cpte_doubles(xd,cptpEST,i,sflags,nnht,&state->nosehoover_xi,list); break;
+            case estNH_VXI:  ret = do_cpte_doubles(xd,cptpEST,i,sflags,nnht,&state->nosehoover_vxi,list); break;
+            case estNHPRES_XI:   ret = do_cpte_doubles(xd,cptpEST,i,sflags,nnhtp,&state->nhpres_xi,list); break;
+            case estNHPRES_VXI:  ret = do_cpte_doubles(xd,cptpEST,i,sflags,nnhtp,&state->nhpres_vxi,list); break;
+            case estTC_INT:  ret = do_cpte_doubles(xd,cptpEST,i,sflags,state->ngtc,&state->therm_integral,list); break;
+            case estVETA:    ret = do_cpte_real(xd,cptpEST,i,sflags,&state->veta,list); break;
+            case estVOL0:    ret = do_cpte_real(xd,cptpEST,i,sflags,&state->vol0,list); break;
+            case estX:       ret = do_cpte_rvecs(xd,cptpEST,i,sflags,state->natoms,&state->x,list); break;
+            case estV:       ret = do_cpte_rvecs(xd,cptpEST,i,sflags,state->natoms,&state->v,list); break;
+            case estSDX:     ret = do_cpte_rvecs(xd,cptpEST,i,sflags,state->natoms,&state->sd_X,list); break;
+            case estLD_RNG:  ret = do_cpte_ints(xd,cptpEST,i,sflags,state->nrng,rng_p,list); break;
+            case estLD_RNGI: ret = do_cpte_ints(xd,cptpEST,i,sflags,state->nrngi,rngi_p,list); break;
+            case estMC_RNG:  ret = do_cpte_ints(xd,cptpEST,i,sflags,state->nmcrng,(int **)&state->mc_rng,list); break;
+            case estMC_RNGI: ret = do_cpte_ints(xd,cptpEST,i,sflags,1,&state->mc_rngi,list); break;
+            case estDISRE_INITF:  ret = do_cpte_real (xd,cptpEST,i,sflags,&state->hist.disre_initf,list); break;
+            case estDISRE_RM3TAV: ret = do_cpte_reals(xd,cptpEST,i,sflags,state->hist.ndisrepairs,&state->hist.disre_rm3tav,list); break;
+            case estORIRE_INITF:  ret = do_cpte_real (xd,cptpEST,i,sflags,&state->hist.orire_initf,list); break;
+            case estORIRE_DTAV:   ret = do_cpte_reals(xd,cptpEST,i,sflags,state->hist.norire_Dtav,&state->hist.orire_Dtav,list); break;
             default:
                 gmx_fatal(FARGS,"Unknown state entry %d\n"
                           "You are probably reading a new checkpoint file with old code",i);
@@ -931,16 +1001,16 @@ static int do_cpt_ekinstate(XDR *xd,gmx_bool bRead,
             switch (i)
             {
                 
-                       case eeksEKIN_N:     ret = do_cpte_int(xd,1,i,fflags,&ekins->ekin_n,list); break;
-                       case eeksEKINH :     ret = do_cpte_matrices(xd,1,i,fflags,ekins->ekin_n,&ekins->ekinh,list); break;
-                       case eeksEKINF:      ret = do_cpte_matrices(xd,1,i,fflags,ekins->ekin_n,&ekins->ekinf,list); break;
-                       case eeksEKINO:      ret = do_cpte_matrices(xd,1,i,fflags,ekins->ekin_n,&ekins->ekinh_old,list); break;
-            case eeksEKINTOTAL:  ret = do_cpte_matrix(xd,1,i,fflags,ekins->ekin_total,list); break;
-            case eeksEKINSCALEF: ret = do_cpte_doubles(xd,1,i,fflags,ekins->ekin_n,&ekins->ekinscalef_nhc,list); break;
-            case eeksVSCALE:     ret = do_cpte_doubles(xd,1,i,fflags,ekins->ekin_n,&ekins->vscale_nhc,list); break;
-            case eeksEKINSCALEH: ret = do_cpte_doubles(xd,1,i,fflags,ekins->ekin_n,&ekins->ekinscaleh_nhc,list); break;
-                       case eeksDEKINDL :   ret = do_cpte_real(xd,1,i,fflags,&ekins->dekindl,list); break;
-            case eeksMVCOS:      ret = do_cpte_real(xd,1,i,fflags,&ekins->mvcos,list); break;                  
+                       case eeksEKIN_N:     ret = do_cpte_int(xd,cptpEEKS,i,fflags,&ekins->ekin_n,list); break;
+                       case eeksEKINH :     ret = do_cpte_matrices(xd,cptpEEKS,i,fflags,ekins->ekin_n,&ekins->ekinh,list); break;
+                       case eeksEKINF:      ret = do_cpte_matrices(xd,cptpEEKS,i,fflags,ekins->ekin_n,&ekins->ekinf,list); break;
+                       case eeksEKINO:      ret = do_cpte_matrices(xd,cptpEEKS,i,fflags,ekins->ekin_n,&ekins->ekinh_old,list); break;
+            case eeksEKINTOTAL:  ret = do_cpte_matrix(xd,cptpEEKS,i,fflags,ekins->ekin_total,list); break;
+            case eeksEKINSCALEF: ret = do_cpte_doubles(xd,cptpEEKS,i,fflags,ekins->ekin_n,&ekins->ekinscalef_nhc,list); break;
+            case eeksVSCALE:     ret = do_cpte_doubles(xd,1,cptpEEKS,fflags,ekins->ekin_n,&ekins->vscale_nhc,list); break;
+            case eeksEKINSCALEH: ret = do_cpte_doubles(xd,1,cptpEEKS,fflags,ekins->ekin_n,&ekins->ekinscaleh_nhc,list); break;
+                       case eeksDEKINDL :   ret = do_cpte_real(xd,1,cptpEEKS,fflags,&ekins->dekindl,list); break;
+            case eeksMVCOS:      ret = do_cpte_real(xd,1,cptpEEKS,fflags,&ekins->mvcos,list); break;
             default:
                 gmx_fatal(FARGS,"Unknown ekin data state entry %d\n"
                           "You are probably reading a new checkpoint file with old code",i);
@@ -985,40 +1055,39 @@ static int do_cpt_enerhist(XDR *xd,gmx_bool bRead,
         {
             switch (i)
             {
-                case eenhENERGY_N:     ret = do_cpte_int(xd,2,i,fflags,&enerhist->nener,list); break;
-                case eenhENERGY_AVER:  ret = do_cpte_doubles(xd,2,i,fflags,enerhist->nener,&enerhist->ener_ave,list); break;
-                case eenhENERGY_SUM:   ret = do_cpte_doubles(xd,2,i,fflags,enerhist->nener,&enerhist->ener_sum,list); break;
-                case eenhENERGY_NSUM:  do_cpt_step_err(xd,eenh_names[i],&enerhist->nsum,list); break;
-                case eenhENERGY_SUM_SIM: ret = do_cpte_doubles(xd,2,i,fflags,enerhist->nener,&enerhist->ener_sum_sim,list); break;
-                case eenhENERGY_NSUM_SIM:   do_cpt_step_err(xd,eenh_names[i],&enerhist->nsum_sim,list); break;
-                case eenhENERGY_NSTEPS:     do_cpt_step_err(xd,eenh_names[i],&enerhist->nsteps,list); break;
-                case eenhENERGY_NSTEPS_SIM: do_cpt_step_err(xd,eenh_names[i],&enerhist->nsteps_sim,list); break;
-                case eenhENERGY_DELTA_H_NN: do_cpt_int_err(xd,eenh_names[i], &(enerhist->dht->nndh), list); 
-                    if (bRead) /* now allocate memory for it */
-                    {
-                        snew(enerhist->dht->dh, enerhist->dht->nndh);
-                        snew(enerhist->dht->ndh, enerhist->dht->nndh);
-                        for(j=0;j<enerhist->dht->nndh;j++)
-                        {
-                            enerhist->dht->ndh[j] = 0;
-                            enerhist->dht->dh[j] = NULL;
-                        }
-                    }
-                break;
-                case eenhENERGY_DELTA_H_LIST: 
+                       case eenhENERGY_N:     ret = do_cpte_int(xd,cptpEENH,i,fflags,&enerhist->nener,list); break;
+                       case eenhENERGY_AVER:  ret = do_cpte_doubles(xd,cptpEENH,i,fflags,enerhist->nener,&enerhist->ener_ave,list); break;
+                       case eenhENERGY_SUM:   ret = do_cpte_doubles(xd,cptpEENH,i,fflags,enerhist->nener,&enerhist->ener_sum,list); break;
+            case eenhENERGY_NSUM:  do_cpt_step_err(xd,eenh_names[i],&enerhist->nsum,list); break;
+            case eenhENERGY_SUM_SIM: ret = do_cpte_doubles(xd,cptpEENH,i,fflags,enerhist->nener,&enerhist->ener_sum_sim,list); break;
+            case eenhENERGY_NSUM_SIM:   do_cpt_step_err(xd,eenh_names[i],&enerhist->nsum_sim,list); break;
+            case eenhENERGY_NSTEPS:     do_cpt_step_err(xd,eenh_names[i],&enerhist->nsteps,list); break;
+            case eenhENERGY_NSTEPS_SIM: do_cpt_step_err(xd,eenh_names[i],&enerhist->nsteps_sim,list); break;
+            case eenhENERGY_DELTA_H_NN: do_cpt_int_err(xd,eenh_names[i], &(enerhist->dht->nndh), list);
+                if (bRead) /* now allocate memory for it */
+                {
+                    snew(enerhist->dht->dh, enerhist->dht->nndh);
+                    snew(enerhist->dht->ndh, enerhist->dht->nndh);
                     for(j=0;j<enerhist->dht->nndh;j++)
                     {
-                        ret=do_cpte_n_reals(xd, 2, i, fflags, &enerhist->dht->ndh[j], &(enerhist->dht->dh[j]), list); 
+                        enerhist->dht->ndh[j] = 0;
+                        enerhist->dht->dh[j] = NULL;
                     }
-                    break;
-                case eenhENERGY_DELTA_H_STARTTIME: 
-                    ret=do_cpte_double(xd, 2, i, fflags, &(enerhist->dht->start_time), list); break;
-                case eenhENERGY_DELTA_H_STARTLAMBDA: 
-                    enerhist->dht->start_lambda_set=TRUE;
-                    ret=do_cpte_double(xd, 2, i, fflags, &(enerhist->dht->start_lambda), list); break;
-                default:
-                    gmx_fatal(FARGS,"Unknown energy history entry %d\n"
-                              "You are probably reading a new checkpoint file with old code",i);
+                }
+                break;
+            case eenhENERGY_DELTA_H_LIST:
+                for(j=0;j<enerhist->dht->nndh;j++)
+                {
+                    ret=do_cpte_n_reals(xd, cptpEENH, i, fflags, &enerhist->dht->ndh[j], &(enerhist->dht->dh[j]), list);
+                }
+                break;
+            case eenhENERGY_DELTA_H_STARTTIME:
+                ret=do_cpte_double(xd, cptpEENH, i, fflags, &(enerhist->dht->start_time), list); break;
+            case eenhENERGY_DELTA_H_STARTLAMBDA:
+                ret=do_cpte_double(xd, cptpEENH, i, fflags, &(enerhist->dht->start_lambda), list); break;
+            default:
+                gmx_fatal(FARGS,"Unknown energy history entry %d\n"
+                          "You are probably reading a new checkpoint file with old code",i);
             }
         }
     }
@@ -1052,6 +1121,45 @@ static int do_cpt_enerhist(XDR *xd,gmx_bool bRead,
     return ret;
 }
 
+static int do_cpt_df_hist(XDR *xd,gmx_bool bRead,int fflags,df_history_t *dfhist,FILE *list)
+{
+    int  i,nlambda;
+    int  ret;
+
+    nlambda = dfhist->nlambda;
+    ret = 0;
+
+    for(i=0; (i<edfhNR && ret == 0); i++)
+    {
+        if (fflags & (1<<i))
+        {
+            switch (i)
+            {
+            case edfhBEQUIL:       ret = do_cpte_int(xd,cptpEDFH,i,fflags,&dfhist->bEquil,list); break;
+            case edfhNATLAMBDA:    ret = do_cpte_ints(xd,cptpEDFH,i,fflags,nlambda,&dfhist->n_at_lam,list); break;
+            case edfhWLHISTO:      ret = do_cpte_reals(xd,cptpEDFH,i,fflags,nlambda,&dfhist->wl_histo,list); break;
+            case edfhWLDELTA:      ret = do_cpte_real(xd,cptpEDFH,i,fflags,&dfhist->wl_delta,list); break;
+            case edfhSUMWEIGHTS:   ret = do_cpte_reals(xd,cptpEDFH,i,fflags,nlambda,&dfhist->sum_weights,list); break;
+            case edfhSUMDG:        ret = do_cpte_reals(xd,cptpEDFH,i,fflags,nlambda,&dfhist->sum_dg,list); break;
+            case edfhSUMMINVAR:    ret = do_cpte_reals(xd,cptpEDFH,i,fflags,nlambda,&dfhist->sum_minvar,list); break;
+            case edfhSUMVAR:       ret = do_cpte_reals(xd,cptpEDFH,i,fflags,nlambda,&dfhist->sum_variance,list); break;
+            case edfhACCUMP:       ret = do_cpte_nmatrix(xd,cptpEDFH,i,fflags,nlambda,dfhist->accum_p,list); break;
+            case edfhACCUMM:       ret = do_cpte_nmatrix(xd,cptpEDFH,i,fflags,nlambda,dfhist->accum_m,list); break;
+            case edfhACCUMP2:      ret = do_cpte_nmatrix(xd,cptpEDFH,i,fflags,nlambda,dfhist->accum_p2,list); break;
+            case edfhACCUMM2:      ret = do_cpte_nmatrix(xd,cptpEDFH,i,fflags,nlambda,dfhist->accum_m2,list); break;
+            case edfhTIJ:          ret = do_cpte_nmatrix(xd,cptpEDFH,i,fflags,nlambda,dfhist->Tij,list); break;
+            case edfhTIJEMP:       ret = do_cpte_nmatrix(xd,cptpEDFH,i,fflags,nlambda,dfhist->Tij_empirical,list); break;
+
+            default:
+                gmx_fatal(FARGS,"Unknown df history entry %d\n"
+                          "You are probably reading a new checkpoint file with old code",i);
+            }
+        }
+    }
+
+    return ret;
+}
+
 static int do_cpt_files(XDR *xd, gmx_bool bRead, 
                         gmx_file_position_t **p_outputfiles, int *nfiles, 
                         FILE *list, int file_version)
@@ -1155,6 +1263,7 @@ static int do_cpt_files(XDR *xd, gmx_bool bRead,
 void write_checkpoint(const char *fn,gmx_bool bNumberAndKeep,
                       FILE *fplog,t_commrec *cr,
                       int eIntegrator,int simulation_part,
+                      gmx_bool bExpanded, int elamstats,
                       gmx_large_int_t step,double t,t_state *state)
 {
     t_fileio *fp;
@@ -1173,7 +1282,7 @@ void write_checkpoint(const char *fn,gmx_bool bNumberAndKeep,
     gmx_file_position_t *outputfiles;
     int  noutputfiles;
     char *ftime;
-    int  flags_eks,flags_enh,i;
+    int  flags_eks,flags_enh,flags_dfh,i;
     t_fileio *ret;
                
     if (PAR(cr))
@@ -1252,7 +1361,23 @@ void write_checkpoint(const char *fn,gmx_bool bNumberAndKeep,
         }
     }
 
-    
+    if (bExpanded)
+    {
+        flags_dfh = ((1<<edfhBEQUIL) | (1<<edfhNATLAMBDA) | (1<<edfhSUMWEIGHTS) |  (1<<edfhSUMDG)  |
+                     (1<<edfhTIJ) | (1<<edfhTIJEMP));
+        if (EWL(elamstats))
+        {
+            flags_dfh |= ((1<<edfhWLDELTA) | (1<<edfhWLHISTO));
+        }
+        if ((elamstats == elamstatsMINVAR) || (elamstats == elamstatsBARKER) || (elamstats == elamstatsMETROPOLIS))
+        {
+            flags_dfh |= ((1<<edfhACCUMP) | (1<<edfhACCUMM) | (1<<edfhACCUMP2) | (1<<edfhACCUMM2)
+                          | (1<<edfhSUMMINVAR) | (1<<edfhSUMVAR));
+        }
+    } else {
+        flags_dfh = 0;
+    }
+
     version = gmx_strdup(VERSION);
     btime   = gmx_strdup(BUILD_TIME);
     buser   = gmx_strdup(BUILD_USER);
@@ -1267,7 +1392,7 @@ void write_checkpoint(const char *fn,gmx_bool bNumberAndKeep,
                   &eIntegrator,&simulation_part,&step,&t,&nppnodes,
                   DOMAINDECOMP(cr) ? cr->dd->nc : NULL,&npmenodes,
                   &state->natoms,&state->ngtc,&state->nnhpres,
-                  &state->nhchainlength, &state->flags,&flags_eks,&flags_enh,
+                  &state->nhchainlength,&(state->dfhist.nlambda),&state->flags,&flags_eks,&flags_enh,&flags_dfh,
                   NULL);
     
     sfree(version);
@@ -1279,6 +1404,7 @@ void write_checkpoint(const char *fn,gmx_bool bNumberAndKeep,
     if((do_cpt_state(gmx_fio_getxdr(fp),FALSE,state->flags,state,TRUE,NULL) < 0)        ||
        (do_cpt_ekinstate(gmx_fio_getxdr(fp),FALSE,flags_eks,&state->ekinstate,NULL) < 0)||
        (do_cpt_enerhist(gmx_fio_getxdr(fp),FALSE,flags_enh,&state->enerhist,NULL) < 0)  ||
+       (do_cpt_df_hist(gmx_fio_getxdr(fp),FALSE,flags_dfh,&state->dfhist,NULL) < 0)  ||
        (do_cpt_files(gmx_fio_getxdr(fp),FALSE,&outputfiles,&noutputfiles,NULL,
                      file_version) < 0))
     {
@@ -1468,7 +1594,7 @@ static void check_match(FILE *fplog,
 
 static void read_checkpoint(const char *fn,FILE **pfplog,
                             t_commrec *cr,gmx_bool bPartDecomp,ivec dd_nc,
-                            int eIntegrator,gmx_large_int_t *step,double *t,
+                            int eIntegrator, int *init_fep_state, gmx_large_int_t *step,double *t,
                             t_state *state,gmx_bool *bReadRNG,gmx_bool *bReadEkin,
                             int *simulation_part,
                             gmx_bool bAppendOutputFiles,gmx_bool bForceAppend)
@@ -1481,7 +1607,7 @@ static void read_checkpoint(const char *fn,FILE **pfplog,
        char filename[STRLEN],buf[STEPSTRSIZE];
     int  nppnodes,eIntegrator_f,nppnodes_f,npmenodes_f;
     ivec dd_nc_f;
-    int  natoms,ngtc,nnhpres,nhchainlength,fflags,flags_eks,flags_enh;
+    int  natoms,ngtc,nnhpres,nhchainlength,nlambda,fflags,flags_eks,flags_enh,flags_dfh;
     int  d;
     int  ret;
     gmx_file_position_t *outputfiles;
@@ -1521,8 +1647,8 @@ static void read_checkpoint(const char *fn,FILE **pfplog,
                   &version,&btime,&buser,&bmach,&double_prec,&fprog,&ftime,
                   &eIntegrator_f,simulation_part,step,t,
                   &nppnodes_f,dd_nc_f,&npmenodes_f,
-                  &natoms,&ngtc,&nnhpres,&nhchainlength,
-                  &fflags,&flags_eks,&flags_enh,NULL);
+                  &natoms,&ngtc,&nnhpres,&nhchainlength,&nlambda,
+                  &fflags,&flags_eks,&flags_enh,&flags_dfh,NULL);
 
     if (bAppendOutputFiles &&
         file_version >= 13 && double_prec != GMX_CPT_BUILD_DP)
@@ -1566,6 +1692,11 @@ static void read_checkpoint(const char *fn,FILE **pfplog,
         gmx_fatal(FARGS,"Checkpoint file is for a system of %d NH-pressure-coupling variables, while the current system consists of %d NH-pressure-coupling variables",nnhpres,state->nnhpres);
     }
 
+    if (nlambda != state->dfhist.nlambda)
+    {
+        gmx_fatal(FARGS,"Checkpoint file is for a system with %d lambda states, while the current system consists of %d lambda states",nlambda,state->dfhist.nlambda);
+    }
+
     init_gtc_state(state,state->ngtc,state->nnhpres,nhchainlength); /* need to keep this here to keep the tpr format working */
     /* write over whatever was read; we use the number of Nose-Hoover chains from the checkpoint */
     
@@ -1684,6 +1815,8 @@ static void read_checkpoint(const char *fn,FILE **pfplog,
         }
     }
     ret = do_cpt_state(gmx_fio_getxdr(fp),TRUE,fflags,state,*bReadRNG,NULL);
+    *init_fep_state = state->fep_state;  /* there should be a better way to do this than setting it here.
+                                            Investigate for 5.0. */
     if (ret)
     {
         cp_error();
@@ -1717,6 +1850,13 @@ static void read_checkpoint(const char *fn,FILE **pfplog,
         state->enerhist.nsum_sim = *step;
     }
 
+    ret = do_cpt_df_hist(gmx_fio_getxdr(fp),TRUE,
+                         flags_dfh,&state->dfhist,NULL);
+    if (ret)
+    {
+        cp_error();
+    }
+
        ret = do_cpt_files(gmx_fio_getxdr(fp),TRUE,&outputfiles,&nfiles,NULL,file_version);
        if (ret)
        {
@@ -1894,7 +2034,7 @@ void load_checkpoint(const char *fn,FILE **fplog,
       /* Read the state from the checkpoint file */
       read_checkpoint(fn,fplog,
                       cr,bPartDecomp,dd_nc,
-                      ir->eI,&step,&t,state,bReadRNG,bReadEkin,
+                      ir->eI,&(ir->fepvals->init_fep_state),&step,&t,state,bReadRNG,bReadEkin,
                       &ir->simulation_part,bAppend,bForceAppend);
     }
     if (PAR(cr)) {
@@ -1924,7 +2064,7 @@ static void read_checkpoint_data(t_fileio *fp,int *simulation_part,
     int  eIntegrator;
     int  nppnodes,npme;
     ivec dd_nc;
-    int  flags_eks,flags_enh;
+    int  flags_eks,flags_enh,flags_dfh;
     int  nfiles_loc;
     gmx_file_position_t *files_loc=NULL;
     int  ret;
@@ -1933,7 +2073,7 @@ static void read_checkpoint_data(t_fileio *fp,int *simulation_part,
                   &version,&btime,&buser,&bmach,&double_prec,&fprog,&ftime,
                   &eIntegrator,simulation_part,step,t,&nppnodes,dd_nc,&npme,
                   &state->natoms,&state->ngtc,&state->nnhpres,&state->nhchainlength,
-                  &state->flags,&flags_eks,&flags_enh,NULL);
+                  &(state->dfhist.nlambda),&state->flags,&flags_eks,&flags_enh,&flags_dfh,NULL);
     ret =
         do_cpt_state(gmx_fio_getxdr(fp),TRUE,state->flags,state,bReadRNG,NULL);
     if (ret)
@@ -1952,6 +2092,12 @@ static void read_checkpoint_data(t_fileio *fp,int *simulation_part,
     {
         cp_error();
     }
+    ret = do_cpt_df_hist(gmx_fio_getxdr(fp),TRUE,
+                          flags_dfh,&state->dfhist,NULL);
+    if (ret)
+    {
+        cp_error();
+    }
 
     ret = do_cpt_files(gmx_fio_getxdr(fp),TRUE,
                        outputfiles != NULL ? outputfiles : &files_loc,
@@ -2001,7 +2147,7 @@ void read_checkpoint_trxframe(t_fileio *fp,t_trxframe *fr)
     gmx_large_int_t step;
     double t;
     
-    init_state(&state,0,0,0,0);
+    init_state(&state,0,0,0,0,0);
     
     read_checkpoint_data(fp,&simulation_part,&step,&t,&state,FALSE,NULL,NULL);
     
@@ -2013,7 +2159,8 @@ void read_checkpoint_trxframe(t_fileio *fp,t_trxframe *fr)
     fr->bTime   = TRUE;
     fr->time    = t;
     fr->bLambda = TRUE;
-    fr->lambda  = state.lambda;
+    fr->lambda  = state.lambda[efptFEP];
+    fr->fep_state  = state.fep_state;
     fr->bAtoms  = FALSE;
     fr->bX      = (state.flags & (1<<estX));
     if (fr->bX)
@@ -2047,21 +2194,22 @@ void list_checkpoint(const char *fn,FILE *out)
     double t;
     ivec dd_nc;
     t_state state;
-    int  flags_eks,flags_enh;
+    int  flags_eks,flags_enh,flags_dfh;
     int  indent;
     int  i,j;
     int  ret;
     gmx_file_position_t *outputfiles;
        int  nfiles;
        
-    init_state(&state,-1,-1,-1,-1);
+    init_state(&state,-1,-1,-1,-1,0);
 
     fp = gmx_fio_open(fn,"r");
     do_cpt_header(gmx_fio_getxdr(fp),TRUE,&file_version,
                   &version,&btime,&buser,&bmach,&double_prec,&fprog,&ftime,
                   &eIntegrator,&simulation_part,&step,&t,&nppnodes,dd_nc,&npme,
                   &state.natoms,&state.ngtc,&state.nnhpres,&state.nhchainlength,
-                  &state.flags,&flags_eks,&flags_enh,out);
+                  &(state.dfhist.nlambda),&state.flags,
+                  &flags_eks,&flags_enh,&flags_dfh,out);
     ret = do_cpt_state(gmx_fio_getxdr(fp),TRUE,state.flags,&state,TRUE,out);
     if (ret)
     {
@@ -2076,6 +2224,12 @@ void list_checkpoint(const char *fn,FILE *out)
     ret = do_cpt_enerhist(gmx_fio_getxdr(fp),TRUE,
                           flags_enh,&state.enerhist,out);
 
+    if (ret == 0)
+    {
+        init_df_history(&state.dfhist,state.dfhist.nlambda,0); /* reinitialize state with correct sizes */
+        ret = do_cpt_df_hist(gmx_fio_getxdr(fp),TRUE,
+                             flags_dfh,&state.dfhist,out);
+    }
     if (ret == 0)
     {
                do_cpt_files(gmx_fio_getxdr(fp),TRUE,&outputfiles,&nfiles,out,file_version);
@@ -2142,7 +2296,7 @@ gmx_bool read_checkpoint_simulation_part(const char *filename, int *simulation_p
         }
         else 
         {
-            init_state(&state,0,0,0,0);
+            init_state(&state,0,0,0,0,0);
 
             read_checkpoint_data(fp,simulation_part,&step,&t,&state,FALSE,
                                  &nfiles,&outputfiles);
diff --git a/src/gmxlib/dihres.c b/src/gmxlib/dihres.c
deleted file mode 100644 (file)
index a54f3c7..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROningen Mixture of Alchemy and Childrens' Stories
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <math.h>
-#include "typedefs.h"
-#include "sysstuff.h"
-#include "smalloc.h"
-#include "macros.h"
-#include "physics.h"
-#include "vec.h"
-#include "futil.h"
-#include "xvgr.h"
-#include "gmx_fatal.h"
-#include "bondf.h"
-#include "copyrite.h"
-#include "disre.h"
-#include "main.h"
-#include "mtop_util.h"
-#include "dihre.h"
-
-void init_dihres(FILE *fplog,gmx_mtop_t *mtop,t_inputrec *ir,t_fcdata *fcd)
-{
-  int count;
-
-  fcd->dihre_fc = ir->dihre_fc;
-
-  count = gmx_mtop_ftype_count(mtop,F_DIHRES);
-
-  if (fplog && count) {
-    fprintf(fplog,"There are %d dihedral restraints\n",count);
-  }
-}
-
-real ta_dihres(int nfa,const t_iatom forceatoms[],const t_iparams ip[],
-              const rvec x[],rvec f[],rvec fshift[],
-              const t_pbc *pbc,const t_graph *g,
-              real lambda,real *dvdlambda,
-              const t_mdatoms *md,t_fcdata *fcd,
-              int *ddgatindex)
-{
-  real vtot = 0;
-  int  ai,aj,ak,al,i,k,type,typep,label,power,t1,t2,t3;
-  real phi0,phi,ddphi,ddp,dp,dp2,dphi,kfac,sign,d2r,fc;
-  rvec r_ij,r_kj,r_kl,m,n;
-  
-  fc  = fcd->dihre_fc;
-  d2r = DEG2RAD;
-  k   = 0;
-  for(i=0; (i<nfa); ) {
-    type = forceatoms[i++];
-    ai   = forceatoms[i++];
-    aj   = forceatoms[i++];
-    ak   = forceatoms[i++];
-    al   = forceatoms[i++];
-    
-    phi0  = ip[type].dihres.phi*d2r;
-    dphi  = ip[type].dihres.dphi*d2r;
-    kfac  = ip[type].dihres.kfac*fc; 
-    power = ip[type].dihres.power;
-    label = ip[type].dihres.label;
-    
-    phi = dih_angle(x[ai],x[aj],x[ak],x[al],pbc,r_ij,r_kj,r_kl,m,n,
-                    &sign,&t1,&t2,&t3);          
-    /* 84 flops */
-    
-    if (debug)
-        fprintf(debug,"dihres[%d]: %d %d %d %d : phi=%f, dphi=%f, kfac=%f, power=%d, label=%d\n",
-                k++,ai,aj,ak,al,phi,dphi,kfac,power,label);
-
-    /* phi can jump if phi0 is close to Pi/-Pi, which will cause huge
-     * force changes if we just apply a normal harmonic.
-     * Instead, we first calculate phi-phi0 and take it modulo (-Pi,Pi).
-     * This means we will never have the periodicity problem, unless
-     * the dihedral is Pi away from phiO, which is very unlikely due to
-     * the potential.
-     */
-    dp = phi-phi0;  
-    if (fabs(dp) > dphi) {
-      /* dp cannot be outside (-2*pi,2*pi) */
-      if (dp >= M_PI)
-       dp -= 2*M_PI;
-      else if(dp < -M_PI)
-       dp += 2*M_PI;
-
-      if (dp > dphi)
-       ddp = dp-dphi;
-      else if (dp < -dphi)
-       ddp = dp+dphi;
-      else
-       ddp = 0;
-
-      if (ddp != 0.0) {
-       vtot += 0.5*kfac*ddp*ddp;
-       ddphi = kfac*ddp;
-       
-       do_dih_fup(ai,aj,ak,al,ddphi,r_ij,r_kj,r_kl,m,n,
-                  f,fshift,pbc,g,x,t1,t2,t3);          /* 112          */
-      }
-    }
-  }
-  return vtot;
-}
index e2dc8fe6db14ebc841deb497951c9ccdab723e90..d9b1d7bd2549731cb440dfcc5b3c23ae10f7080f 100644 (file)
@@ -1122,7 +1122,7 @@ void get_enx_state(const char *fn, real t, gmx_groups_t *groups, t_inputrec *ir,
       }
       fprintf(stderr,"\nREAD %d NOSE-HOOVER Xi chains FROM %s\n\n",state->ngtc,fn);
 
-      if (IR_NPT_TROTTER(ir)
+      if (IR_NPT_TROTTER(ir) || IR_NPH_TROTTER(ir))
       {
           for(i=0; i<state->nnhpres; i++) {
               bufi = baro_nm[0]; /* All barostat DOF's together for now */
index 316d01f6a308ce4b75eacfcdaf4b9069e4b88f68..6e2625552af57f88d563ceab34169ec2342e78eb 100644 (file)
@@ -41,7 +41,6 @@
 #include "typedefs.h"
 #include "bondf.h"
 #include "disre.h"
-#include "dihre.h"
 #include "orires.h"
 #include "genborn.h"
 
@@ -90,7 +89,7 @@ const t_interaction_function interaction_function[F_NRE]=
 {
   def_bond    ("BONDS",    "Bond",            2, 2, 2,  eNR_BONDS,  bonds         ),
   def_bond    ("G96BONDS", "G96Bond",         2, 2, 2,  eNR_BONDS,  g96bonds      ),
-  def_bond    ("MORSE",    "Morse",           2, 3, 0,  eNR_MORSE,  morse_bonds   ),
+  def_bond    ("MORSE",    "Morse",           2, 3, 3,  eNR_MORSE,  morse_bonds   ),
   def_bond    ("CUBICBONDS","Cubic Bonds",    2, 3, 0,  eNR_CUBICBONDS, cubic_bonds),
   def_bondnb  ("CONNBONDS","Connect Bonds",   2, 0, 0,  0,      unimplemented     ),
   def_bonded  ("HARMONIC", "Harmonic Pot.",   2, 2, 2,  eNR_BONDS,  bonds         ),
@@ -103,7 +102,7 @@ const t_interaction_function interaction_function[F_NRE]=
   def_angle   ("LINEAR_ANGLES", "Lin. Angle", 3, 2, 2,  eNR_LINEAR_ANGLES, linear_angles ),
   def_bonded  ("CROSS_BOND_BOND", "Bond-Cross", 3, 3, 0,0,          cross_bond_bond ),
   def_bonded  ("CROSS_BOND_ANGLE","BA-Cross",   3, 4, 0,0,          cross_bond_angle ),
-  def_angle   ("UREY_BRADLEY","U-B",          3, 4, 0,  0,          urey_bradley ),
+  def_angle   ("UREY_BRADLEY","U-B",          3, 4, 4,  0,          urey_bradley ),
   def_angle   ("QANGLES","Quartic Angles",    3, 6, 0,  eNR_QANGLES, quartic_angles ),
   def_bondedt ("TABANGLES", "Tab. Angles",    3, 2, 2,  eNR_TABANGLES, tab_angles ),
   def_bonded  ("PDIHS",    "Proper Dih.",     4, 3, 3,  eNR_PROPER, pdihs         ),
@@ -138,13 +137,13 @@ const t_interaction_function interaction_function[F_NRE]=
   def_bondnb  ("ANHARM_POL", "Anharm. Pol.",2, 3, 0, 0,          anharm_polarize      ),
   def_bonded  ("POSRES",   "Position Rest.",  1, 3, 3,  eNR_POSRES, unimplemented ),
   def_bonded  ("DISRES",   "Dis. Rest.",      2, 6, 0,  eNR_DISRES, ta_disres     ),
-  def_nofc    ("DRVIOL",   "D.R.Viol. (nm)"                                       ),    
+  def_nofc    ("DISRESVIOL",   "D.R.Viol. (nm)"                                       ),
   def_bonded  ("ORIRES",   "Orient. Rest.",   2, 6, 0,  eNR_ORIRES, orires        ),
   def_nofc    ("ORDEV",    "Ori. R. RMSD"                                         ),  
   def_bonded  ("ANGRES",   "Angle Rest.",     4, 3, 3,  eNR_ANGRES, angres        ),
   def_bonded  ("ANGRESZ",  "Angle Rest. Z",   2, 3, 3,  eNR_ANGRESZ,angresz       ),
-  def_bonded  ("DIHRES",   "Dih. Rest.",      4, 5, 0,  eNR_DIHRES, ta_dihres     ),
-  def_nofc    ("DIHVIOL",  "Dih. Rest. viol."                                     ),    
+  def_bonded  ("DIHRES",   "Dih. Rest.",      4, 3, 3,  eNR_DIHRES, dihres        ),
+  def_nofc    ("DIHRESVIOL",  "Dih. Rest. Viol."                                     ), /* obsolete */
   def_shkcb   ("CONSTR",   "Constraint",      2, 1, 1                             ),
   def_shk     ("CONSTRNC", "Constr. No Conn.",2, 1, 1                             ),
   def_shkcb   ("SETTLE",   "Settle",          3, 2, 0                             ),
@@ -169,7 +168,12 @@ const t_interaction_function interaction_function[F_NRE]=
    */
   def_nofc    ("PDISPCORR","Pres. DC"         ),  
   def_nofc    ("PRES",     "Pressure"         ),
-  def_nofc    ("DV/DL",    "dVpot/dlambda"    ),
-  def_nofc    ("DK/DL",    "dEkin/dlambda"    ),
-  def_nofc    ("DH/DL_CON","dH/dl constr."    )
+  def_nofc    ("DH/DL_CON","dH/dl constr."    ), /* obsolete */
+  def_nofc    ("DV/DL",    "dVremain/dl"      ),
+  def_nofc    ("DK/DL",    "dEkin/dl"         ),
+  def_nofc    ("DVC/DL",   "dVcoul/dl"        ),
+  def_nofc    ("DVV/DL",   "dVvdw/dl"         ),
+  def_nofc    ("DVB/DL",   "dVbonded/dl"      ),
+  def_nofc    ("DVR/DL",   "dVrestraint/dl"   ),
+  def_nofc    ("DVT/DL",   "dVtemperature/dl" )
 };
index b5dadcacd663960ea43e32dd59178f6d81363fc9..f6640328d41588149a399b191082382da442c52d 100644 (file)
@@ -89,7 +89,7 @@ int tcouple_min_integration_steps(int etc)
         n = nstmin_harmonic;
         break;
     case etcANDERSEN:
-    case etcANDERSENINTERVAL:
+    case etcANDERSENMASSIVE:
         n = 1;
         break;
     default:
index bc3f52b448df7c177c59e4c949a0472d9fc46238..30da1f11b64bca093551cf257b22262cb6c0f473 100644 (file)
@@ -218,6 +218,10 @@ void bcast_state_setup(const t_commrec *cr,t_state *state)
   block_bc(cr,state->nrng);
   block_bc(cr,state->nrngi);
   block_bc(cr,state->flags);
+  if (state->lambda==NULL)
+  {
+      snew_bc(cr,state->lambda,efptNR)
+  }
 }
 
 void bcast_state(const t_commrec *cr,t_state *state,gmx_bool bAlloc)
@@ -238,7 +242,8 @@ void bcast_state(const t_commrec *cr,t_state *state,gmx_bool bAlloc)
   for(i=0; i<estNR; i++) {
     if (state->flags & (1<<i)) {
       switch (i) {
-      case estLAMBDA:  block_bc(cr,state->lambda); break;
+      case estLAMBDA:  nblock_bc(cr,efptNR,state->lambda); break;
+      case estFEPSTATE: block_bc(cr,state->fep_state); break;
       case estBOX:     block_bc(cr,state->box); break;
       case estBOX_REL: block_bc(cr,state->box_rel); break;
       case estBOXV:    block_bc(cr,state->boxv); break;
@@ -481,16 +486,119 @@ static void bc_adress(const t_commrec *cr,t_adress *adress)
       nblock_bc(cr, adress->n_energy_grps, adress->group_explicit);
   }
 }
+static void bc_fepvals(const t_commrec *cr,t_lambda *fep)
+{
+    gmx_bool bAlloc=TRUE;
+    int i;
+
+    block_bc(cr,fep->nstdhdl);
+    block_bc(cr,fep->init_lambda);
+    block_bc(cr,fep->init_fep_state);
+    block_bc(cr,fep->delta_lambda);
+    block_bc(cr,fep->bPrintEnergy);
+    block_bc(cr,fep->n_lambda);
+    snew_bc(cr,fep->all_lambda,efptNR);
+    nblock_bc(cr,efptNR,fep->all_lambda);
+    for (i=0;i<efptNR;i++) {
+        snew_bc(cr,fep->all_lambda[i],fep->n_lambda);
+        nblock_bc(cr,fep->n_lambda,fep->all_lambda[i]);
+    }
+    block_bc(cr,fep->sc_alpha);
+    block_bc(cr,fep->sc_power);
+    block_bc(cr,fep->sc_r_power);
+    block_bc(cr,fep->sc_sigma);
+    block_bc(cr,fep->sc_sigma_min);
+    block_bc(cr,fep->bScCoul);
+    nblock_bc(cr,efptNR,&(fep->separate_dvdl[0]));
+    block_bc(cr,fep->dhdl_derivatives);
+    block_bc(cr,fep->dh_hist_size);
+    block_bc(cr,fep->dh_hist_spacing);
+    if (debug)
+    {
+        fprintf(debug,"after bc_fepvals\n");
+    }
+}
+
+static void bc_expandedvals(const t_commrec *cr,t_expanded *expand, int n_lambda)
+{
+    gmx_bool bAlloc=TRUE;
+    int i;
+
+    block_bc(cr,expand->nstexpanded);
+    block_bc(cr,expand->elamstats);
+    block_bc(cr,expand->elmcmove);
+    block_bc(cr,expand->elmceq);
+    block_bc(cr,expand->equil_n_at_lam);
+    block_bc(cr,expand->equil_wl_delta);
+    block_bc(cr,expand->equil_ratio);
+    block_bc(cr,expand->equil_steps);
+    block_bc(cr,expand->equil_samples);
+    block_bc(cr,expand->lmc_seed);
+    block_bc(cr,expand->minvar);
+    block_bc(cr,expand->minvar_const);
+    block_bc(cr,expand->c_range);
+    block_bc(cr,expand->bSymmetrizedTMatrix);
+    block_bc(cr,expand->nstTij);
+    block_bc(cr,expand->lmc_repeats);
+    block_bc(cr,expand->lmc_forced_nstart);
+    block_bc(cr,expand->gibbsdeltalam);
+    block_bc(cr,expand->wl_scale);
+    block_bc(cr,expand->wl_ratio);
+    block_bc(cr,expand->init_wl_delta);
+    block_bc(cr,expand->bInit_weights);
+    snew_bc(cr,expand->init_lambda_weights,n_lambda);
+    nblock_bc(cr,n_lambda,expand->init_lambda_weights);
+    block_bc(cr,expand->mc_temp);
+    if (debug)
+    {
+        fprintf(debug,"after bc_expandedvals\n");
+    }
+}
+
+static void bc_simtempvals(const t_commrec *cr,t_simtemp *simtemp, int n_lambda)
+{
+    gmx_bool bAlloc=TRUE;
+    int i;
+
+    block_bc(cr,simtemp->simtemp_low);
+    block_bc(cr,simtemp->simtemp_high);
+    block_bc(cr,simtemp->eSimTempScale);
+    snew_bc(cr,simtemp->temperatures,n_lambda);
+    nblock_bc(cr,n_lambda,simtemp->temperatures);
+    if (debug)
+    {
+        fprintf(debug,"after bc_simtempvals\n");
+    }
+}
 
 static void bc_inputrec(const t_commrec *cr,t_inputrec *inputrec)
 {
   gmx_bool bAlloc=TRUE;
   int i;
-  
+
   block_bc(cr,*inputrec);
-  snew_bc(cr,inputrec->flambda,inputrec->n_flambda);
-  nblock_bc(cr,inputrec->n_flambda,inputrec->flambda);
+
   bc_grpopts(cr,&(inputrec->opts));
+
+  /* even if efep is efepNO, we need to initialize to make sure that
+   * n_lambda is set to zero */
+
+  snew_bc(cr,inputrec->fepvals,1);
+  if (inputrec->efep != efepNO || inputrec->bSimTemp) 
+  {
+      bc_fepvals(cr,inputrec->fepvals);
+  }
+  /* need to initialize this as well because of data checked for in the logic */
+  snew_bc(cr,inputrec->expandedvals,1);
+  if (inputrec->bExpanded)
+  {
+      bc_expandedvals(cr,inputrec->expandedvals,inputrec->fepvals->n_lambda);
+  }
+  snew_bc(cr,inputrec->simtempvals,1);
+  if (inputrec->bSimTemp)
+  {
+      bc_simtempvals(cr,inputrec->simtempvals,inputrec->fepvals->n_lambda);
+  }
   if (inputrec->ePull != epullNO) {
     snew_bc(cr,inputrec->pull,1);
     bc_pull(cr,inputrec->pull);
index 51e5d04c23f73621c87dee1e1473dd462540f450..c67faa60ea96f8f2aab9046c1662c64b0d1c2aa7 100644 (file)
@@ -96,7 +96,7 @@ const char *egrp_nm[egNR+1] = {
 };
 
 const char *etcoupl_names[etcNR+1] = {
-  "No", "Berendsen", "Nose-Hoover", "yes", "Andersen", "Andersen-interval", "V-rescale", NULL
+  "No", "Berendsen", "Nose-Hoover", "yes", "Andersen", "Andersen-massive", "V-rescale", NULL
 }; /* yes is alias for berendsen */
 
 const char *epcoupl_names[epcNR+1] = {
@@ -132,15 +132,35 @@ const char *gtypes[egcNR+1] = {
   "User1", "User2", "VCM", "XTC", "Or. Res. Fit", "QMMM", NULL
 };
 
+const char *esimtemp_names[esimtempNR+1] = {
+  "geometric", "exponential", "linear", NULL
+};
+
 const char *efep_names[efepNR+1] = {
-  "no", "yes", NULL
+  "no", "yes", "static", "slow-growth", "expanded", NULL
+};
+
+const char *efpt_names[efptNR+1] = {
+  "fep-lambdas", "mass-lambdas", "coul-lambdas", "vdw-lambdas", "bonded-lambdas", "restraint-lambdas", "temperature-lambdas", NULL
+};
+
+const char *elamstats_names[elamstatsNR+1] = {
+  "no", "metropolis-transition", "barker-transition", "minvar", "wang-landau", "weighted-wang-landau", NULL
+};
+
+const char *elmcmove_names[elmcmoveNR+1] = {
+  "no", "metropolis", "barker", "gibbs", "metropolized-gibbs", NULL
+};
+
+const char *elmceq_names[elmceqNR+1] = {
+  "no", "yes", "wl-delta", "number-all-lambda", "number-steps", "number-samples", "count-ratio", NULL
 };
 
-const char *separate_dhdl_file_names[sepdhdlfileNR+1] = {
+const char *separate_dhdl_file_names[esepdhdlfileNR+1] = {
   "yes", "no", NULL
 };
 
-const char *dhdl_derivatives_names[dhdlderivativesNR+1] = {
+const char *dhdl_derivatives_names[edhdlderivativesNR+1] = {
   "yes", "no", NULL
 };
 
index 466c0d4827573e89b0f7e5dd5392d95a02dc92c1..941be19a201e653fb345fc8d63a4b1a1e647287e 100644 (file)
@@ -66,61 +66,86 @@ gmx_nb_free_energy_kernel(int                  icoul,
                           int *                typeB,
                           int                  ntype,
                           real *               nbfp,
-                          real *               Vvdw,
+                          real *               Vv,
                           real                 tabscale,
                           real *               VFtab,
-                          real                 lambda,
-                          real *               dvdlambda,
-                          real                 alpha,
+                          real                 lambda_coul,
+                          real                 lambda_vdw,
+                          real *               dvdl,
+                          real                 alpha_coul,
+                          real                 alpha_vdw,
                           int                  lam_power,
+                          real                 sc_r_power,
                           real                 sigma6_def,
                           real                 sigma6_min,
-                          gmx_bool                 bDoForces,
+                          gmx_bool             bDoForces,
                           int *                outeriter,
                           int *                inneriter)
 {
-    int           n,ii,is3,ii3,k,nj0,nj1,jnr,j3,ggid;
+
+#define  STATE_A  0
+#define  STATE_B  1
+#define  NSTATES  2
+    int           i,j,n,ii,is3,ii3,k,nj0,nj1,jnr,j3,ggid;
     real          shX,shY,shZ;
-    real          Fscal,FscalA,FscalB,tx,ty,tz;
-    real          VcoulA,VcoulB,VvdwA,VvdwB;
-    real          rinv6,r,rt;
+    real          Fscal,FscalC[NSTATES],FscalV[NSTATES],tx,ty,tz;
+    real          Vcoul[NSTATES],Vvdw[NSTATES];
+    real          rinv6,r,rt,rtC,rtV;
     real          iqA,iqB;
-    real          qqA,qqB,vcoul,vctot,krsq;
-    int           ntiA,ntiB;
-    int           tjA,tjB;
-    real          rinvsix;
-    real          Vvdw6,Vvdwtot;
-    real          Vvdw12;
+    real          qq[NSTATES],vctot,krsq;
+    int           ntiA,ntiB,tj[NSTATES];
+    real          Vvdw6, Vvdw12,vvtot;
     real          ix,iy,iz,fix,fiy,fiz;
-    real          dx,dy,dz,rsq,r4,r6,rinv;
-    real          c6A,c12A,c6B,c12B;
-    real          dvdl,L1,alfA,alfB,dalfA,dalfB;
-    real          sigma6a,sigma6b;
-    real          rA,rinvA,rinv4A,rB,rinvB,rinv4B;
+    real          dx,dy,dz,rsq,rinv;
+    real          c6[NSTATES],c12[NSTATES];
+    real          LFC[NSTATES],LFV[NSTATES],DLF[NSTATES];
+    double        dvdl_coul,dvdl_vdw;
+    real          lfac_coul[NSTATES],dlfac_coul[NSTATES],lfac_vdw[NSTATES],dlfac_vdw[NSTATES];
+    real          sigma6[NSTATES],alpha_vdw_eff,alpha_coul_eff,sigma2_def,sigma2_min;
+    real          rp,rpm2,rC,rV,rinvC,rpinvC,rinvV,rpinvV;
+    real          sigma2[NSTATES],sigma_pow[NSTATES],sigma_powm2[NSTATES],rs,rs2;
     int           do_coultab,do_vdwtab,do_tab,tab_elemsize;
-    int           n0,n1,nnn;
-    real          Y,F,G,H,Fp,Geps,Heps2,eps,eps2,VV,FF;
+    int           n0,n1C,n1V,nnn;
+    real          Y,F,G,H,Fp,Geps,Heps2,epsC,eps2C,epsV,eps2V,VV,FF;
     double        isp=0.564189583547756;
-
+    real          dvdl_part;
 
     /* fix compiler warnings */
-    nj1 = 0;
-    n1  = 0;
-    eps = 0;
-    eps2 = 0;
-   
-    dvdl = 0;
-    L1   = 1.0 - lambda;
-
-    alfA  = alpha*(lam_power==2 ? lambda*lambda : lambda);
-    alfB  = alpha*(lam_power==2 ? L1*L1 : L1);
-    dalfA = alpha*lam_power/6.0*(lam_power==2 ? lambda : 1); 
-    dalfB = alpha*lam_power/6.0*(lam_power==2 ? L1 : 1); 
-
-    /* Ewald table is special (icoul==5) */
-    
-    do_coultab = (icoul==3);
-    do_vdwtab  = (ivdw==3);
+    nj1   = 0;
+    n1C   = n1V   = 0;
+    epsC  = epsV  = 0;
+    eps2C = eps2V = 0;
+
+    dvdl_coul  = 0;
+    dvdl_vdw   = 0;
+
+    /* Lambda factor for state A, 1-lambda*/
+    LFC[STATE_A] = 1.0 - lambda_coul;
+    LFV[STATE_A] = 1.0 - lambda_vdw;
+
+    /* Lambda factor for state B, lambda*/
+    LFC[STATE_B] = lambda_coul;
+    LFV[STATE_B] = lambda_vdw;
+
+    /*derivative of the lambda factor for state A and B */
+    DLF[STATE_A] = -1;
+    DLF[STATE_B] = 1;
+
+    for (i=0;i<NSTATES;i++)
+    {
+        lfac_coul[i]  = (lam_power==2 ? (1-LFC[i])*(1-LFC[i]) : (1-LFC[i]));
+        dlfac_coul[i] = DLF[i]*lam_power/sc_r_power*(lam_power==2 ? (1-LFC[i]) : 1);
+        lfac_vdw[i]   = (lam_power==2 ? (1-LFV[i])*(1-LFV[i]) : (1-LFV[i]));
+        dlfac_vdw[i]  = DLF[i]*lam_power/sc_r_power*(lam_power==2 ? (1-LFV[i]) : 1);
+    }
+    /* precalculate */
+    sigma2_def = pow(sigma6_def,1.0/3.0);
+    sigma2_min = pow(sigma6_min,1.0/3.0);
+
+    /* Ewald (not PME) table is special (icoul==enbcoulFEWALD) */
+
+    do_coultab = (icoul==enbcoulTAB);
+    do_vdwtab  = (ivdw==enbcoulTAB);
     
     do_tab = do_coultab || do_vdwtab;
     
@@ -145,7 +170,7 @@ gmx_nb_free_energy_kernel(int                  icoul,
         ntiA             = 2*ntype*typeA[ii];
         ntiB             = 2*ntype*typeB[ii];
         vctot            = 0;              
-        Vvdwtot          = 0;              
+        vvtot            = 0;
         fix              = 0;              
         fiy              = 0;              
         fiz              = 0;              
@@ -160,234 +185,196 @@ gmx_nb_free_energy_kernel(int                  icoul,
             rsq              = dx*dx+dy*dy+dz*dz;
             rinv             = gmx_invsqrt(rsq);
             r                = rsq*rinv;
-            tjA              = ntiA+2*typeA[jnr];
-            tjB              = ntiB+2*typeB[jnr];
-            c6A              = nbfp[tjA];
-            c6B              = nbfp[tjB];
-            c12A             = nbfp[tjA+1];
-            c12B             = nbfp[tjB+1];
-            qqA              = iqA*chargeA[jnr]; 
-            qqB              = iqB*chargeB[jnr]; 
-            
-            if((c6A > 0) && (c12A > 0)) 
+            if (sc_r_power == 6.0)
             {
-                sigma6a      = c12A/c6A;
-
-                if (sigma6a < sigma6_min)
-                {
-                    sigma6a  = sigma6_min;
-                }
+                rpm2             = rsq*rsq; /* r4 */
+                rp               = rpm2*rsq; /* r6 */
             }
-            else 
+            else if (sc_r_power == 48.0)
             {
-                sigma6a      = sigma6_def;
-            }
-            if((c6B > 0) && (c12B > 0))
-            {
-                sigma6b      = c12B/c6B;
-
-                if (sigma6b < sigma6_min)
-                {
-                    sigma6b  = sigma6_min;
-                }
+                rp               = rsq*rsq*rsq;  /* r6 */
+                rp               = rp*rp; /* r12 */
+                rp               = rp*rp; /* r24 */
+                rp               = rp*rp; /* r48 */
+                rpm2             = rp/rsq; /* r46 */
             }
             else
             {
-                sigma6b      = sigma6_def;
+                rp             = pow(r,sc_r_power);  /* not currently supported as input, but can handle it */
+                rpm2           = rp/rsq;
             }
-                        
-            r4               = rsq*rsq;
-            r6               = r4*rsq;
-            
-            FscalA           = 0;
-            VcoulA           = 0;
-            VvdwA            = 0;
-            rinv4A           = 0;
-            
-            /* Only spend time on A state if it is non-zero */
-            if( (qqA != 0) || (c6A != 0) || (c12A != 0) ) 
+
+            tj[STATE_A]      = ntiA+2*typeA[jnr];
+            tj[STATE_B]      = ntiB+2*typeB[jnr];
+            qq[STATE_A]      = iqA*chargeA[jnr];
+            qq[STATE_B]      = iqB*chargeB[jnr];
+
+            for (i=0;i<NSTATES;i++) 
             {
-                rA             = pow(alfA*sigma6a+r6,1.0/6.0);
-                rinvA          = 1.0/rA;
-                rinv4A         = rinvA*rinvA;
-                rinv4A         = rinv4A*rinv4A;
 
-                
-                if(do_tab)
+                c6[i]              = nbfp[tj[i]];
+                c12[i]             = nbfp[tj[i]+1];
+                if((c6[i] > 0) && (c12[i] > 0))
                 {
-                    rt         = rA*tabscale;
-                    n0         = rt;
-                    eps        = rt-n0;
-                    eps2       = eps*eps;
-                    n1         = tab_elemsize*n0;
+                    sigma6[i]       = c12[i]/c6[i];
+                    sigma2[i]       = pow(c12[i]/c6[i],1.0/3.0);
+                    /* should be able to get rid of this ^^^ internal pow call eventually.  Will require agreement on
+                       what data to store externally.  Can't be fixed without larger scale changes, so not 4.6 */
+                    if (sigma6[i] < sigma6_min) { /* for disappearing coul and vdw with soft core at the same time */
+                        sigma6[i] = sigma6_min;
+                        sigma2[i] = sigma2_min;
+                    }
                 }
-                
-                if(icoul==1 || icoul==5)
+                else
                 {
-                    /* simple cutoff */
-                    VcoulA     = qqA*rinvA;
-                    FscalA     = VcoulA*rinvA*rinvA;
+                    sigma6[i]       = sigma6_def;
+                    sigma2[i]       = sigma2_def;
                 }
-                else if(icoul==2)
+                if (sc_r_power == 6.0)
                 {
-                    /* reaction-field */
-                    krsq       = krf*rA*rA;      
-                    VcoulA     = qqA*(rinvA+krsq-crf);
-                    FscalA     = qqA*(rinvA-2.0*krsq)*rinvA*rinvA;
+                    sigma_pow[i]    = sigma6[i];
+                    sigma_powm2[i]  = sigma6[i]/sigma2[i];
                 }
-                else if(icoul==3)
+                else if (sc_r_power == 48.0) 
                 {
-                    /* non-Ewald tabulated coulomb */
-                    nnn        = n1;
-                    Y          = VFtab[nnn];
-                    F          = VFtab[nnn+1];
-                    Geps       = eps*VFtab[nnn+2];
-                    Heps2      = eps2*VFtab[nnn+3];
-                    Fp         = F+Geps+Heps2;
-                    VV         = Y+eps*Fp;
-                    FF         = Fp+Geps+2.0*Heps2;
-                    VcoulA     = qqA*VV;
-                    FscalA     = -qqA*tabscale*FF*rinvA;                    
+                    sigma_pow[i]    = sigma6[i]*sigma6[i];   /* sigma^12 */
+                    sigma_pow[i]    = sigma_pow[i]*sigma_pow[i]; /* sigma^24 */
+                    sigma_pow[i]    = sigma_pow[i]*sigma_pow[i]; /* sigma^48 */
+                    sigma_powm2[i]  = sigma_pow[i]/sigma2[i];                    
                 }
-                
-                if(ivdw==1)
-                {
-                    /* cutoff LJ */
-                    rinv6            = rinvA*rinvA*rinv4A;
-                    Vvdw6            = c6A*rinv6;     
-                    Vvdw12           = c12A*rinv6*rinv6;
-                    VvdwA            = Vvdw12-Vvdw6;
-                    FscalA          += (12.0*Vvdw12-6.0*Vvdw6)*rinvA*rinvA;                    
+                else 
+                {    /* not really supported as input, but in here for testing the general case*/
+                    sigma_pow[i]    = pow(sigma2[i],sc_r_power/2);
+                    sigma_powm2[i]  = sigma_pow[i]/(sigma2[i]);
                 }
-                else if(ivdw==3)
-                {
-                    /* Table LJ */
-                   nnn = n1+4;
-                    
-                    /* dispersion */
-                    Y          = VFtab[nnn];
-                    F          = VFtab[nnn+1];
-                    Geps       = eps*VFtab[nnn+2];
-                    Heps2      = eps2*VFtab[nnn+3];
-                    Fp         = F+Geps+Heps2;
-                    VV         = Y+eps*Fp;
-                    FF         = Fp+Geps+2.0*Heps2;
-                    VvdwA     += c6A*VV;
-                    FscalA    -= c6A*tabscale*FF*rinvA;                    
-                    
-                    /* repulsion */
-                    Y          = VFtab[nnn+4];
-                    F          = VFtab[nnn+5];
-                    Geps       = eps*VFtab[nnn+6];
-                    Heps2      = eps2*VFtab[nnn+7];
-                    Fp         = F+Geps+Heps2;
-                    VV         = Y+eps*Fp;
-                    FF         = Fp+Geps+2.0*Heps2;
-                    VvdwA     += c12A*VV;
-                    FscalA    -= c12A*tabscale*FF*rinvA;
-                }           
-                /* Buckingham vdw free energy not supported */
             }
-            
-            FscalB           = 0;
-            VcoulB           = 0;
-            VvdwB            = 0;
-            rinv4B           = 0;
-            
-            /* Only spend time on B state if it is non-zero */
-            if( (qqB != 0) || (c6B != 0) || (c12B != 0) ) 
+
+            /* only use softcore if one of the states has a zero endstate - softcore is for avoiding infinities!*/
+            if ((c12[STATE_A] > 0) && (c12[STATE_B] > 0)) {
+                alpha_vdw_eff    = 0;
+                alpha_coul_eff   = 0;
+            } else {
+                alpha_vdw_eff    = alpha_vdw;
+                alpha_coul_eff   = alpha_coul;
+            }
+
+            for (i=0;i<NSTATES;i++) 
             {
-                rB             = pow(alfB*sigma6b+r6,1.0/6.0);
-                rinvB          = 1.0/rB;
-                rinv4B         = rinvB*rinvB;
-                rinv4B         = rinv4B*rinv4B;
-                
-                
-                if(do_tab)
-                {
-                    rt         = rB*tabscale;
-                    n0         = rt;
-                    eps        = rt-n0;
-                    eps2       = eps*eps;
-                    n1         = tab_elemsize*n0;
-                }
-                
-                if(icoul==1 || icoul==5)
-                {
-                    /* simple cutoff */
-                    VcoulB     = qqB*rinvB;
-                    FscalB     = VcoulB*rinvB*rinvB;
-                }
-                else if(icoul==2)
-                {
-                    /* reaction-field */
-                    krsq       = krf*rB*rB;      
-                    VcoulB     = qqB*(rinvB+krsq-crf);
-                    FscalB     = qqB*(rinvB-2.0*krsq)*rinvB*rinvB;                    
-                }
-                else if(icoul==3)
-                {
-                    /* non-Ewald tabulated coulomb */
-                    nnn        = n1;
-                    Y          = VFtab[nnn];
-                    F          = VFtab[nnn+1];
-                    Geps       = eps*VFtab[nnn+2];
-                    Heps2      = eps2*VFtab[nnn+3];
-                    Fp         = F+Geps+Heps2;
-                    VV         = Y+eps*Fp;
-                    FF         = Fp+Geps+2.0*Heps2;
-                    VcoulB     = qqB*VV;
-                    FscalB     = -qqB*tabscale*FF*rinvB;                    
-                }
-                
-                if(ivdw==1)
-                {
-                    /* cutoff LJ */
-                    rinv6            = rinvB*rinvB*rinv4B;
-                    Vvdw6            = c6B*rinv6;     
-                    Vvdw12           = c12B*rinv6*rinv6;
-                    VvdwB            = Vvdw12-Vvdw6;
-                    FscalB          += (12.0*Vvdw12-6.0*Vvdw6)*rinvB*rinvB;                    
-                }
-                else if(ivdw==3)
+                FscalC[i]    = 0;
+                FscalV[i]    = 0;
+                Vcoul[i]     = 0;
+                Vvdw[i]      = 0;
+
+                /* Only spend time on A or B state if it is non-zero */
+                if( (qq[i] != 0) || (c6[i] != 0) || (c12[i] != 0) )
                 {
-                    /* Table LJ */
-                    nnn = n1+4;
-                    
-                    /* dispersion */
-                    Y          = VFtab[nnn];
-                    F          = VFtab[nnn+1];
-                    Geps       = eps*VFtab[nnn+2];
-                    Heps2      = eps2*VFtab[nnn+3];
-                    Fp         = F+Geps+Heps2;
-                    VV         = Y+eps*Fp;
-                    FF         = Fp+Geps+2.0*Heps2;
-                    VvdwB     += c6B*VV;
-                    FscalB    -= c6B*tabscale*FF*rinvB;                    
+
+                    /* this section has to be inside the loop becaue of the dependence on sigma_pow */
+                    rpinvC         = 1.0/(alpha_coul_eff*lfac_coul[i]*sigma_pow[i]+rp);
+                    rinvC          = pow(rpinvC,1.0/sc_r_power);
+                    rC             = 1.0/rinvC;
                     
-                    /* repulsion */
-                    Y          = VFtab[nnn+4];
-                    F          = VFtab[nnn+5];
-                    Geps       = eps*VFtab[nnn+6];
-                    Heps2      = eps2*VFtab[nnn+7];
-                    Fp         = F+Geps+Heps2;
-                    VV         = Y+eps*Fp;
-                    FF         = Fp+Geps+2.0*Heps2;
-                    VvdwB     += c12B*VV;
-                    FscalB    -= c12B*tabscale*FF*rinvB;                    
-                }           
-                /* Buckingham vdw free energy not supported */
+                    rpinvV         = 1.0/(alpha_vdw_eff*lfac_vdw[i]*sigma_pow[i]+rp);
+                    rinvV          = pow(rpinvV,1.0/sc_r_power);
+                    rV             = 1.0/rinvV;
+
+                    if (do_tab)
+                    {
+                        rtC        = rC*tabscale;
+                        n0         = rtC;
+                        epsC       = rtC-n0;
+                        eps2C      = epsC*epsC;
+                        n1C        = tab_elemsize*n0;
+
+                        rtV        = rV*tabscale;
+                        n0         = rtV;
+                        epsV       = rtV-n0;
+                        eps2V      = epsV*epsV;
+                        n1V        = tab_elemsize*n0;
+                    }
+
+                    if(icoul==enbcoulOOR || icoul==enbcoulFEWALD)
+                    {
+                        /* simple cutoff */
+                        Vcoul[i]   = qq[i]*rinvC;
+                        FscalC[i]  = Vcoul[i]*rpinvC;
+                    }
+                    else if(icoul==enbcoulRF)
+                    {
+                        /* reaction-field */
+                        krsq       = krf*rC*rC;
+                        Vcoul[i]   = qq[i]*(rinvC+krsq-crf);
+                        FscalC[i]  = qq[i]*(rinvC-2.0*krsq)*rpinvC;
+                    }
+                    else if (icoul==enbcoulTAB)
+                    {
+                        /* non-Ewald tabulated coulomb */
+                        nnn        = n1C;
+                        Y          = VFtab[nnn];
+                        F          = VFtab[nnn+1];
+                        Geps       = epsC*VFtab[nnn+2];
+                        Heps2      = eps2C*VFtab[nnn+3];
+                        Fp         = F+Geps+Heps2;
+                        VV         = Y+epsC*Fp;
+                        FF         = Fp+Geps+2.0*Heps2;
+                        Vcoul[i]   = qq[i]*VV;
+                        FscalC[i]  = -qq[i]*tabscale*FF*rC*rpinvC;
+                    }
+
+                    if(ivdw==enbvdwLJ)
+                    {
+                        /* cutoff LJ */
+                        if (sc_r_power == 6.0)
+                        {
+                            rinv6            = rpinvV;
+                        }
+                        else
+                        {
+                            rinv6            = pow(rinvV,6.0);
+                        }
+                        Vvdw6            = c6[i]*rinv6;
+                        Vvdw12           = c12[i]*rinv6*rinv6;
+                        Vvdw[i]          = Vvdw12-Vvdw6;
+                        FscalV[i]        = (12.0*Vvdw12-6.0*Vvdw6)*rpinvV;
+                    }
+                    else if(ivdw==enbvdwTAB)
+                    {
+                        /* Table LJ */
+                        nnn = n1V+4;
+
+                        /* dispersion */
+                        Y          = VFtab[nnn];
+                        F          = VFtab[nnn+1];
+                        Geps       = epsV*VFtab[nnn+2];
+                        Heps2      = eps2V*VFtab[nnn+3];
+                        Fp         = F+Geps+Heps2;
+                        VV         = Y+epsV*Fp;
+                        FF         = Fp+Geps+2.0*Heps2;
+                        Vvdw[i]   += c6[i]*VV;
+                        FscalV[i] -= c6[i]*tabscale*FF*rV*rpinvV;
+
+                        /* repulsion */
+                        Y          = VFtab[nnn+4];
+                        F          = VFtab[nnn+5];
+                        Geps       = epsV*VFtab[nnn+6];
+                        Heps2      = eps2V*VFtab[nnn+7];
+                        Fp         = F+Geps+Heps2;
+                        VV         = Y+epsV*Fp;
+                        FF         = Fp+Geps+2.0*Heps2;
+                        Vvdw[i]   += c12[i]*VV;
+                        FscalV[i] -= c12[i]*tabscale*FF*rV*rpinvV;
+                    }           
+                    /* Buckingham vdw free energy not supported for now */
+                }
             }
 
             Fscal = 0;
-            
-            if(icoul==5)
-            {
-                /* Soft-core Ewald interactions are special:
-                 * For the direct space interactions we effectively want the
-                 * normal coulomb interaction (added above when icoul==5),
-                 * but need to subtract the part added in reciprocal space.
-                 */
+
+            if (icoul==enbcoulFEWALD) {
+                /* because we compute the softcore normally,
+                   we have to remove the ewald short range portion. Done outside of
+                   the states loop because this part doesn't depend on the scaled R */
+
                 if (r != 0) 
                 {
                     VV    = gmx_erf(ewc*r)*rinv;
@@ -398,20 +385,28 @@ gmx_nb_free_energy_kernel(int                  icoul,
                     VV    = ewc*2.0/sqrt(M_PI);
                     FF    = 0;
                 }
-                vctot  -= (lambda*qqB + L1*qqA)*VV;
-                Fscal  -= (lambda*qqB + L1*qqA)*FF;
-                dvdl   -= (qqB - qqA)*VV;
+
+                for (i=0;i<NSTATES;i++)
+                {
+                    vctot      -= LFC[i]*qq[i]*VV;
+                    Fscal      -= LFC[i]*qq[i]*FF;
+                    dvdl_coul  -= (DLF[i]*qq[i])*VV;
+                }
             }
-           
+
             /* Assemble A and B states */
-            vctot         += lambda*VcoulB + L1*VcoulA;
-            Vvdwtot       += lambda*VvdwB  + L1*VvdwA;
-                
-            Fscal         += (L1*FscalA*rinv4A + lambda*FscalB*rinv4B)*r4;
-            dvdl          += (VcoulB + VvdwB) - (VcoulA + VvdwA);
-            dvdl          += lambda*dalfB*FscalB*sigma6b*rinv4B
-                              - L1*dalfA*FscalA*sigma6a*rinv4A;
-                
+            for (i=0;i<NSTATES;i++)
+            {
+                vctot         += LFC[i]*Vcoul[i];
+                vvtot         += LFV[i]*Vvdw[i];
+
+                Fscal         += LFC[i]*FscalC[i]*rpm2;
+                Fscal         += LFV[i]*FscalV[i]*rpm2;
+
+                dvdl_coul     += Vcoul[i]*DLF[i] + LFC[i]*alpha_coul_eff*dlfac_coul[i]*FscalC[i]*sigma_pow[i];
+                dvdl_vdw      += Vvdw[i]*DLF[i] + LFV[i]*alpha_vdw_eff*dlfac_vdw[i]*FscalV[i]*sigma_pow[i];
+            }
+
             if (bDoForces)
             {
                 tx         = Fscal*dx;     
@@ -425,7 +420,7 @@ gmx_nb_free_energy_kernel(int                  icoul,
                 f[j3+2]    = f[j3+2] - tz;
             }
         }
-        
+
         if (bDoForces)
         {
             f[ii3]         = f[ii3]        + fix;
@@ -437,10 +432,11 @@ gmx_nb_free_energy_kernel(int                  icoul,
         }
         ggid               = gid[n];
         Vc[ggid]           = Vc[ggid] + vctot;
-        Vvdw[ggid]         = Vvdw[ggid] + Vvdwtot;
+        Vv[ggid]           = Vv[ggid] + vvtot;
     }
-    
-    *dvdlambda      += dvdl;
+
+    dvdl[efptCOUL]     += dvdl_coul;
+    dvdl[efptVDW]      += dvdl_vdw;
     *outeriter       = nri;            
     *inneriter       = nj1;            
 }
index 03d96df75c8f0205a0e2d4745c29a61ecb37b0a8..53696012324e4c7334e7b3aa2a568d7b44667975 100644 (file)
@@ -55,7 +55,7 @@ gmx_nb_free_energy_kernel(int                  icoul,
                           real                 facel,
                           real                 krf,
                           real                 crf,
-                         real                 ewc,
+                          real                 ewc,
                           real *               Vc,
                           int *                typeA,
                           int *                typeB,
@@ -64,13 +64,16 @@ gmx_nb_free_energy_kernel(int                  icoul,
                           real *               Vvdw,
                           real                 tabscale,
                           real *               VFtab,
-                          real                 lambda,
-                          real *               dvdlambda,
-                          real                 alpha,
-                         int                  lam_power,
+                          real                 lambda_coul,
+                          real                 lambda_vdw,
+                          real *               dvdl,
+                          real                 alpha_coul,
+                          real                 alpha_vdw,
+                          int                  lam_power,
+                          real                 sc_r_power,
                           real                 sigma6_def,
                           real                 sigma6_min,
-                         gmx_bool                 bDoForces,
+                          gmx_bool             bDoForces,
                           int *                outeriter,
                           int *                inneriter);
 
index d6de9b0058c0164c6c04d36ea2e1e9fbe2066810..5a7c1ad7434d30bf7a23d7635a63556fb218abae 100644 (file)
@@ -322,7 +322,7 @@ gmx_setup_adress_kernels(FILE *fplog,gmx_bool bGenericKernelOnly) {
 void do_nonbonded(t_commrec *cr,t_forcerec *fr,
                   rvec x[],rvec f[],t_mdatoms *mdatoms,t_blocka *excl,
                   real egnb[],real egcoul[],real egpol[],rvec box_size,
-                  t_nrnb *nrnb,real lambda,real *dvdlambda,
+                  t_nrnb *nrnb,real *lambda, real *dvdl,
                   int nls,int eNL,int flags)
 {
     gmx_bool            bLR,bDoForces,bForeignLambda;
@@ -524,7 +524,7 @@ void do_nonbonded(t_commrec *cr,t_forcerec *fr,
                                
                                if(nlist->free_energy)
                                {
-                                       if(nlist->ivdw==2)
+                                       if(nlist->ivdw==enbvdwBHAM)
                                        {
                                                gmx_fatal(FARGS,"Cannot do free energy Buckingham interactions.");
                                        }
@@ -555,10 +555,13 @@ void do_nonbonded(t_commrec *cr,t_forcerec *fr,
                                                                                          egnb,
                                                                                          nblists->tab.scale,
                                                                                          tabledata,
-                                                                                         lambda,
-                                                                                         dvdlambda,
-                                                                                         fr->sc_alpha,
+                                                                                         lambda[efptCOUL],
+                                              lambda[efptVDW],
+                                              dvdl,
+                                              fr->sc_alphacoul,
+                                                                                         fr->sc_alphavdw,
                                                                                          fr->sc_power,
+                                                                                         fr->sc_r_power,
                                                                                          fr->sc_sigma6_def,
                                               fr->sc_sigma6_min,
                                               bDoForces,
@@ -777,7 +780,7 @@ do_listed_vdw_q(int ftype,int nbonds,
                 const t_iatom iatoms[],const t_iparams iparams[],
                 const rvec x[],rvec f[],rvec fshift[],
                 const t_pbc *pbc,const t_graph *g,
-                real lambda,real *dvdlambda,
+                real *lambda, real *dvdl,
                 const t_mdatoms *md,
                 const t_forcerec *fr,gmx_grppairener_t *grppener,
                 int *global_atom_index)
@@ -846,32 +849,28 @@ do_listed_vdw_q(int ftype,int nbonds,
 
     /* Determine the values for icoul/ivdw. */
     if (fr->bEwald) {
-        icoul = 1;
+        icoul = enbcoulOOR;
     } 
     else if(fr->bcoultab)
     {
-        icoul = 3;
+        icoul = enbcoulTAB;
     }
     else if(fr->eeltype == eelRF_NEC)
     {
-        icoul = 2;
+        icoul = enbcoulRF;
     }
     else 
     {
-        icoul = 1;
+        icoul = enbcoulOOR;
     }
     
     if(fr->bvdwtab)
     {
-        ivdw = 3;
+        ivdw = enbvdwTAB;
     }
-    else if(fr->bBHAM)
-    {
-        ivdw = 2;
-    }
-    else 
+    else
     {
-        ivdw = 1;
+        ivdw = enbvdwLJ;
     }
     
     
@@ -980,7 +979,12 @@ do_listed_vdw_q(int ftype,int nbonds,
              * in the innerloops if we assign type combinations 0-0 and 0-1
              * to atom pair ai-aj in topologies A and B respectively.
              */
-            if(ivdw==2)
+
+            /* need to do a bit of a kludge here -- the way it is set up,
+               if the charges change, but the vdw do not, then even though bFreeEnergy is on,
+               it won't work, because all the bonds are perturbed.
+            */
+            if(ivdw==enbvdwBHAM)
             {
                 gmx_fatal(FARGS,"Cannot do free energy Buckingham interactions.");
             }
@@ -1011,10 +1015,13 @@ do_listed_vdw_q(int ftype,int nbonds,
                                       egnb,
                                       tabscale,
                                       tab,
-                                      lambda,
-                                      dvdlambda,
-                                      fr->sc_alpha,
+                                      lambda[efptCOUL],
+                                      lambda[efptVDW],
+                                      dvdl,
+                                      fr->sc_alphacoul,
+                                      fr->sc_alphavdw,
                                       fr->sc_power,
+                                      6.0, /* for 1-4's use the 6 power always - 48 power too high because of where they are forced to be */
                                       fr->sc_sigma6_def,
                                       fr->sc_sigma6_min,
                                       TRUE,
index 85567cde38a4884b14c96f661092ffc71adb47f8..fba9cb76eaab289131dc18d33b7df9c3de9b9a8c 100644 (file)
@@ -230,7 +230,7 @@ static const t_nrnb_data nbdata[eNRNB] = {
     { "Pos. Restr.",                   50  },
     { "Angle Restr.",                  191 },
     { "Angle Restr. Z",                164 },
-    { "Morse Potent.",                 58  },
+    { "Morse Potent.",                 83  },
     { "Cubic Bonds",                   54  },
     { "Walls",                         31  },
     { "Polarization",                  59  },
index 66c55f2889245e00d92cf8cc6ac9a75970032065..e79e2bd71fdb81259e9f79d087a848e57091c9f5 100644 (file)
@@ -61,10 +61,14 @@ static gmx_bool ip_pert(int ftype,const t_iparams *ip)
     case F_ANGLES:
     case F_G96ANGLES:
     case F_IDIHS:
-    case F_PIDIHS:
         bPert = (ip->harmonic.rA  != ip->harmonic.rB ||
                  ip->harmonic.krA != ip->harmonic.krB);
         break;
+    case F_MORSE:
+        bPert = (ip->morse.b0A  != ip->morse.b0B ||
+                 ip->morse.cbA  != ip->morse.cbB ||
+                 ip->morse.betaA  != ip->morse.betaB);
+        break;
     case F_RESTRBONDS:
         bPert = (ip->restraint.lowA  != ip->restraint.lowB ||
                  ip->restraint.up1A  != ip->restraint.up1B ||
@@ -72,6 +76,7 @@ static gmx_bool ip_pert(int ftype,const t_iparams *ip)
                  ip->restraint.kA    != ip->restraint.kB);
         break;
     case F_PDIHS:
+    case F_PIDIHS:
     case F_ANGRES:
     case F_ANGRESZ:
         bPert = (ip->pdihs.phiA != ip->pdihs.phiB ||
@@ -104,7 +109,12 @@ static gmx_bool ip_pert(int ftype,const t_iparams *ip)
             }
         }
         break;
-    case F_LJ14:
+    case F_DIHRES:
+        bPert = ((ip->dihres.phiA != ip->dihres.phiB) ||
+                 (ip->dihres.dphiA != ip->dihres.dphiB) ||
+                 (ip->dihres.kfacA != ip->dihres.kfacB));
+        break;
+   case F_LJ14:
         bPert = (ip->lj14.c6A  != ip->lj14.c6B ||
                  ip->lj14.c12A != ip->lj14.c12B);
         break;
index fa081ba975b20676b3cedd2ed7e3b4078c92826a..68bcadbc28e6aab97dd1c98051bb3719e395e0c7 100644 (file)
@@ -73,7 +73,7 @@
 static const char *tpx_tag = TPX_TAG_RELEASE;
 
 /* This number should be increased whenever the file format changes! */
-static const int tpx_version = 78;
+static const int tpx_version = 79;
 
 /* This number should only be increased when you edit the TOPOLOGY section
  * of the tpx format. This way we can maintain forward compatibility too
@@ -119,14 +119,15 @@ typedef struct {
   { 30, F_CROSS_BOND_BONDS  },
   { 30, F_CROSS_BOND_ANGLES },
   { 30, F_UREY_BRADLEY      },
-  { 30, F_POLARIZATION      }
+  { 30, F_POLARIZATION      },
+  { 54, F_DHDL_CON          },
   };*/
-  
 /* 
  *The entries should be ordered in:
  * 1. ascending function type number
  * 2. ascending file version number
  */
+/* question; what is the purpose of the commented code above? */
 static const t_ftupd ftupd[] = {
   { 20, F_CUBICBONDS        },
   { 20, F_CONNBONDS         },
@@ -171,7 +172,13 @@ static const t_ftupd ftupd[] = {
   { 69, F_VTEMP             },
   { 66, F_PDISPCORR         },
   { 54, F_DHDL_CON          },
-  { 76, F_ANHARM_POL        }
+  { 76, F_ANHARM_POL        },
+  { 79, F_DVDL_COUL         },
+  { 79, F_DVDL_VDW,         },
+  { 79, F_DVDL_BONDED,      },
+  { 79, F_DVDL_RESTRAINT    },
+  { 79, F_DVDL_TEMPERATURE  },
+  { 54, F_DHDL_CON          }
 };
 #define NFTUPD asize(ftupd)
 
@@ -242,6 +249,229 @@ static void do_pullgrp(t_fileio *fio, t_pullgrp *pgrp, gmx_bool bRead,
   }
 }
 
+static void do_expandedvals(t_fileio *fio,t_expanded *expand,int n_lambda, gmx_bool bRead, int file_version)
+{
+  /* i is used in the ndo_double macro*/
+  int i;
+  real fv;
+  gmx_bool bDum=TRUE;
+  real rdum;
+
+  if (file_version >= 79)
+  {
+      if (n_lambda>0)
+      {
+          if (bRead)
+          {
+              snew(expand->init_lambda_weights,n_lambda);
+          }
+          bDum=gmx_fio_ndo_real(fio,expand->init_lambda_weights,n_lambda);
+          gmx_fio_do_gmx_bool(fio,expand->bInit_weights);
+      }
+
+      gmx_fio_do_int(fio,expand->nstexpanded);
+      gmx_fio_do_int(fio,expand->elmcmove);
+      gmx_fio_do_int(fio,expand->elamstats);
+      gmx_fio_do_int(fio,expand->lmc_repeats);
+      gmx_fio_do_int(fio,expand->gibbsdeltalam);
+      gmx_fio_do_int(fio,expand->lmc_forced_nstart);
+      gmx_fio_do_int(fio,expand->lmc_seed);
+      gmx_fio_do_real(fio,expand->mc_temp);
+      gmx_fio_do_int(fio,expand->bSymmetrizedTMatrix);
+      gmx_fio_do_int(fio,expand->nstTij);
+      gmx_fio_do_int(fio,expand->minvarmin);
+      gmx_fio_do_int(fio,expand->c_range);
+      gmx_fio_do_real(fio,expand->wl_scale);
+      gmx_fio_do_real(fio,expand->wl_ratio);
+      gmx_fio_do_real(fio,expand->init_wl_delta);
+      gmx_fio_do_gmx_bool(fio,expand->bWLoneovert);
+      gmx_fio_do_int(fio,expand->elmceq);
+      gmx_fio_do_int(fio,expand->equil_steps);
+      gmx_fio_do_int(fio,expand->equil_samples);
+      gmx_fio_do_int(fio,expand->equil_n_at_lam);
+      gmx_fio_do_real(fio,expand->equil_wl_delta);
+      gmx_fio_do_real(fio,expand->equil_ratio);
+  }
+}
+
+static void do_simtempvals(t_fileio *fio,t_simtemp *simtemp, int n_lambda, gmx_bool bRead, 
+                           int file_version)
+{
+  gmx_bool bDum=TRUE;
+
+  if (file_version >= 79)
+  {
+      gmx_fio_do_int(fio,simtemp->eSimTempScale);
+      gmx_fio_do_real(fio,simtemp->simtemp_high);
+      gmx_fio_do_real(fio,simtemp->simtemp_low);
+      if (n_lambda>0)
+      {
+          if (bRead)
+          {
+              snew(simtemp->temperatures,n_lambda);
+          }
+          bDum=gmx_fio_ndo_real(fio,simtemp->temperatures,n_lambda);
+      }
+  }
+}
+
+static void do_fepvals(t_fileio *fio,t_lambda *fepvals,gmx_bool bRead, int file_version)
+{
+  /* i is defined in the ndo_double macro; use g to iterate. */
+  int i,g;
+  real fv;
+  gmx_bool bDum=TRUE;
+  real rdum;
+
+  /* free energy values */
+  if (file_version >= 79)
+  {
+      gmx_fio_do_int(fio,fepvals->init_fep_state);
+      gmx_fio_do_double(fio,fepvals->init_lambda);
+      gmx_fio_do_double(fio,fepvals->delta_lambda);
+  }
+  else if (file_version >= 59) {
+      gmx_fio_do_double(fio,fepvals->init_lambda);
+      gmx_fio_do_double(fio,fepvals->delta_lambda);
+  } else {
+      gmx_fio_do_real(fio,rdum);
+      fepvals->init_lambda = rdum;
+      gmx_fio_do_real(fio,rdum);
+      fepvals->delta_lambda = rdum;
+  }
+  if (file_version >= 79)
+  {
+      gmx_fio_do_int(fio,fepvals->n_lambda);
+      if (bRead)
+      {
+          snew(fepvals->all_lambda,efptNR);
+      }
+      for (g=0;g<efptNR;g++)
+      {
+          if (fepvals->n_lambda > 0) {
+              if (bRead)
+              {
+                  snew(fepvals->all_lambda[g],fepvals->n_lambda);
+              }
+              bDum=gmx_fio_ndo_double(fio,fepvals->all_lambda[g],fepvals->n_lambda);
+              bDum=gmx_fio_ndo_int(fio,fepvals->separate_dvdl,efptNR);
+          }
+          else if (fepvals->init_lambda >= 0)
+          {
+              fepvals->separate_dvdl[efptFEP] = TRUE;
+          }
+      }
+  }
+  else if (file_version >= 64)
+  {
+      gmx_fio_do_int(fio,fepvals->n_lambda);
+      snew(fepvals->all_lambda,efptNR);
+      if (bRead)
+      {
+          snew(fepvals->all_lambda[efptFEP],fepvals->n_lambda);
+      }
+      bDum=gmx_fio_ndo_double(fio,fepvals->all_lambda[efptFEP],fepvals->n_lambda);
+      if (fepvals->init_lambda >= 0)
+      {
+          fepvals->separate_dvdl[efptFEP] = TRUE;
+      }
+  }
+  else
+  {
+      fepvals->n_lambda = 0;
+      fepvals->all_lambda   = NULL;
+      if (fepvals->init_lambda >= 0)
+      {
+          fepvals->separate_dvdl[efptFEP] = TRUE;
+      }
+  }
+  if (file_version >= 13)
+  {
+      gmx_fio_do_real(fio,fepvals->sc_alpha);
+  }
+  else
+  {
+      fepvals->sc_alpha = 0;
+  }
+  if (file_version >= 38)
+  {
+      gmx_fio_do_int(fio,fepvals->sc_power);
+  }
+  else
+  {
+      fepvals->sc_power = 2;
+  }
+  if (file_version >= 79)
+  {
+      gmx_fio_do_real(fio,fepvals->sc_r_power);
+  }
+  else
+  {
+      fepvals->sc_r_power = 6.0;
+  }
+  if (file_version >= 15)
+  {
+      gmx_fio_do_real(fio,fepvals->sc_sigma);
+  }
+  else
+  {
+      fepvals->sc_sigma = 0.3;
+  }
+  if (bRead)
+  {
+      if (file_version >= 71)
+      {
+          fepvals->sc_sigma_min = fepvals->sc_sigma;
+      }
+      else
+      {
+          fepvals->sc_sigma_min = 0;
+      }
+  }
+  if (file_version >= 79)
+  {
+      gmx_fio_do_int(fio,fepvals->bScCoul);
+  }
+  else
+  {
+      fepvals->bScCoul = TRUE;
+  }
+  if (file_version >= 64) {
+      gmx_fio_do_int(fio,fepvals->nstdhdl);
+  } else {
+      fepvals->nstdhdl = 1;
+  }
+
+  if (file_version >= 73)
+  {
+      gmx_fio_do_int(fio, fepvals->separate_dhdl_file);
+      gmx_fio_do_int(fio, fepvals->dhdl_derivatives);
+  }
+  else
+  {
+      fepvals->separate_dhdl_file = esepdhdlfileYES;
+      fepvals->dhdl_derivatives = edhdlderivativesYES;
+  }
+  if (file_version >= 71)
+  {
+      gmx_fio_do_int(fio,fepvals->dh_hist_size);
+      gmx_fio_do_double(fio,fepvals->dh_hist_spacing);
+  }
+  else
+  {
+      fepvals->dh_hist_size    = 0;
+      fepvals->dh_hist_spacing = 0.1;
+  }
+  if (file_version >= 79)
+  {
+      gmx_fio_do_int(fio,fepvals->bPrintEnergy);
+  }
+  else
+  {
+      fepvals->bPrintEnergy = FALSE;
+  }
+}
+
 static void do_pull(t_fileio *fio, t_pull *pull,gmx_bool bRead, int file_version)
 {
   int g;
@@ -544,6 +774,9 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir,gmx_bool bRead,
      * but the values 0 and 1 still mean no and
      * berendsen temperature coupling, respectively.
      */
+    if (file_version >= 79) {
+        gmx_fio_do_gmx_bool(fio,ir->bPrintNHChains);
+    }
     if (file_version >= 71)
     {
         gmx_fio_do_int(fio,ir->nsttcouple);
@@ -623,11 +856,10 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir,gmx_bool bRead,
       clear_rvec(ir->posres_com);
       clear_rvec(ir->posres_comB);
     }
-    if(file_version > 25)
-      gmx_fio_do_int(fio,ir->andersen_seed);
+    if((file_version > 25) && (file_version < 79))
+        gmx_fio_do_int(fio,ir->andersen_seed);
     else
-      ir->andersen_seed=0;
-    
+        ir->andersen_seed=0;
     if(file_version < 26) {
       gmx_fio_do_gmx_bool(fio,bSimAnn); 
       gmx_fio_do_real(fio,zerotemptime);
@@ -639,77 +871,46 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir,gmx_bool bRead,
     gmx_fio_do_real(fio,ir->shake_tol);
     if (file_version < 54)
       gmx_fio_do_real(fio,*fudgeQQ);
+
     gmx_fio_do_int(fio,ir->efep);
-    if (file_version <= 14 && ir->efep > efepNO)
-      ir->efep = efepYES;
-    if (file_version >= 59) {
-      gmx_fio_do_double(fio, ir->init_lambda); 
-      gmx_fio_do_double(fio, ir->delta_lambda);
-    } else {
-      gmx_fio_do_real(fio,rdum);
-      ir->init_lambda = rdum;
-      gmx_fio_do_real(fio,rdum);
-      ir->delta_lambda = rdum;
-    }
-    if (file_version >= 64) {
-      gmx_fio_do_int(fio,ir->n_flambda);
-      if (bRead) {
-       snew(ir->flambda,ir->n_flambda);
-      }
-      bDum=gmx_fio_ndo_double(fio,ir->flambda,ir->n_flambda);
-    } else {
-      ir->n_flambda = 0;
-      ir->flambda   = NULL;
+    if (file_version <= 14 && ir->efep != efepNO)
+    {
+        ir->efep = efepYES;
     }
-    if (file_version >= 13)
-      gmx_fio_do_real(fio,ir->sc_alpha);
-    else
-      ir->sc_alpha = 0;
-    if (file_version >= 38)
-      gmx_fio_do_int(fio,ir->sc_power);
-    else
-      ir->sc_power = 2;
-    if (file_version >= 15)
-      gmx_fio_do_real(fio,ir->sc_sigma);
-    else
-      ir->sc_sigma = 0.3;
-    if (bRead)
+    do_fepvals(fio,ir->fepvals,bRead,file_version);
+
+    if (file_version >= 79)
     {
-        if (file_version >= 71)
-        {
-            ir->sc_sigma_min = ir->sc_sigma;
-        }
-        else
+        gmx_fio_do_gmx_bool(fio,ir->bSimTemp);
+        if (ir->bSimTemp) 
         {
-            ir->sc_sigma_min = 0;
+            ir->bSimTemp = TRUE;
         }
     }
-    if (file_version >= 64) {
-      gmx_fio_do_int(fio,ir->nstdhdl);
-    } else {
-      ir->nstdhdl = 1;
-    }
-
-    if (file_version >= 73)
+    else
     {
-        gmx_fio_do_int(fio, ir->separate_dhdl_file);
-        gmx_fio_do_int(fio, ir->dhdl_derivatives);
+        ir->bSimTemp = FALSE;
     }
-    else
+    if (ir->bSimTemp)
     {
-        ir->separate_dhdl_file = sepdhdlfileYES;
-        ir->dhdl_derivatives = dhdlderivativesYES;
+        do_simtempvals(fio,ir->simtempvals,ir->fepvals->n_lambda,bRead,file_version);
     }
 
-    if (file_version >= 71)
+    if (file_version >= 79)
     {
-        gmx_fio_do_int(fio,ir->dh_hist_size);
-        gmx_fio_do_double(fio,ir->dh_hist_spacing);
+        gmx_fio_do_gmx_bool(fio,ir->bExpanded);
+        if (ir->bExpanded)
+        {
+            ir->bExpanded = TRUE;
+        }
+        else
+        {
+            ir->bExpanded = FALSE;
+        }
     }
-    else
+    if (ir->bExpanded)
     {
-        ir->dh_hist_size    = 0;
-        ir->dh_hist_spacing = 0.1;
+        do_expandedvals(fio,ir->expandedvals,ir->fepvals->n_lambda,bRead,file_version);
     }
     if (file_version >= 57) {
       gmx_fio_do_int(fio,ir->eDisre); 
@@ -734,14 +935,15 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir,gmx_bool bRead,
       ir->orires_tau = 0;
       ir->nstorireout = 0;
     }
-    if(file_version >= 26) {
+    if(file_version >= 26 && file_version < 79) {
       gmx_fio_do_real(fio,ir->dihre_fc);
-      if (file_version < 56) {
-       gmx_fio_do_real(fio,rdum);
-       gmx_fio_do_int(fio,idum);
+      if (file_version < 56) 
+      {
+          gmx_fio_do_real(fio,rdum);
+          gmx_fio_do_int(fio,idum);
       }
     } else {
-      ir->dihre_fc=0;
+        ir->dihre_fc=0;
     }
 
     gmx_fio_do_real(fio,ir->em_stepsize); 
@@ -798,7 +1000,7 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir,gmx_bool bRead,
     gmx_fio_do_real(fio,ir->userreal4); 
     
     /* AdResS stuff */
-    if (file_version >= 75) {
+    if (file_version >= 77) {
       gmx_fio_do_gmx_bool(fio,ir->bAdress);
       if(ir->bAdress){
           if (bRead) snew(ir->adress, 1);
@@ -1082,10 +1284,21 @@ void do_iparams(t_fileio *fio, t_functype ftype,t_iparams *iparams,
     gmx_fio_do_real(fio,iparams->cross_ba.krt);
     break;
   case F_UREY_BRADLEY:
-    gmx_fio_do_real(fio,iparams->u_b.theta);
-    gmx_fio_do_real(fio,iparams->u_b.ktheta);
-    gmx_fio_do_real(fio,iparams->u_b.r13);
-    gmx_fio_do_real(fio,iparams->u_b.kUB);
+    gmx_fio_do_real(fio,iparams->u_b.thetaA);
+    gmx_fio_do_real(fio,iparams->u_b.kthetaA);
+    gmx_fio_do_real(fio,iparams->u_b.r13A);
+    gmx_fio_do_real(fio,iparams->u_b.kUBA);
+    if (file_version >= 79) {
+        gmx_fio_do_real(fio,iparams->u_b.thetaB);
+        gmx_fio_do_real(fio,iparams->u_b.kthetaB);
+        gmx_fio_do_real(fio,iparams->u_b.r13B);
+        gmx_fio_do_real(fio,iparams->u_b.kUBB);
+    } else {
+        iparams->u_b.thetaB=iparams->u_b.thetaA;
+        iparams->u_b.kthetaB=iparams->u_b.kthetaA;
+        iparams->u_b.r13B=iparams->u_b.r13A;
+        iparams->u_b.kUBB=iparams->u_b.kUBA;
+    }
     break;
   case F_QUARTIC_ANGLES:
     gmx_fio_do_real(fio,iparams->qangle.theta);
@@ -1097,9 +1310,18 @@ void do_iparams(t_fileio *fio, t_functype ftype,t_iparams *iparams,
     gmx_fio_do_real(fio,iparams->bham.c);
     break;
   case F_MORSE:
-    gmx_fio_do_real(fio,iparams->morse.b0);
-    gmx_fio_do_real(fio,iparams->morse.cb);
-    gmx_fio_do_real(fio,iparams->morse.beta);
+    gmx_fio_do_real(fio,iparams->morse.b0A);
+    gmx_fio_do_real(fio,iparams->morse.cbA);
+    gmx_fio_do_real(fio,iparams->morse.betaA);
+    if (file_version >= 79) {
+        gmx_fio_do_real(fio,iparams->morse.b0B);
+        gmx_fio_do_real(fio,iparams->morse.cbB);
+        gmx_fio_do_real(fio,iparams->morse.betaB);
+    } else {
+        iparams->morse.b0B = iparams->morse.b0A;
+        iparams->morse.cbB = iparams->morse.cbA;
+        iparams->morse.betaB = iparams->morse.betaA;
+    }
     break;
   case F_CUBICBONDS:
     gmx_fio_do_real(fio,iparams->cubic.b0);
@@ -1190,11 +1412,18 @@ void do_iparams(t_fileio *fio, t_functype ftype,t_iparams *iparams,
     gmx_fio_do_real(fio,iparams->orires.kfac);
     break;
   case F_DIHRES:
-    gmx_fio_do_int(fio,iparams->dihres.power);
-    gmx_fio_do_int(fio,iparams->dihres.label);
-    gmx_fio_do_real(fio,iparams->dihres.phi);
-    gmx_fio_do_real(fio,iparams->dihres.dphi);
-    gmx_fio_do_real(fio,iparams->dihres.kfac);
+    gmx_fio_do_real(fio,iparams->dihres.phiA);
+    gmx_fio_do_real(fio,iparams->dihres.dphiA);
+    gmx_fio_do_real(fio,iparams->dihres.kfacA);
+    if (file_version >= 72) {
+        gmx_fio_do_real(fio,iparams->dihres.phiB);
+        gmx_fio_do_real(fio,iparams->dihres.dphiB);
+        gmx_fio_do_real(fio,iparams->dihres.kfacB);
+    } else {
+        iparams->dihres.phiB=iparams->dihres.phiA;
+        iparams->dihres.dphiB=iparams->dihres.dphiA;
+        iparams->dihres.kfacB=iparams->dihres.kfacA;
+    }
     break;
   case F_POSRES:
     gmx_fio_do_rvec(fio,iparams->posres.pos0A);
@@ -1270,9 +1499,8 @@ void do_iparams(t_fileio *fio, t_functype ftype,t_iparams *iparams,
        gmx_fio_do_int(fio,iparams->cmap.cmapB);
     break;
   default:
-    gmx_fatal(FARGS,"unknown function type %d (%s) in %s line %d",
-               
-               ftype,interaction_function[ftype].name,__FILE__,__LINE__);
+      gmx_fatal(FARGS,"unknown function type %d (%s) in %s line %d",
+                ftype,interaction_function[ftype].name,__FILE__,__LINE__);
   }
   if (!bRead)
     gmx_fio_unset_comment(fio);
@@ -1387,8 +1615,8 @@ static void do_ilists(t_fileio *fio, t_ilist *ilist,gmx_bool bRead,
     bClear = FALSE;
     if (bRead)
       for (k=0; k<NFTUPD; k++)
-       if ((file_version < ftupd[k].fvnr) && (j == ftupd[k].ftype))
-         bClear = TRUE;
+        if ((file_version < ftupd[k].fvnr) && (j == ftupd[k].ftype)) 
+          bClear = TRUE;
     if (bClear) {
       ilist[j].nr = 0;
       ilist[j].iatoms = NULL;
@@ -2181,8 +2409,17 @@ static void do_tpxheader(t_fileio *fio,gmx_bool bRead,t_tpxheader *tpx,
   else
     tpx->ngtc = 0;
   if (fver < 62) {
-    gmx_fio_do_int(fio,idum);
-    gmx_fio_do_real(fio,rdum);
+      gmx_fio_do_int(fio,idum);
+      gmx_fio_do_real(fio,rdum);
+  }
+  /*a better decision will eventually (5.0 or later) need to be made
+    on how to treat the alchemical state of the system, which can now
+    vary through a simulation, and cannot be completely described
+    though a single lambda variable, or even a single state
+    index. Eventually, should probably be a vector. MRS*/
+  if (fver >= 79) 
+  {
+      gmx_fio_do_int(fio,tpx->fep_state);
   }
   gmx_fio_do_real(fio,tpx->lambda);
   gmx_fio_do_int(fio,tpx->bIr);
@@ -2214,8 +2451,9 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
 
   if (!bRead) {
     tpx.natoms = state->natoms;
-    tpx.ngtc   = state->ngtc;
-    tpx.lambda = state->lambda;
+    tpx.ngtc   = state->ngtc;  /* need to add nnhpres here? */
+    tpx.fep_state = state->fep_state;
+    tpx.lambda = state->lambda[efptFEP];
     tpx.bIr  = (ir       != NULL);
     tpx.bTop = (mtop     != NULL);
     tpx.bX   = (state->x != NULL);
@@ -2230,18 +2468,18 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
 
   if (bRead) {
     state->flags  = 0;
-    state->lambda = tpx.lambda;
+    /* state->lambda = tpx.lambda;*/ /*remove this eventually? */
     /* The init_state calls initialize the Nose-Hoover xi integrals to zero */
     if (bXVallocated) {
       xptr = state->x;
       vptr = state->v;
-      init_state(state,0,tpx.ngtc,0,0);  /* nose-hoover chains */ /* eventually, need to add nnhpres here? */
-      state->natoms = tpx.natoms; 
-      state->nalloc = tpx.natoms; 
+      init_state(state,0,tpx.ngtc,0,0,0);  /* nose-hoover chains */ /* eventually, need to add nnhpres here? */
+      state->natoms = tpx.natoms;
+      state->nalloc = tpx.natoms;
       state->x = xptr;
       state->v = vptr;
     } else {
-      init_state(state,tpx.natoms,tpx.ngtc,0,0);  /* nose-hoover chains */
+        init_state(state,tpx.natoms,tpx.ngtc,0,0,0);  /* nose-hoover chains */
     }
   }
 
index 4c45288ed68f6a46ade2541756890b2d6cb9784b..c16770b9b83c3e64be0a9ff4ca18b8eaf3316f2e 100644 (file)
@@ -409,6 +409,7 @@ static gmx_bool gmx_next_frame(t_trxstatus *status,t_trxframe *fr)
     fr->bTime=TRUE;
     fr->time=sh.t;
     fr->bLambda = TRUE;
+    fr->bFepState = TRUE;
     fr->lambda = sh.lambda;
     fr->bBox = sh.box_size>0;
     if (fr->flags & (TRX_READ_X | TRX_NEED_X)) {
index 2e1381bcc79a4d2babff481cc8ff0d33d2221027..35531701ec8f2bc0b6e372951e73fbed8cc8b11d 100644 (file)
@@ -492,6 +492,99 @@ static void pr_pullgrp(FILE *fp,int indent,int g,t_pullgrp *pg)
   PR("kB",pg->kB);
 }
 
+static void pr_simtempvals(FILE *fp,int indent,t_simtemp *simtemp, int n_lambda, gmx_bool bMDPformat)
+{
+    PR("simtemp_low",simtemp->simtemp_low);
+    PR("simtemp_high",simtemp->simtemp_high);
+    PS("simulated-tempering-scaling",ESIMTEMP(simtemp->eSimTempScale));
+    pr_rvec(fp,indent,"simulated tempering temperatures",simtemp->temperatures,n_lambda,TRUE);
+}
+
+static void pr_expandedvals(FILE *fp,int indent,t_expanded *expand, int n_lambda, gmx_bool bMDPformat)
+{
+
+    PI("nstexpanded", expand->nstexpanded);
+    PS("lambda-stats", elamstats_names[expand->elamstats]);
+    PS("lambda-mc-move", elmcmove_names[expand->elmcmove]);
+    PI("lmc-repeats",expand->lmc_repeats);
+    PI("lmc-gibbsdelta",expand->gibbsdeltalam);
+    PI("lmc-nstart",expand->lmc_forced_nstart);
+    PS("symmetrized-transition-matrix", EBOOL(expand->bSymmetrizedTMatrix));
+    PI("nst-transition-matrix",expand->nstTij);
+    PI("mininum-var-min",expand->minvarmin); /*default is reasonable */
+    PI("weight-c-range",expand->c_range); /* default is just C=0 */
+    PR("wl-scale",expand->wl_scale);
+    PR("init-wl-delta",expand->init_wl_delta);
+    PR("wl-ratio",expand->wl_ratio);
+    PS("bWLoneovert",EBOOL(expand->bWLoneovert));
+    PI("lmc-seed",expand->lmc_seed);
+    PR("mc-temperature",expand->mc_temp);
+    PS("lmc-weights-equil",elmceq_names[expand->elmceq]);
+    if (expand->elmceq == elmceqNUMATLAM)
+    {
+        PI("weight-equil-number-all-lambda",expand->equil_n_at_lam);
+    }
+    if (expand->elmceq == elmceqSAMPLES)
+    {
+        PI("weight-equil-number-samples",expand->equil_samples);
+    }
+    if (expand->elmceq == elmceqSTEPS)
+    {
+        PI("weight-equil-number-steps",expand->equil_steps);
+    }
+    if (expand->elmceq == elmceqWLDELTA)
+    {
+        PR("weight-equil-wl-delta",expand->equil_wl_delta);
+    }
+    if (expand->elmceq == elmceqRATIO)
+    {
+        PR("weight-equil-count-ratio",expand->equil_ratio);
+    }
+
+    pr_indent(fp,indent);
+    pr_rvec(fp,indent,"init-lambda-weights",expand->init_lambda_weights,n_lambda,TRUE);
+    PS("init-weights",EBOOL(expand->bInit_weights));
+}
+
+static void pr_fepvals(FILE *fp,int indent,t_lambda *fep, gmx_bool bMDPformat)
+{
+    int i,j;
+
+    PI("nstdhdl",fep->nstdhdl);
+    PI("init-fep_state",fep->init_fep_state);
+    PR("init-lambda",fep->init_lambda);
+    PR("delta-lambda",fep->delta_lambda);
+    if (!bMDPformat)
+    {
+        PI("n-lambdas",fep->n_lambda);
+    }
+    if (fep->n_lambda > 0)
+    {
+        pr_indent(fp,indent);
+        fprintf(fp,"all-lambdas%s\n",bMDPformat ? " = " : ":");
+        for(i=0; i<efptNR; i++) {
+            fprintf(fp,"%18s = ",efpt_names[i]);
+            for(j=0; j<fep->n_lambda; j++)
+            {
+                fprintf(fp,"  %10g",fep->all_lambda[i][j]);
+            }
+            fprintf(fp,"\n");
+        }
+    }
+
+    PR("sc-alpha",fep->sc_alpha);
+    PS("bScCoul",EBOOL(fep->bScCoul));
+    PS("bScPrintEnergy",EBOOL(fep->bPrintEnergy));
+    PI("sc-power",fep->sc_power);
+    PR("sc-r-power",fep->sc_r_power);
+    PR("sc-sigma",fep->sc_sigma);
+    PR("sc-sigma_min",fep->sc_sigma_min);
+    PS("separate-dhdl-file", SEPDHDLFILETYPE(fep->separate_dhdl_file));
+    PS("dhdl-derivatives", DHDLDERIVATIVESTYPE(fep->dhdl_derivatives));
+    PI("dh-hist-size", fep->dh_hist_size);
+    PD("dh-hist-spacing", fep->dh_hist_spacing);
+};
+
 static void pr_pull(FILE *fp,int indent,t_pull *pull)
 {
   int g;
@@ -581,6 +674,7 @@ void pr_inputrec(FILE *fp,int indent,const char *title,t_inputrec *ir,
     PS("bContinuation",EBOOL(ir->bContinuation));
     PS("bShakeSOR",EBOOL(ir->bShakeSOR));
     PS("etc",ETCOUPLTYPE(ir->etc));
+    PS("bPrintNHChains",EBOOL(ir->bPrintNHChains));
     PI("nsttcouple",ir->nsttcouple);
     PS("epc",EPCOUPLTYPE(ir->epc));
     PS("epctype",EPCOUPLTYPETYPE(ir->epct));
@@ -599,7 +693,6 @@ void pr_inputrec(FILE *fp,int indent,const char *title,t_inputrec *ir,
              ir->posres_comB[YY],ir->posres_comB[ZZ]);
     else
       pr_rvec(fp,indent,"posres-comB",ir->posres_comB,DIM,TRUE);
-    PI("andersen-seed",ir->andersen_seed);
     PR("rlist",ir->rlist);
     PR("rlistlong",ir->rlistlong);
     PR("rtpi",ir->rtpi);
@@ -630,34 +723,18 @@ void pr_inputrec(FILE *fp,int indent,const char *title,t_inputrec *ir,
     PR("gb-dielectric-offset",ir->gb_dielectric_offset);
     PS("sa-algorithm",ESAALGORITHM(ir->gb_algorithm));
     PR("sa-surface-tension",ir->sa_surface_tension);
-         
     PS("DispCorr",EDISPCORR(ir->eDispCorr));
+    PS("bSimTemp",EBOOL(ir->bSimTemp));
+    if (ir->bSimTemp) {
+        pr_simtempvals(fp,indent,ir->simtempvals,ir->fepvals->n_lambda,bMDPformat);
+    }
     PS("free-energy",EFEPTYPE(ir->efep));
-    PR("init-lambda",ir->init_lambda);
-    PR("delta-lambda",ir->delta_lambda);
-    if (!bMDPformat)
-    {
-        PI("n-foreign-lambda",ir->n_flambda);
+    if (ir->efep != efepNO || ir->bSimTemp) {
+        pr_fepvals(fp,indent,ir->fepvals,bMDPformat);
     }
-    if (ir->n_flambda > 0)
-    {
-        pr_indent(fp,indent);
-        fprintf(fp,"foreign-lambda%s",bMDPformat ? " = " : ":");
-        for(i=0; i<ir->n_flambda; i++)
-        {
-            fprintf(fp,"  %10g",ir->flambda[i]);
-        }
-        fprintf(fp,"\n");
+    if (ir->bExpanded) {
+        pr_expandedvals(fp,indent,ir->expandedvals,ir->fepvals->n_lambda,bMDPformat);
     }
-    PR("sc-alpha",ir->sc_alpha);
-    PI("sc-power",ir->sc_power);
-    PR("sc-sigma",ir->sc_sigma);
-    PR("sc-sigma-min",ir->sc_sigma_min);
-    PI("nstdhdl", ir->nstdhdl);
-    PS("separate-dhdl-file", SEPDHDLFILETYPE(ir->separate_dhdl_file));
-    PS("dhdl-derivatives", DHDLDERIVATIVESTYPE(ir->dhdl_derivatives));
-    PI("dh-hist-size", ir->dh_hist_size);
-    PD("dh-hist-spacing", ir->dh_hist_spacing);
 
     PI("nwall",ir->nwall);
     PS("wall-type",EWALLTYPE(ir->wall_type));
@@ -776,8 +853,7 @@ void pr_iparams(FILE *fp,t_functype ftype,t_iparams *iparams)
             iparams->linangle.klinB,iparams->linangle.aB);
     break;
   case F_UREY_BRADLEY:
-    fprintf(fp,"theta=%15.8e, ktheta=%15.8e, r13=%15.8e, kUB=%15.8e\n",
-           iparams->u_b.theta,iparams->u_b.ktheta,iparams->u_b.r13,iparams->u_b.kUB);
+      fprintf(fp,"thetaA=%15.8e, kthetaA=%15.8e, r13A=%15.8e, kUBA=%15.8e, thetaB=%15.8e, kthetaB=%15.8e, r13B=%15.8e, kUBB=%15.8e\n",iparams->u_b.thetaA,iparams->u_b.kthetaA,iparams->u_b.r13A,iparams->u_b.kUBA,iparams->u_b.thetaB,iparams->u_b.kthetaB,iparams->u_b.r13B,iparams->u_b.kUBB);
     break;
   case F_QUARTIC_ANGLES:
     fprintf(fp,"theta=%15.8e",iparams->qangle.theta);
@@ -798,8 +874,9 @@ void pr_iparams(FILE *fp,t_functype ftype,t_iparams *iparams)
     pr_harm(fp,iparams,"xi","cx");
     break;
   case F_MORSE:
-    fprintf(fp,"b0=%15.8e, cb=%15.8e, beta=%15.8e\n",
-           iparams->morse.b0,iparams->morse.cb,iparams->morse.beta);
+    fprintf(fp,"b0A=%15.8e, cbA=%15.8e, betaA=%15.8e, b0B=%15.8e, cbB=%15.8e, betaB=%15.8e\n",
+            iparams->morse.b0A,iparams->morse.cbA,iparams->morse.betaA,
+            iparams->morse.b0B,iparams->morse.cbB,iparams->morse.betaB);
     break;
   case F_CUBICBONDS:
     fprintf(fp,"b0=%15.8e, kb=%15.8e, kcub=%15.8e\n",
@@ -884,9 +961,9 @@ void pr_iparams(FILE *fp,t_functype ftype,t_iparams *iparams)
            iparams->orires.c,iparams->orires.obs,iparams->orires.kfac);
     break;
   case F_DIHRES:
-    fprintf(fp,"label=%d, power=%4d phi=%15.8e, dphi=%15.8e, kfac=%15.8e)\n",
-           iparams->dihres.label,iparams->dihres.power,
-           iparams->dihres.phi,iparams->dihres.dphi,iparams->dihres.kfac);
+      fprintf(fp,"phiA=%15.8e, dphiA=%15.8e, kfacA=%15.8e, phiB=%15.8e, dphiB=%15.8e, kfacB=%15.8e\n",
+              iparams->dihres.phiA,iparams->dihres.dphiA,iparams->dihres.kfacA,
+              iparams->dihres.phiB,iparams->dihres.dphiB,iparams->dihres.kfacB);
     break;
   case F_POSRES:
     fprintf(fp,"pos0A=(%15.8e,%15.8e,%15.8e), fcA=(%15.8e,%15.8e,%15.8e), pos0B=(%15.8e,%15.8e,%15.8e), fcB=(%15.8e,%15.8e,%15.8e)\n",
index 897d2f82a78598ddeb3fe2ed14f7d7a51b6a207a..7a1ac826933e6de7a07f98774073a30cb8f09197 100644 (file)
@@ -193,7 +193,10 @@ void init_top (t_topology *top)
 
 void init_inputrec(t_inputrec *ir)
 {
-  memset(ir,0,(size_t)sizeof(*ir));
+    memset(ir,0,(size_t)sizeof(*ir));
+    snew(ir->fepvals,1);
+    snew(ir->expandedvals,1);
+    snew(ir->simtempvals,1);
 }
 
 void stupid_fill_block(t_block *grp,int natom,gmx_bool bOneIndexGroup)
@@ -491,7 +494,7 @@ void init_gtc_state(t_state *state, int ngtc, int nnhpres, int nhchainlength)
         for(i=0; i<state->ngtc; i++)
         {
             for (j=0;j<state->nhchainlength;j++)
- {
           {
                 state->nosehoover_xi[i*state->nhchainlength + j]  = 0.0;
                 state->nosehoover_vxi[i*state->nhchainlength + j]  = 0.0;
             }
@@ -528,7 +531,7 @@ void init_gtc_state(t_state *state, int ngtc, int nnhpres, int nhchainlength)
 }
 
 
-void init_state(t_state *state, int natoms, int ngtc, int nnhpres, int nhchainlength)
+void init_state(t_state *state, int natoms, int ngtc, int nnhpres, int nhchainlength, int nlambda)
 {
   int i;
 
@@ -536,6 +539,11 @@ void init_state(t_state *state, int natoms, int ngtc, int nnhpres, int nhchainle
   state->nrng   = 0;
   state->flags  = 0;
   state->lambda = 0;
+  snew(state->lambda,efptNR);
+  for (i=0;i<efptNR;i++)
+  {
+      state->lambda[i] = 0;
+  }
   state->veta   = 0;
   clear_mat(state->box);
   clear_mat(state->box_rel);
@@ -559,6 +567,8 @@ void init_state(t_state *state, int natoms, int ngtc, int nnhpres, int nhchainle
 
   init_energyhistory(&state->enerhist);
 
+  init_df_history(&state->dfhist,nlambda,0);
+
   state->ddp_count = 0;
   state->ddp_count_cg_gl = 0;
   state->cg_gl = NULL;
@@ -750,3 +760,70 @@ real max_cutoff(real cutoff1,real cutoff2)
         return max(cutoff1,cutoff2);
     }
 }
+
+extern void init_df_history(df_history_t *dfhist, int nlambda, real wl_delta)
+{
+    int i;
+
+    dfhist->bEquil = 0;
+    dfhist->nlambda = nlambda;
+    dfhist->wl_delta = wl_delta;
+    snew(dfhist->sum_weights,dfhist->nlambda);
+    snew(dfhist->sum_dg,dfhist->nlambda);
+    snew(dfhist->sum_minvar,dfhist->nlambda);
+    snew(dfhist->sum_variance,dfhist->nlambda);
+    snew(dfhist->n_at_lam,dfhist->nlambda);
+    snew(dfhist->wl_histo,dfhist->nlambda);
+
+    /* allocate transition matrices here */
+    snew(dfhist->Tij,dfhist->nlambda);
+    snew(dfhist->Tij_empirical,dfhist->nlambda);
+
+    for (i=0;i<dfhist->nlambda;i++) {
+        snew(dfhist->Tij[i],dfhist->nlambda);
+        snew(dfhist->Tij_empirical[i],dfhist->nlambda);
+    }
+
+    snew(dfhist->accum_p,dfhist->nlambda);
+    snew(dfhist->accum_m,dfhist->nlambda);
+    snew(dfhist->accum_p2,dfhist->nlambda);
+    snew(dfhist->accum_m2,dfhist->nlambda);
+
+    for (i=0;i<dfhist->nlambda;i++) {
+        snew((dfhist->accum_p)[i],dfhist->nlambda);
+        snew((dfhist->accum_m)[i],dfhist->nlambda);
+        snew((dfhist->accum_p2)[i],dfhist->nlambda);
+        snew((dfhist->accum_m2)[i],dfhist->nlambda);
+    }
+}
+
+extern void copy_df_history(df_history_t *df_dest, df_history_t *df_source)
+{
+    int i,j;
+
+    init_df_history(df_dest,df_source->nlambda,df_source->wl_delta);
+    df_dest->nlambda = df_source->nlambda;
+    df_dest->bEquil = df_source->bEquil;
+    for (i=0;i<df_dest->nlambda;i++)
+    {
+        df_dest->sum_weights[i]  = df_source->sum_weights[i];
+        df_dest->sum_dg[i]       = df_source->sum_dg[i];
+        df_dest->sum_minvar[i]   = df_source->sum_minvar[i];
+        df_dest->sum_variance[i] = df_source->sum_variance[i];
+        df_dest->n_at_lam[i]     = df_source->n_at_lam[i];
+        df_dest->wl_histo[i]     = df_source->wl_histo[i];
+        df_dest->accum_p[i]      = df_source->accum_p[i];
+        df_dest->accum_m[i]      = df_source->accum_m[i];
+        df_dest->accum_p2[i]     = df_source->accum_p2[i];
+        df_dest->accum_m2[i]     = df_source->accum_m2[i];
+    }
+
+    for (i=0;i<df_dest->nlambda;i++)
+    {
+        for (j=0;j<df_dest->nlambda;j++)
+        {
+            df_dest->Tij[i][j]  = df_source->Tij[i][j];
+            df_dest->Tij_empirical[i][j]  = df_source->Tij_empirical[i][j];
+        }
+    }
+}
index 5ccd73f50fff5e82f2ba7806aa2db014ea319539..2cac2bd4951da11fbfa3b1c7b97030cc1edf065a 100644 (file)
@@ -56,11 +56,12 @@ static int div_nsteps(int nsteps,int nst)
 double compute_io(t_inputrec *ir,int natoms,gmx_groups_t *groups,
                  int nrener,int nrepl)
 {
-  int nsteps = ir->nsteps;
-  int i,nxtcatoms=0;
-  int nstx,nstv,nstf,nste,nstlog,nstxtc,nfep=0;
-  double cio;
-  
+
+    int nsteps = ir->nsteps;
+    int i,nxtcatoms=0;
+    int nstx,nstv,nstf,nste,nstlog,nstxtc,nfep=0;
+    double cio;
+
     nstx   = div_nsteps(nsteps,ir->nstxout);
     nstv   = div_nsteps(nsteps,ir->nstvout);
     nstf   = div_nsteps(nsteps,ir->nstfout);
@@ -79,46 +80,71 @@ double compute_io(t_inputrec *ir,int natoms,gmx_groups_t *groups,
     /* We add 2 for the header */
     nste   = div_nsteps(2+nsteps,ir->nstenergy);
 
-  cio  = 80*natoms;
-  cio += (nstx+nstf+nstv)*sizeof(real)*(3.0*natoms);
-  cio += nstxtc*(14*4 + nxtcatoms*5.0); /* roughly 5 bytes per atom */
-  cio += nstlog*(nrener*16*2.0); /* 16 bytes per energy term plus header */
-  /* t_energy contains doubles, but real is written to edr */
-  cio += (1.0*nste)*nrener*3*sizeof(real);
-  
-  if (ir->efep != efepNO) {
-      int ndh=ir->n_flambda;
-      if (ir->dhdl_derivatives == dhdlderivativesYES)
-      {
-          ndh += 1;
-      }   
-      if (ir->separate_dhdl_file==sepdhdlfileYES)
-      {
-          int nchars = 8 + ndh*10; /* time data ~8 chars/line,
-                                        dH data ~10 chars/line */
-          cio += div_nsteps(nsteps,ir->nstdhdl)*nchars;
-      }
-      else
-      {
-          /* dH output to ener.edr: */
-          if (ir->dh_hist_size <= 0) 
-          {
-              /* as data blocks: 1 real per dH point */
-              cio += div_nsteps(nsteps,ir->nstenergy)*ndh*sizeof(real); 
-          }
-          else
-          {
-              /* as histograms: dh_hist_size ints per histogram */
-              cio += div_nsteps(nsteps,ir->nstenergy)*
-                        sizeof(int)*ir->dh_hist_size*ndh;
-          }
-      }
-  }
+    cio  = 80*natoms;
+    cio += (nstx+nstf+nstv)*sizeof(real)*(3.0*natoms);
+    cio += nstxtc*(14*4 + nxtcatoms*5.0); /* roughly 5 bytes per atom */
+    cio += nstlog*(nrener*16*2.0); /* 16 bytes per energy term plus header */
+    /* t_energy contains doubles, but real is written to edr */
+    cio += (1.0*nste)*nrener*3*sizeof(real);
+
+    if ((ir->efep != efepNO || ir->bSimTemp) && (ir->fepvals->nstdhdl > 0))
+    {
+        int ndh=ir->fepvals->n_lambda;
+        int ndhdl=0;
+        int nchars=0;
+
+        for (i=0;i<efptNR;i++)
+        {
+            if (ir->fepvals->separate_dvdl[i])
+            {
+                ndhdl+=1;
+            }
+        }
+
+        if (ir->fepvals->separate_dhdl_file==esepdhdlfileYES)
+        {
+            nchars = 8 + ndhdl*8 + ndh*10; /* time data ~8 chars/entry, dH data ~10 chars/entry */
+            if (ir->expandedvals->elmcmove > elmcmoveNO)
+            {
+                nchars += 5;   /* alchemical state */
+            }
+            
+            if (ir->fepvals->bPrintEnergy)
+            {
+                nchars += 12; /* energy for dhdl */
+            }
+            cio += div_nsteps(nsteps,ir->fepvals->nstdhdl)*nchars; 
+        }
+        else
+        {
+            /* dH output to ener.edr: */
+            if (ir->fepvals->dh_hist_size <= 0)
+            {
+                int ndh_tot = ndh+ndhdl;
+                if (ir->expandedvals->elmcmove > elmcmoveNO)
+                {
+                    ndh_tot += 1;
+                }
+                if (ir->fepvals->bPrintEnergy)
+                {
+                    ndh_tot += 1;
+                }
+                /* as data blocks: 1 real per dH point */
+                cio += div_nsteps(nsteps,ir->fepvals->nstdhdl)*(ndh+ndhdl)*sizeof(real);
+            }
+            else
+            {
+                /* as histograms: dh_hist_size ints per histogram */
+                cio += div_nsteps(nsteps,ir->nstenergy)*
+                    sizeof(int)*ir->fepvals->dh_hist_size*ndh;
+            }
+        }
+    }
     if (ir->pull != NULL)
     {
         cio += div_nsteps(nsteps,ir->pull->nstxout)*20; /* roughly 20 chars per line */
         cio += div_nsteps(nsteps,ir->pull->nstfout)*20; /* roughly 20 chars per line */
-    }
+    }    
 
-  return cio*nrepl/(1024*1024);
+    return cio*nrepl/(1024*1024);
 }
index e88e408beb7b9a47fd334dc51b6f7be49c2de155..06328d5f3a50914e6b40fe3046d6c88cbfe75df1 100644 (file)
@@ -149,10 +149,14 @@ static void assign_param(t_functype ftype,t_iparams *newparam,
     newparam->cross_ba.krt=old[3];
     break;
   case F_UREY_BRADLEY:
-    newparam->u_b.theta=old[0];
-    newparam->u_b.ktheta=old[1];
-    newparam->u_b.r13=old[2];
-    newparam->u_b.kUB=old[3];
+    newparam->u_b.thetaA=old[0];
+    newparam->u_b.kthetaA=old[1];
+    newparam->u_b.r13A=old[2];
+    newparam->u_b.kUBA=old[3];
+    newparam->u_b.thetaB=old[4];
+    newparam->u_b.kthetaB=old[5];
+    newparam->u_b.r13B=old[6];
+    newparam->u_b.kUBB=old[7];
     break;
   case F_QUARTIC_ANGLES:
     newparam->qangle.theta=old[0];
@@ -165,8 +169,8 @@ static void assign_param(t_functype ftype,t_iparams *newparam,
     newparam->linangle.aB    = old[2];
     newparam->linangle.klinB = old[3];
     break;
-  case F_ANGLES:
   case F_BONDS:
+  case F_ANGLES:
   case F_HARMONIC:
   case F_IDIHS:
     newparam->harmonic.rA =old[0];
@@ -175,9 +179,12 @@ static void assign_param(t_functype ftype,t_iparams *newparam,
     newparam->harmonic.krB=old[3];
     break;
   case F_MORSE:
-    newparam->morse.b0    =old[0];
-    newparam->morse.cb    =old[1];
-    newparam->morse.beta  =old[2];
+    newparam->morse.b0A    =old[0];
+    newparam->morse.cbA    =old[1];
+    newparam->morse.betaA  =old[2];
+    newparam->morse.b0B    =old[3];
+    newparam->morse.cbB    =old[4];
+    newparam->morse.betaB  =old[5];
     break;
   case F_CUBICBONDS:
     newparam->cubic.b0    =old[0];
@@ -294,11 +301,12 @@ static void assign_param(t_functype ftype,t_iparams *newparam,
     newparam->orires.kfac  = old[5];
     break;
   case F_DIHRES:
-    newparam->dihres.label = round_check(old[0],0,ftype,"label");
-    newparam->dihres.phi   = old[1];
-    newparam->dihres.dphi  = old[2];
-    newparam->dihres.kfac  = old[3];
-    newparam->dihres.power = round_check(old[4],0,ftype,"power");
+    newparam->dihres.phiA  = old[0];
+    newparam->dihres.dphiA = old[1];
+    newparam->dihres.kfacA = old[2];
+    newparam->dihres.phiB   = old[3];
+    newparam->dihres.dphiB  = old[4];
+    newparam->dihres.kfacB  = old[5];
     break;
   case F_RBDIHS:
     for (i=0; (i<NR_RBDIHS); i++) {
index da0086e0d22d8b905433812e53e764d6dfcdc65d..6c3b1cac94dcd58d8ec162fc3660d3f49cbcdf3f 100644 (file)
@@ -215,7 +215,7 @@ static void chk_bonds(t_idef *idef,int ePBC,rvec *x,matrix box,real tol)
          b0 = idef->iparams[type].harmonic.rA;
          break;
        case F_MORSE:
-         b0 = idef->iparams[type].morse.b0;
+         b0 = idef->iparams[type].morse.b0A;
          break;
        case F_CUBICBONDS:
          b0 = idef->iparams[type].cubic.b0;
index bde3490087fa92a622e5c9ef8e5cd27cf8caebad..43aaa3e45b1a77bf374b51675cd0d6e644d3f2c6 100644 (file)
@@ -500,14 +500,6 @@ new_status(const char *topfile,const char *topppfile,const char *confin,
       warning_note(wi,warn_buf);
     }
   }
-  if (opts->bDihre == FALSE) {
-    i = rm_interactions(F_DIHRES,nrmols,molinfo);
-    if (i > 0) {
-      set_warning_line(wi,"unknown",-1);
-      sprintf(warn_buf,"dihre = no, removed %d dihedral restraints",i);
-      warning_note(wi,warn_buf);
-    }
-  }
   
   /* Copy structures from msys to sys */
   molinfo2mtop(nrmols,molinfo,sys);
@@ -528,7 +520,7 @@ new_status(const char *topfile,const char *topppfile,const char *confin,
     char title[STRLEN];
     snew(confat,1);
     init_t_atoms(confat,state->natoms,FALSE);
-    init_state(state,state->natoms,0,0,0);
+    init_state(state,state->natoms,0,0,0,0);
     read_stx_conf(confin,title,confat,state->x,state->v,NULL,state->box);
     /* This call fixes the box shape for runs with pressure scaling */
     set_box_rel(ir,state);
@@ -845,14 +837,24 @@ static void gen_posres(gmx_mtop_t *mtop,t_molinfo *mi,
 }
 
 static void set_wall_atomtype(gpp_atomtype_t at,t_gromppopts *opts,
-                             t_inputrec *ir)
+                              t_inputrec *ir,warninp_t wi)
 {
   int i;
+  char warn_buf[STRLEN];
 
   if (ir->nwall > 0)
-    fprintf(stderr,"Searching the wall atom type(s)\n");
+  {
+      fprintf(stderr,"Searching the wall atom type(s)\n");
+  }
   for(i=0; i<ir->nwall; i++)
-    ir->wall_atomtype[i] = get_atomtype_type(opts->wall_atomtype[i],at);
+  {
+      ir->wall_atomtype[i] = get_atomtype_type(opts->wall_atomtype[i],at);
+      if (ir->wall_atomtype[i] == NOTSET)
+      {
+          sprintf(warn_buf,"Specified wall atom type %s is not defined",opts->wall_atomtype[i]);
+          warning_error(wi,warn_buf);
+      }
+  }
 }
 
 static int nrdf_internal(t_atoms *atoms)
@@ -955,8 +957,9 @@ setup_cmap (int              grid_spacing,
        
        for(kk=0;kk<nc;kk++)
        {
-               /* Compute an offset depending on which cmap we are using                                 
-                * Offset will be the map number multiplied with the grid_spacing * grid_spacing * 2      
+               /* Compute an offset depending on which cmap we are using 
+                * Offset will be the map number multiplied with the 
+                 * grid_spacing * grid_spacing * 2
                 */
                offset = kk * grid_spacing * grid_spacing * 2;
                
@@ -1331,6 +1334,11 @@ int main (int argc, char *argv[])
     fprintf(stderr,"Setting the LD random seed to %d\n",ir->ld_seed);
   }
 
+  if (ir->expandedvals->lmc_seed == -1) {
+    ir->expandedvals->lmc_seed = make_seed();
+    fprintf(stderr,"Setting the lambda MC random seed to %d\n",ir->expandedvals->lmc_seed);
+  }
+
   bNeedVel = EI_STATE_VELOCITY(ir->eI);
   bGenVel  = (bNeedVel && opts->bGenVel);
 
@@ -1416,10 +1424,6 @@ int main (int argc, char *argv[])
             else
             {
                 fprintf(stderr," and %s\n",fnB);
-                if (ir->efep != efepNO && ir->n_flambda > 0)
-                {
-                    warning_error(wi,"Can not change the position restraint reference coordinates with lambda togther with foreign lambda calculation.");
-                }
             }
         }
         gen_posres(sys,mi,fn,fnB,
@@ -1449,7 +1453,7 @@ int main (int argc, char *argv[])
                setup_cmap(plist->grid_spacing, plist->nc, plist->cmap,&sys->ffparams.cmap_grid);
        }
        
-  set_wall_atomtype(atype,opts,ir);
+    set_wall_atomtype(atype,opts,ir,wi);
   if (bRenum) {
     renum_atype(plist, sys, ir->wall_atomtype, atype, bVerbose);
     ntype = get_atomtype_ntypes(atype);
@@ -1523,7 +1527,7 @@ int main (int argc, char *argv[])
            wi);
   
   /* Init the temperature coupling state */
-  init_gtc_state(&state,ir->opts.ngtc,0,ir->opts.nhchainlength);
+  init_gtc_state(&state,ir->opts.ngtc,0,ir->opts.nhchainlength); /* need to add nnhpres here? */
 
   if (bVerbose)
     fprintf(stderr,"Checking consistency between energy and charge groups...\n");
@@ -1586,22 +1590,26 @@ int main (int argc, char *argv[])
   /*  reset_multinr(sys); */
   
   if (EEL_PME(ir->coulombtype)) {
-    float ratio = pme_load_estimate(sys,ir,state.box);
-    fprintf(stderr,"Estimate for the relative computational load of the PME mesh part: %.2f\n",ratio);
-    /* With free energy we might need to do PME both for the A and B state
-     * charges. This will double the cost, but the optimal performance will
-     * then probably be at a slightly larger cut-off and grid spacing.
-     */
-    if ((ir->efep == efepNO && ratio > 1.0/2.0) ||
-        (ir->efep != efepNO && ratio > 2.0/3.0)) {
-        warning_note(wi,
-                     "The optimal PME mesh load for parallel simulations is below 0.5\n"
-                  "and for highly parallel simulations between 0.25 and 0.33,\n"
-                  "for higher performance, increase the cut-off and the PME grid spacing");
-    }
+      float ratio = pme_load_estimate(sys,ir,state.box);
+      fprintf(stderr,"Estimate for the relative computational load of the PME mesh part: %.2f\n",ratio);
+      /* With free energy we might need to do PME both for the A and B state
+       * charges. This will double the cost, but the optimal performance will
+       * then probably be at a slightly larger cut-off and grid spacing.
+       */
+      if ((ir->efep == efepNO && ratio > 1.0/2.0) ||
+          (ir->efep != efepNO && ratio > 2.0/3.0)) {
+          warning_note(wi,
+                       "The optimal PME mesh load for parallel simulations is below 0.5\n"
+                       "and for highly parallel simulations between 0.25 and 0.33,\n"
+                       "for higher performance, increase the cut-off and the PME grid spacing.\n");
+          if (ir->efep != efepNO) {
+              warning_note(wi,
+                           "For free energy simulations, the optimal load limit increases from 0.5 to 0.667\n");
+          }
+      }
   }
-
-    {
+  
+  {
         char warn_buf[STRLEN];
         double cio = compute_io(ir,sys->natoms,&sys->groups,F_NRE,1);
         sprintf(warn_buf,"This run will generate roughly %.0f Mb of data",cio);
@@ -1613,12 +1621,38 @@ int main (int argc, char *argv[])
         }
     }
        
+  /* MRS: eventually figure out better logic for initializing the fep
+   values that makes declaring the lambda and declaring the state not
+   potentially conflict if not handled correctly. */
+  if (ir->efep != efepNO)
+  {
+      state.fep_state = ir->fepvals->init_fep_state;
+      for (i=0;i<efptNR;i++)
+      {
+          /* init_lambda trumps state definitions*/
+          if (ir->fepvals->init_lambda >= 0)
+          {
+              state.lambda[i] = ir->fepvals->init_lambda;
+          }
+          else
+          {
+              if (ir->fepvals->all_lambda[i] == NULL)
+              {
+                  gmx_fatal(FARGS,"Values of lambda not set for a free energy calculation!");
+              }
+              else
+              {
+                  state.lambda[i] = ir->fepvals->all_lambda[i][state.fep_state];
+              }
+          }
+      }
+  }
+
   if (bVerbose) 
     fprintf(stderr,"writing run input file...\n");
 
   done_warning(wi,FARGS);
 
-  state.lambda = ir->init_lambda;
   write_tpx_state(ftp2fn(efTPX,NFILE,fnm),ir,&state,sys);
   
   thanx(stderr);
index d42b67a2a085f3eed30117a489387b2a06c49c55..1bc49aa79274c7c3408ea0e764606dcdff47ba34 100644 (file)
@@ -63,7 +63,6 @@
 #include "ionize.h"
 #include "disre.h"
 #include "orires.h"
-#include "dihre.h"
 #include "pme.h"
 #include "mdatoms.h"
 #include "repl_ex.h"
@@ -80,6 +79,7 @@
 #include "checkpoint.h"
 #include "mtop_util.h"
 #include "sighandler.h"
+#include "txtdump.h"
 #include "string2.h"
 #include "membed.h"
 
@@ -94,7 +94,6 @@
 #include "corewrap.h"
 #endif
 
-
 double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
              const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
              int nstglobalcomm,
@@ -106,7 +105,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
              t_mdatoms *mdatoms,
              t_nrnb *nrnb,gmx_wallcycle_t wcycle,
              gmx_edsam_t ed,t_forcerec *fr,
-             int repl_ex_nst,int repl_ex_seed,gmx_membed_t membed,
+             int repl_ex_nst,int repl_ex_nex,int repl_ex_seed,gmx_membed_t membed,
              real cpt_period,real max_hours,
              const char *deviceOptions,
              unsigned long Flags,
@@ -115,16 +114,16 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     gmx_mdoutf_t *outf;
     gmx_large_int_t step,step_rel;
     double     run_time;
-    double     t,t0,lam0;
-    gmx_bool       bGStatEveryStep,bGStat,bNstEner,bCalcEnerPres;
-    gmx_bool       bNS,bNStList,bSimAnn,bStopCM,bRerunMD,bNotLastFrame=FALSE,
+    double     t,t0,lam0[efptNR];
+    gmx_bool   bGStatEveryStep,bGStat,bNstEner,bCalcEnerPres,bEnergyHere;
+    gmx_bool   bNS,bNStList,bSimAnn,bStopCM,bRerunMD,bNotLastFrame=FALSE,
                bFirstStep,bStateFromCP,bStateFromTPX,bInitStep,bLastStep,
                bBornRadii,bStartingFromCpt;
-    gmx_bool       bDoDHDL=FALSE;
-    gmx_bool       do_ene,do_log,do_verbose,bRerunWarnNoV=TRUE,
+    gmx_bool   bDoDHDL=FALSE,bDoFEP=FALSE,bDoExpanded=FALSE;
+    gmx_bool   do_ene,do_log,do_verbose,bRerunWarnNoV=TRUE,
                bForceUpdate=FALSE,bCPT;
     int        mdof_flags;
-    gmx_bool       bMasterState;
+    gmx_bool   bMasterState;
     int        force_flags,cglo_flags;
     tensor     force_vir,shake_vir,total_vir,tmp_vir,pres;
     int        i,m;
@@ -137,9 +136,9 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     t_trxframe rerun_fr;
     gmx_repl_ex_t repl_ex=NULL;
     int        nchkpt=1;
-
     gmx_localtop_t *top;       
     t_mdebin *mdebin=NULL;
+    df_history_t df_history;
     t_state    *state=NULL;
     rvec       *f_global=NULL;
     int        n_xtc=-1;
@@ -150,7 +149,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     gmx_update_t upd=NULL;
     t_graph    *graph=NULL;
     globsig_t   gs;
-
+    gmx_rng_t mcrng=NULL;
     gmx_bool        bFFscan;
     gmx_groups_t *groups;
     gmx_ekindata_t *ekind, *ekind_save;
@@ -173,6 +172,11 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
        tensor      tmpvir;
        real        fom,oldfom,veta_save,pcurr,scalevir,tracevir;
        real        vetanew = 0;
+    int         lamnew=0;
+    /* for FEP */
+    int         fep_state=0;
+    int         nstfep;
+    real        rate;
     double      cycles;
        real        saved_conserved_quantity = 0;
     real        last_ekin = 0;
@@ -215,8 +219,8 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         snew(cbuf,top_global->natoms);
     }
     /* all the iteratative cases - only if there are constraints */ 
-    bIterations = ((IR_NPT_TROTTER(ir)) && (constr) && (!bRerunMD));
-    bTrotter = (bVV && (IR_NPT_TROTTER(ir) || (IR_NVT_TROTTER(ir))));        
+    bIterations = ((IR_NPH_TROTTER(ir) || IR_NPT_TROTTER(ir)) && (constr) && (!bRerunMD));
+    bTrotter = (bVV && (IR_NPT_TROTTER(ir) || IR_NPH_TROTTER(ir) || IR_NVT_TROTTER(ir)));
     
     if (bRerunMD)
     {
@@ -253,7 +257,8 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     groups = &top_global->groups;
 
     /* Initial values */
-    init_md(fplog,cr,ir,oenv,&t,&t0,&state_global->lambda,&lam0,
+    init_md(fplog,cr,ir,oenv,&t,&t0,state_global->lambda,
+            &(state_global->fep_state),lam0,
             nrnb,top_global,&upd,
             nfile,fnm,&outf,&mdebin,
             force_vir,shake_vir,mu_tot,&bSimAnn,&vcm,state_global,Flags);
@@ -262,7 +267,8 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     clear_mat(pres);
     /* Energy terms and groups */
     snew(enerd,1);
-    init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,enerd);
+    init_enerdata(top_global->groups.grps[egcENER].nr,ir->fepvals->n_lambda,
+                  enerd);
     if (DOMAINDECOMP(cr))
     {
         f = NULL;
@@ -272,6 +278,14 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         snew(f,top_global->natoms);
     }
 
+    /* lambda Monte carlo random number generator  */
+    if (ir->bExpanded)
+    {
+        mcrng = gmx_rng_init(ir->expandedvals->lmc_seed);
+    }
+    /* copy the state into df_history */
+    copy_df_history(&df_history,&state_global->dfhist);
+
     /* Kinetic energy data */
     snew(ekind,1);
     init_ekindata(fplog,top_global,&(ir->opts),ekind);
@@ -367,7 +381,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                             nrnb,wcycle,FALSE);
     }
 
-    update_mdatoms(mdatoms,state->lambda);
+    update_mdatoms(mdatoms,state->lambda[efptMASS]);
 
     if (opt2bSet("-cpi",nfile,fnm))
     {
@@ -400,11 +414,17 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         update_energyhistory(&state_global->enerhist,mdebin);
     }  
 
-    if ((state->flags & (1<<estLD_RNG)) && (Flags & MD_READ_RNG)) {
+    if ((state->flags & (1<<estLD_RNG)) && (Flags & MD_READ_RNG)) 
+    {
         /* Set the random state if we read a checkpoint file */
         set_stochd_state(upd,state);
     }
 
+    if (state->flags & (1<<estMC_RNG))
+    {
+        set_mc_state(mcrng,state);
+    }
+
     /* Initialize constraints */
     if (constr) {
         if (!DOMAINDECOMP(cr))
@@ -434,9 +454,10 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
          * signals are initialized, too */
     }
     if (repl_ex_nst > 0 && MASTER(cr))
+    {
         repl_ex = init_replica_exchange(fplog,cr->ms,state_global,ir,
-                                        repl_ex_nst,repl_ex_seed);
-
+                                        repl_ex_nst,repl_ex_nex,repl_ex_seed); 
+    }
     if (!ir->bContinuation && !bRerunMD)
     {
         if (mdatoms->cFREEZE && (state->flags & (1<<estV)))
@@ -470,7 +491,18 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     }
 
     debug_gmx();
-  
+
+    /* set free energy calculation frequency as the minimum of nstdhdl, nstexpanded, and nstrepl_ex_nst*/
+    nstfep = ir->fepvals->nstdhdl;
+    if (ir->bExpanded && (nstfep > ir->expandedvals->nstexpanded))
+    {
+        nstfep = ir->expandedvals->nstexpanded;
+    }
+    if (repl_ex_nst > 0 && repl_ex_nst > nstfep)
+    {
+        nstfep = repl_ex_nst;
+    }
+
     /* I'm assuming we need global communication the first time! MRS */
     cglo_flags = (CGLO_TEMPERATURE | CGLO_GSTAT
                   | ((ir->comm_mode != ecmNO) ? CGLO_STOPCM:0)
@@ -588,7 +620,9 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     print_date_and_time(fplog,cr->nodeid,"Started mdrun",runtime);
     wallcycle_start(wcycle,ewcRUN);
     if (fplog)
+    {
         fprintf(fplog,"\n");
+    }
 
     /* safest point to do file checkpointing is here.  More general point would be immediately before integrator call */
 #ifdef GMX_FAHCORE
@@ -708,18 +742,15 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             t = t0 + step*ir->delta_t;
         }
 
-        if (ir->efep != efepNO)
+        if (ir->efep != efepNO || ir->bSimTemp)
         {
-            if (bRerunMD && rerun_fr.bLambda && (ir->delta_lambda!=0))
-            {
-                state_global->lambda = rerun_fr.lambda;
-            }
-            else
-            {
-                state_global->lambda = lam0 + step*ir->delta_lambda;
-            }
-            state->lambda = state_global->lambda;
-            bDoDHDL = do_per_step(step,ir->nstdhdl);
+            /* find and set the current lambdas.  If rerunning, we either read in a state, or a lambda value,
+               requiring different logic. */
+            
+            set_current_lambdas(step,ir->fepvals,bRerunMD,&rerun_fr,state_global,state,lam0);
+            bDoDHDL = do_per_step(step,ir->fepvals->nstdhdl);
+            bDoFEP  = (do_per_step(step,nstfep) && (ir->efep != efepNO));
+            bDoExpanded  = (do_per_step(step,ir->expandedvals->nstexpanded) && (ir->bExpanded) && (step > 0));
         }
 
         if (bSimAnn) 
@@ -810,12 +841,12 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             /* Determine whether or not to do Neighbour Searching and LR */
             bNStList = (ir->nstlist > 0  && step % ir->nstlist == 0);
             
-            bNS = (bFirstStep || bExchanged || bNStList ||
+            bNS = (bFirstStep || bExchanged || bNStList || bDoFEP ||
                    (ir->nstlist == -1 && nlh.nabnsb > 0));
 
             if (bNS && ir->nstlist == -1)
             {
-                set_nlistheuristics(&nlh,bFirstStep || bExchanged,step);
+                set_nlistheuristics(&nlh,bFirstStep || bExchanged || bDoFEP, step);
             }
         } 
 
@@ -898,12 +929,12 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
 
         if (MASTER(cr) && do_log && !bFFscan)
         {
-            print_ebin_header(fplog,step,t,state->lambda);
+            print_ebin_header(fplog,step,t,state->lambda[efptFEP]); /* can we improve the information printed here? */
         }
 
         if (ir->efep != efepNO)
         {
-            update_mdatoms(mdatoms,state->lambda); 
+            update_mdatoms(mdatoms,state->lambda[efptMASS]);
         }
 
         if (bRerunMD && rerun_fr.bV)
@@ -958,10 +989,15 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         /* Determine the energy and pressure:
          * at nstcalcenergy steps and at energy output steps (set below).
          */
-        bNstEner = do_per_step(step,ir->nstcalcenergy);
+
+        if (EI_VV(ir->eI) && (!bInitStep)) {  /* for vv, the first half actually corresponds to the last step */
+            bNstEner = do_per_step(step-1,ir->nstcalcenergy);
+        } else {
+            bNstEner = do_per_step(step,ir->nstcalcenergy);
+        }
         bCalcEnerPres =
             (bNstEner ||
-             (ir->epc != epcNO && do_per_step(step,ir->nstpcouple)));
+             (ir->epc > epcNO && do_per_step(step,ir->nstpcouple)));
 
         /* Do we need global communication ? */
         bGStat = (bCalcEnerPres || bStopCM ||
@@ -987,7 +1023,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                        (bNStList ? GMX_FORCE_DOLR : 0) |
                        GMX_FORCE_SEPLRF |
                        (bCalcEnerPres ? GMX_FORCE_VIRIAL : 0) |
-                       (bDoDHDL ? GMX_FORCE_DHDL : 0)
+                       (bDoFEP ? GMX_FORCE_DHDL : 0)
             );
         
         if (shellfc)
@@ -1016,7 +1052,6 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
              * This is parallellized as well, and does communication too. 
              * Check comments in sim_util.c
              */
-        
             do_force(fplog,cr,ir,step,nrnb,wcycle,top,top_global,groups,
                      state->box,state->x,&state->hist,
                      f,force_vir,mdatoms,enerd,fcd,
@@ -1119,7 +1154,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                      called in the previous step */
                     unshift_self(graph,state->box,state->x);
                 }
-                
+
                 
                 /* if VV, compute the pressure and constraints */
                 /* For VV2, we strictly only need this if using pressure
@@ -1128,10 +1163,14 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                  * Think about ways around this in the future?
                  * For now, keep this choice in comments.
                  */
-                /*bPres = (ir->eI==eiVV || IR_NPT_TROTTER(ir)); */
-                    /*bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir)));*/
+                /* bPres = (ir->eI==eiVV || IR_NPT_TROTTER(ir)); */
+                /*bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir)));*/
                 bPres = TRUE;
                 bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK));
+                if (bNstEner && ir->eI==eiVVAK)  /*MRS:  7/9/2010 -- this still doesn't fix it?*/
+                {
+                    bSumEkinhOld = TRUE;
+                }
                 compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
                                 wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
                                 constr,NULL,FALSE,state->box,
@@ -1177,6 +1216,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             }
 
             if (bTrotter && !bInitStep) {
+                enerd->term[F_DVDL_BONDED] += dvdl;        /* only add after iterations */
                 copy_mat(shake_vir,state->svir_prev);
                 copy_mat(force_vir,state->fvir_prev);
                 if (IR_NVT_TROTTER(ir) && ir->eI==eiVV) {
@@ -1194,27 +1234,36 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             {
                 fprintf(fplog,sepdvdlformat,"Constraint",0.0,dvdl);
             }
-            enerd->term[F_DHDL_CON] += dvdl;
+            enerd->term[F_DVDL_BONDED] += dvdl;
             
             GMX_MPE_LOG(ev_timestep1);
         }
-    
+
         /* MRS -- now done iterating -- compute the conserved quantity */
         if (bVV) {
             saved_conserved_quantity = compute_conserved_from_auxiliary(ir,state,&MassQ);
             if (ir->eI==eiVV) 
             {
-                last_ekin = enerd->term[F_EKIN]; /* does this get preserved through checkpointing? */
+                last_ekin = enerd->term[F_EKIN];
             }
             if ((ir->eDispCorr != edispcEnerPres) && (ir->eDispCorr != edispcAllEnerPres)) 
             {
                 saved_conserved_quantity -= enerd->term[F_DISPCORR];
             }
+            /* sum up the foreign energy and dhdl terms for vv.  currently done every step so that dhdl is correct in the .edr */
+            sum_dhdl(enerd,state->lambda,ir->fepvals);
         }
         
         /* ########  END FIRST UPDATE STEP  ############## */
         /* ########  If doing VV, we now have v(dt) ###### */
-        
+        if (bDoExpanded) {
+            /* perform extended ensemble sampling in lambda - we don't
+               actually move to the new state before outputting
+               statistics, but if performing simulated tempering, we
+               do update the velocities and the tau_t. */
+
+            lamnew = ExpandedEnsembleDynamics(fplog,ir,enerd,state,&MassQ,&df_history,step,mcrng,state->v,mdatoms);
+        }
         /* ################## START TRAJECTORY OUTPUT ################# */
         
         /* Now we have the energies and forces corresponding to the 
@@ -1256,6 +1305,10 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                 {
                     get_stochd_state(upd,state);
                 }
+                if (state->flags  & (1<<estMC_RNG))
+                {
+                    get_mc_state(mcrng,state);
+                }
                 if (MASTER(cr))
                 {
                     if (bSumEkinhOld)
@@ -1268,6 +1321,14 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                         state_global->ekinstate.bUpToDate = TRUE;
                     }
                     update_energyhistory(&state_global->enerhist,mdebin);
+                    if (ir->efep!=efepNO || ir->bSimTemp) 
+                    {
+                        state_global->fep_state = state->fep_state; /* MRS: seems kludgy. The code should be
+                                                                       structured so this isn't necessary.
+                                                                       Note this reassignment is only necessary
+                                                                       for single threads.*/
+                        copy_df_history(&state_global->dfhist,&df_history);
+                    }
                 }
             }
             write_traj(fplog,cr,outf,mdof_flags,top_global,
@@ -1311,9 +1372,30 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         }
         /*  ################## END TRAJECTORY OUTPUT ################ */
         
+        /* Determine the pressure:
+         * always when we want exact averages in the energy file,
+         * at ns steps when we have pressure coupling,
+         * otherwise only at energy output steps (set below).
+         */
+
+        
+        bNstEner = (bGStatEveryStep || do_per_step(step,ir->nstcalcenergy));
+        bCalcEnerPres = bNstEner;
+
+        /* Do we need global communication ? */
+        bGStat = (bGStatEveryStep || bStopCM || bNS ||
+                  (ir->nstlist == -1 && !bRerunMD && step >= nlh.step_nscheck));
+
+        do_ene = (do_per_step(step,ir->nstenergy) || bLastStep);
+
+        if (do_ene || do_log)
+        {
+            bCalcEnerPres = TRUE;
+            bGStat        = TRUE;
+        }
+
         /* Determine the wallclock run time up till now */
         run_time = gmx_gettime() - (double)runtime->real;
-
         /* Check whether everything is still allright */    
         if (((int)gmx_get_stop_condition() > handled_stop_condition)
 #ifdef GMX_THREAD_MPI
@@ -1400,7 +1482,23 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         {
             gs.sig[eglsCHKPT] = 1;
         }
-  
+
+
+        /* at the start of step, randomize the velocities */
+        if (ETC_ANDERSEN(ir->etc) && EI_VV(ir->eI))
+        {
+            gmx_bool bDoAndersenConstr;
+            bDoAndersenConstr = update_randomize_velocities(ir,step,mdatoms,state,upd,&top->idef,constr);
+            /* if we have constraints, we have to remove the kinetic energy parallel to the bonds */
+            if (bDoAndersenConstr)
+            {
+                update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
+                                   &top->idef,tmp_vir,NULL,
+                                   cr,nrnb,wcycle,upd,constr,
+                                   bInitStep,TRUE,FALSE,vetanew);
+            }
+        }
+
         if (bIterations)
         {
             gmx_iterate_init(&iterate,bIterations);
@@ -1497,7 +1595,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                                    cr,nrnb,wcycle,upd,constr,
                                    bInitStep,FALSE,bCalcEnerPres,state->veta);  
                 
-                if (ir->eI==eiVVAK) 
+                if (ir->eI==eiVVAK)
                 {
                     /* erase F_EKIN and F_TEMP here? */
                     /* just compute the kinetic energy at the half step to perform a trotter step */
@@ -1505,7 +1603,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                                     wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
                                     constr,NULL,FALSE,lastbox,
                                     top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
-                                    cglo_flags | CGLO_TEMPERATURE    
+                                    cglo_flags | CGLO_TEMPERATURE
                         );
                     wallcycle_start(wcycle,ewcUPDATE);
                     trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ4);            
@@ -1534,9 +1632,9 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                 
                 if (fr->bSepDVDL && fplog && do_log) 
                 {
-                    fprintf(fplog,sepdvdlformat,"Constraint",0.0,dvdl);
+                    fprintf(fplog,sepdvdlformat,"Constraint dV/dl",0.0,dvdl);
                 }
-                enerd->term[F_DHDL_CON] += dvdl;
+                enerd->term[F_DVDL_BONDED] += dvdl;
             } 
             else if (graph) 
             {
@@ -1570,6 +1668,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             {
                 gs.sig[eglsNABNSB] = nlh.nabnsb;
             }
+            bEnergyHere = (!EI_VV(ir->eI) || (EI_VV(ir->eI) && bRerunMD)); /* this is not quite working for vv and rerun! fails for running rerun on multiple threads. This is caught in runner.c. */
             compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
                             wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
                             constr,
@@ -1582,10 +1681,10 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                             | (!EI_VV(ir->eI) ? CGLO_ENERGY : 0) 
                             | (!EI_VV(ir->eI) && bStopCM ? CGLO_STOPCM : 0)
                             | (!EI_VV(ir->eI) ? CGLO_TEMPERATURE : 0) 
-                            | (!EI_VV(ir->eI) || bRerunMD ? CGLO_PRESSURE : 0) 
+                            | (bEnergyHere || bRerunMD ? CGLO_PRESSURE : 0) 
                             | (bIterations && iterate.bIterate ? CGLO_ITERATE : 0) 
                             | (bFirstIterate ? CGLO_FIRSTITERATE : 0)
-                            | CGLO_CONSTRAINT 
+                            | CGLO_CONSTRAINT
                 );
             if (ir->nstlist == -1 && bFirstIterate)
             {
@@ -1609,6 +1708,13 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             bFirstIterate = FALSE;
         }
 
+        /* only add constraint dvdl after constraints */
+        enerd->term[F_DVDL_BONDED] += dvdl;
+        if (!bVV)
+        {
+            /* sum up the foreign energy and dhdl terms for md and sd. currently done every step so that dhdl is correct in the .edr */
+            sum_dhdl(enerd,state->lambda,ir->fepvals);
+        }
         update_box(fplog,step,ir,mdatoms,state,graph,f,
                    ir->nstlist==-1 ? &nlh.scale_tot : NULL,pcoupl_mu,nrnb,wcycle,upd,bInitStep,FALSE);
         
@@ -1657,9 +1763,6 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         }
 
         /* #########  BEGIN PREPARING EDR OUTPUT  ###########  */
-        
-        /* sum up the foreign energy and dhdl terms */
-        sum_dhdl(enerd,state->lambda,ir);
 
         /* use the directly determined last velocity, not actually the averaged half steps */
         if (bTrotter && ir->eI==eiVV) 
@@ -1703,12 +1806,19 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         {
             gmx_bool do_dr,do_or;
             
+            if (fplog && do_log && bDoExpanded)
+            {
+                /* only needed if doing expanded ensemble */
+                PrintFreeEnergyInfoToFile(fplog,ir->fepvals,ir->expandedvals,ir->bSimTemp?ir->simtempvals:NULL,
+                                          &df_history,state->fep_state,ir->nstlog,step);
+            }
             if (!(bStartingFromCpt && (EI_VV(ir->eI)))) 
             {
                 if (bNstEner)
                 {
-                    upd_mdebin(mdebin,bDoDHDL, TRUE,
-                               t,mdatoms->tmass,enerd,state,lastbox,
+                    upd_mdebin(mdebin,bDoDHDL,TRUE,
+                               t,mdatoms->tmass,enerd,state,
+                               ir->fepvals,ir->expandedvals,lastbox,
                                shake_vir,force_vir,total_vir,pres,
                                ekind,mu_tot,constr);
                 }
@@ -1737,8 +1847,15 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                 }
             }
         }
-
-
+        if (bDoExpanded)
+        {
+            /* Have to do this part after outputting the logfile and the edr file */
+            state->fep_state = lamnew;
+            for (i=0;i<efptNR;i++)
+            {
+                state->lambda[i] = ir->fepvals->all_lambda[i][lamnew];
+            }
+        }
         /* Remaining runtime */
         if (MULTIMASTER(cr) && (do_verbose || gmx_got_usr_signal() ))
         {
@@ -1755,7 +1872,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             do_per_step(step,repl_ex_nst)) 
         {
             bExchanged = replica_exchange(fplog,cr,repl_ex,
-                                          state_global,enerd->term,
+                                          state_global,enerd,
                                           state,step,t);
 
             if (bExchanged && DOMAINDECOMP(cr)) 
index 1bcb07488a99bb97fad10dec22f4f5d6b214452d..30e2e0f3ecf66b268117b8396f1b8e12a73af044 100644 (file)
@@ -66,7 +66,6 @@
 #include "ionize.h"
 #include "disre.h"
 #include "orires.h"
-#include "dihre.h"
 #include "pme.h"
 #include "mdatoms.h"
 #include "qmmm.h"
@@ -104,7 +103,7 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                     t_mdatoms *mdatoms,
                     t_nrnb *nrnb,gmx_wallcycle_t wcycle,
                     gmx_edsam_t ed,t_forcerec *fr,
-                    int repl_ex_nst,int repl_ex_seed,
+                    int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
                     gmx_membed_t membed,
                     real cpt_period,real max_hours,
                     const char *deviceOptions,
@@ -164,7 +163,8 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     groups = &top_global->groups;
 
     /* Initial values */
-    init_md(fplog,cr,ir,oenv,&t,&t0,&state_global->lambda,&lam0,
+    init_md(fplog,cr,ir,oenv,&t,&t0,state_global->lambda,
+            &(state_global->fep_state),&lam0,
             nrnb,top_global,&upd,
             nfile,fnm,&outf,&mdebin,
             force_vir,shake_vir,mu_tot,&bSimAnn,&vcm,state_global,Flags);
@@ -173,7 +173,8 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     clear_mat(pres);
     /* Energy terms and groups */
     snew(enerd,1);
-    init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,enerd);
+    init_enerdata(top_global->groups.grps[egcENER].nr,ir->fepvals->n_lambda,
+                  enerd);
     snew(f,top_global->natoms);
 
     /* Kinetic energy data */
@@ -216,7 +217,7 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         graph = mk_graph(fplog,&(top->idef),0,top_global->natoms,FALSE,FALSE);
     }
 
-    update_mdatoms(mdatoms,state->lambda);
+    update_mdatoms(mdatoms,state->lambda[efptMASS]);
 
     if (deviceOptions[0]=='\0')
     {
@@ -371,7 +372,7 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
 
         if (MASTER(cr) && do_log)
         {
-            print_ebin_header(fplog,step,t,state->lambda);
+            print_ebin_header(fplog,step,t,state->lambda[efptFEP]);
         }
 
         clear_mat(force_vir);
@@ -430,7 +431,7 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             openmm_copy_state(openmmData, state, &t, f, enerd, bX, bV, bF, do_ene);
 
             upd_mdebin(mdebin,FALSE,TRUE,
-                       t,mdatoms->tmass,enerd,state,lastbox,
+                       t,mdatoms->tmass,enerd,state,ir->fepvals,ir->expandedvals,lastbox,
                        shake_vir,force_vir,total_vir,pres,
                        ekind,mu_tot,constr);
             print_ebin(outf->fp_ene,do_ene,FALSE,FALSE,do_log?fplog:NULL,
index 3bb95ce1d4da37102d04e2a50739c7736cac852b..0cf3172cc61a5edec9357d676f794563b72dd800 100644 (file)
@@ -46,7 +46,7 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
              t_mdatoms *mdatoms,
              t_nrnb *nrnb,gmx_wallcycle_t wcycle,
              gmx_edsam_t ed,t_forcerec *fr,
-             int repl_ex_nst,int repl_ex_seed,
+             int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
              gmx_membed_t membed,
              real cpt_period,real max_hours,
              const char *deviceOptions,
index 9c74add3e0ea2a0edf9882bfa92b34de78bf1139..1d011082be2a359a5c38c0576bea30aeccfcd35a 100644 (file)
@@ -414,6 +414,7 @@ int main(int argc,char *argv[])
   int  nstglobalcomm=-1;
   int  repl_ex_nst=0;
   int  repl_ex_seed=-1;
+  int  repl_ex_nex=0;
   int  nstepout=100;
   int  nthreads=0; /* set to determine # of threads automatically */
   int  resetstep=-1;
@@ -488,6 +489,8 @@ int main(int argc,char *argv[])
       "Do multiple simulations in parallel" },
     { "-replex",  FALSE, etINT, {&repl_ex_nst}, 
       "Attempt replica exchange periodically with this period (steps)" },
+    { "-nex",  FALSE, etINT, {&repl_ex_nex},
+      "Number of random exchanges to carry out each exchange interval (N^3 is one suggestion).  -nex zero or not specified gives neighbor replica exchange." },
     { "-reseed",  FALSE, etINT, {&repl_ex_seed}, 
       "Seed for replica exchange, -1 is generate a seed" },
     { "-rerunvsite", FALSE, etBOOL, {&bRerunVSite},
@@ -571,6 +574,9 @@ int main(int argc,char *argv[])
   if (repl_ex_nst != 0 && nmultisim < 2)
       gmx_fatal(FARGS,"Need at least two replicas for replica exchange (option -multi)");
 
+  if (repl_ex_nex < 0)
+      gmx_fatal(FARGS,"Replica exchange number of exchanges needs to be positive");
+
   if (nmultisim > 1) {
 #ifndef GMX_THREAD_MPI
     gmx_bool bParFn = (multidir == NULL);
@@ -679,7 +685,7 @@ int main(int argc,char *argv[])
   rc = mdrunner(nthreads, fplog,cr,NFILE,fnm,oenv,bVerbose,bCompact,
                 nstglobalcomm, ddxyz,dd_node_order,rdd,rconstr,
                 dddlb_opt[0],dlb_scale,ddcsx,ddcsy,ddcsz,
-                nstepout,resetstep,nmultisim,repl_ex_nst,repl_ex_seed,
+                nstepout,resetstep,nmultisim,repl_ex_nst,repl_ex_nex,repl_ex_seed,
                 pforce, cpt_period,max_hours,deviceOptions,Flags);
 
   gmx_finalize_par();
index 9c1d3da3d8efb5968430eee0f18886de86848408..5ec50e6620ab7e00dbf7698cf5e70a14baa18738 100644 (file)
@@ -64,6 +64,7 @@
 
 #define MAXPTR 254
 #define NOGID  255
+#define MAXLAMBDAS 1024
 
 /* Resource parameters 
  * Do not change any of these until you read the instruction
@@ -77,7 +78,8 @@ static char tcgrps[STRLEN],tau_t[STRLEN],ref_t[STRLEN],
   energy[STRLEN],user1[STRLEN],user2[STRLEN],vcm[STRLEN],xtc_grps[STRLEN],
   couple_moltype[STRLEN],orirefitgrp[STRLEN],egptable[STRLEN],egpexcl[STRLEN],
   wall_atomtype[STRLEN],wall_density[STRLEN],deform[STRLEN],QMMM[STRLEN];
-static char foreign_lambda[STRLEN];
+static char fep_lambda[efptNR][STRLEN];
+static char lambda_weights[STRLEN];
 static char **pull_grp;
 static char **rot_grp;
 static char anneal[STRLEN],anneal_npoints[STRLEN],
@@ -103,8 +105,42 @@ void init_ir(t_inputrec *ir, t_gromppopts *opts)
 {
   snew(opts->include,STRLEN); 
   snew(opts->define,STRLEN);
+  snew(ir->fepvals,1);
+  snew(ir->expandedvals,1);
+  snew(ir->simtempvals,1);
 }
 
+static void GetSimTemps(int ntemps, t_simtemp *simtemp, double *temperature_lambdas)
+{
+
+    int i;
+
+    for (i=0;i<ntemps;i++)
+    {
+        /* simple linear scaling -- allows more control */
+        if (simtemp->eSimTempScale == esimtempLINEAR)
+        {
+            simtemp->temperatures[i] = simtemp->simtemp_low + (simtemp->simtemp_high-simtemp->simtemp_low)*temperature_lambdas[i];
+        }
+        else if (simtemp->eSimTempScale == esimtempGEOMETRIC)  /* should give roughly equal acceptance for constant heat capacity . . . */
+        {
+            simtemp->temperatures[i] = simtemp->simtemp_low * pow(simtemp->simtemp_high/simtemp->simtemp_low,(1.0*i)/(ntemps-1));
+        }
+        else if (simtemp->eSimTempScale == esimtempEXPONENTIAL)
+        {
+            simtemp->temperatures[i] = simtemp->simtemp_low + (simtemp->simtemp_high-simtemp->simtemp_low)*((exp(temperature_lambdas[i])-1)/(exp(1.0)-1));
+        }
+        else
+        {
+            char errorstr[128];
+            sprintf(errorstr,"eSimTempScale=%d not defined",simtemp->eSimTempScale);
+            gmx_fatal(FARGS,errorstr);
+        }
+    }
+}
+
+
+
 static void _low_check(gmx_bool b,char *s,warninp_t wi)
 {
     if (b)
@@ -160,8 +196,13 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
      */
 #define CHECK(b) _low_check(b,err_buf,wi)
     char err_buf[256],warn_buf[STRLEN];
+    int i,j;
     int  ns_type=0;
+    real dt_coupl=0;
     real dt_pcoupl;
+    int  nstcmin;
+    t_lambda *fep = ir->fepvals;
+    t_expanded *expand = ir->expandedvals;
 
   set_warning_line(wi,mdparin,-1);
 
@@ -194,6 +235,10 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
     {
         ir->etc = etcNO;
     }
+    if (ir->eI == eiVVAK) {
+        sprintf(warn_buf,"Integrator method %s is implemented primarily for validation purposes; for molecular dynamics, you should probably be using %s or %s",ei_names[eiVVAK],ei_names[eiMD],ei_names[eiVV]);
+        warning_note(wi,warn_buf);
+    }
     if (!EI_DYNAMICS(ir->eI))
     {
         ir->epc = epcNO;
@@ -247,7 +292,7 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
             {
                 /* nstdhdl should be a multiple of nstcalcenergy */
                 check_nst("nstcalcenergy",ir->nstcalcenergy,
-                          "nstdhdl",&ir->nstdhdl,wi);
+                          "nstdhdl",&ir->fepvals->nstdhdl,wi);
             }
         }
     }
@@ -272,16 +317,207 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
 
   /* SHAKE / LINCS */
   if ( (opts->nshake > 0) && (opts->bMorse) ) {
-    sprintf(warn_buf,
-           "Using morse bond-potentials while constraining bonds is useless");
-    warning(wi,warn_buf);
+      sprintf(warn_buf,
+              "Using morse bond-potentials while constraining bonds is useless");
+      warning(wi,warn_buf);
   }
-  
-  sprintf(err_buf,"shake_tol must be > 0 instead of %g while using shake",
-         ir->shake_tol);
-  CHECK(((ir->shake_tol <= 0.0) && (opts->nshake>0) && 
-        (ir->eConstrAlg == econtSHAKE)));
-     
+
+  if ((EI_SD(ir->eI) || ir->eI == eiBD) &&
+      ir->bContinuation && ir->ld_seed != -1) {
+      warning_note(wi,"You are doing a continuation with SD or BD, make sure that ld_seed is different from the previous run (using ld_seed=-1 will ensure this)");
+  }
+  /* verify simulated tempering options */
+
+  if (ir->bSimTemp) {
+      gmx_bool bAllTempZero = TRUE;
+      for (i=0;i<fep->n_lambda;i++)
+      {
+          sprintf(err_buf,"Entry %d for %s must be between 0 and 1, instead is %g",i,efpt_names[efptTEMPERATURE],fep->all_lambda[efptTEMPERATURE][i]);
+          CHECK((fep->all_lambda[efptTEMPERATURE][i] < 0) || (fep->all_lambda[efptTEMPERATURE][i] > 1));
+          if (fep->all_lambda[efptTEMPERATURE][i] > 0)
+          {
+              bAllTempZero = FALSE;
+          }
+      }
+      sprintf(err_buf,"if simulated tempering is on, temperature-lambdas may not be all zero");
+      CHECK(bAllTempZero==TRUE);
+
+      sprintf(err_buf,"Simulated tempering is currently only compatible with md-vv");
+      CHECK(ir->eI != eiVV);
+
+      /* check compatability of the temperature coupling with simulated tempering */
+
+      if (ir->etc == etcNOSEHOOVER) {
+          sprintf(warn_buf,"Nose-Hoover based temperature control such as [%s] my not be entirelyconsistent with simulated tempering",etcoupl_names[ir->etc]);
+          warning_note(wi,warn_buf);
+      }
+
+      /* check that the temperatures make sense */
+
+      sprintf(err_buf,"Higher simulated tempering temperature (%g) must be >= than the simulated tempering lower temperature (%g)",ir->simtempvals->simtemp_high,ir->simtempvals->simtemp_low);
+      CHECK(ir->simtempvals->simtemp_high <= ir->simtempvals->simtemp_low);
+
+      sprintf(err_buf,"Higher simulated tempering temperature (%g) must be >= zero",ir->simtempvals->simtemp_high);
+      CHECK(ir->simtempvals->simtemp_high <= 0);
+
+      sprintf(err_buf,"Lower simulated tempering temperature (%g) must be >= zero",ir->simtempvals->simtemp_low);
+      CHECK(ir->simtempvals->simtemp_low <= 0);
+  }
+
+  /* verify free energy options */
+
+  if (ir->efep != efepNO) {
+      fep = ir->fepvals;
+      sprintf(err_buf,"The soft-core power is %d and can only be 1 or 2",
+              fep->sc_power);
+      CHECK(fep->sc_alpha!=0 && fep->sc_power!=1 && fep->sc_power!=2);
+
+      sprintf(err_buf,"The soft-core sc-r-power is %d and can only be 6 or 48",
+              (int)fep->sc_r_power);
+      CHECK(fep->sc_alpha!=0 && fep->sc_r_power!=6.0 && fep->sc_r_power!=48.0);
+
+      /* check validity of options */
+      if (fep->n_lambda > 0 && ir->rlist < max(ir->rvdw,ir->rcoulomb))
+      {
+          sprintf(warn_buf,
+                  "For foreign lambda free energy differences it is assumed that the soft-core interactions have no effect beyond the neighborlist cut-off");
+          warning(wi,warn_buf);
+      }
+
+      sprintf(err_buf,"Can't use postive delta-lambda (%g) if initial state/lambda does not start at zero",fep->delta_lambda);
+      CHECK(fep->delta_lambda > 0 && ((fep->init_fep_state !=0) ||  (fep->init_lambda !=0)));
+
+      sprintf(err_buf,"Can't use postive delta-lambda (%g) with expanded ensemble simulations",fep->delta_lambda);
+      CHECK(fep->delta_lambda > 0 && (ir->efep == efepEXPANDED));
+
+      sprintf(err_buf,"Free-energy not implemented for Ewald");
+      CHECK(ir->coulombtype==eelEWALD);
+
+      /* check validty of lambda inputs */
+      sprintf(err_buf,"initial thermodynamic state %d does not exist, only goes to %d",fep->init_fep_state,fep->n_lambda);
+      CHECK((fep->init_fep_state > fep->n_lambda));
+
+      for (j=0;j<efptNR;j++)
+      {
+          for (i=0;i<fep->n_lambda;i++)
+          {
+              sprintf(err_buf,"Entry %d for %s must be between 0 and 1, instead is %g",i,efpt_names[j],fep->all_lambda[j][i]);
+              CHECK((fep->all_lambda[j][i] < 0) || (fep->all_lambda[j][i] > 1));
+          }
+      }
+
+      if ((fep->sc_alpha>0) && (!fep->bScCoul))
+      {
+          for (i=0;i<fep->n_lambda;i++)
+          {
+              sprintf(err_buf,"For state %d, vdw-lambdas (%f) is changing with vdw softcore, while coul-lambdas (%f) is nonzero without coulomb softcore: this will lead to crashes, and is not supported.",i,fep->all_lambda[efptVDW][i],
+                      fep->all_lambda[efptCOUL][i]);
+              CHECK((fep->sc_alpha>0) &&
+                    (((fep->all_lambda[efptCOUL][i] > 0.0) &&
+                      (fep->all_lambda[efptCOUL][i] < 1.0)) &&
+                     ((fep->all_lambda[efptVDW][i] > 0.0) &&
+                      (fep->all_lambda[efptVDW][i] < 1.0))));
+          }
+      }
+
+      if ((fep->bScCoul) && (EEL_PME(ir->coulombtype)))
+      {
+          sprintf(warn_buf,"With coulomb soft core, the reciprocal space calculation will not necessarily cancel.  It may be necessary to decrease the reciprocal space energy, and increase the cutoff radius to get sufficiently close matches to energies with free energy turned off.");
+          warning(wi, warn_buf);
+      }
+
+      /*  Free Energy Checks -- In an ideal world, slow growth and FEP would
+          be treated differently, but that's the next step */
+
+      for (i=0;i<efptNR;i++) {
+          for (j=0;j<fep->n_lambda;j++) {
+              sprintf(err_buf,"%s[%d] must be between 0 and 1",efpt_names[i],j);
+              CHECK((fep->all_lambda[i][j] < 0) || (fep->all_lambda[i][j] > 1));
+          }
+      }
+  }
+
+  if ((ir->bSimTemp) || (ir->efep == efepEXPANDED)) {
+      fep = ir->fepvals;
+      expand = ir->expandedvals;
+
+      /* checking equilibration of weights inputs for validity */
+
+      sprintf(err_buf,"weight-equil-number-all-lambda (%d) is ignored if lmc-weights-equil is not equal to %s",
+              expand->equil_n_at_lam,elmceq_names[elmceqNUMATLAM]);
+      CHECK((expand->equil_n_at_lam>0) && (expand->elmceq!=elmceqNUMATLAM));
+
+      sprintf(err_buf,"weight-equil-number-samples (%d) is ignored if lmc-weights-equil is not equal to %s",
+              expand->equil_samples,elmceq_names[elmceqSAMPLES]);
+      CHECK((expand->equil_samples>0) && (expand->elmceq!=elmceqSAMPLES));
+
+      sprintf(err_buf,"weight-equil-number-steps (%d) is ignored if lmc-weights-equil is not equal to %s",
+              expand->equil_steps,elmceq_names[elmceqSTEPS]);
+      CHECK((expand->equil_steps>0) && (expand->elmceq!=elmceqSTEPS));
+
+      sprintf(err_buf,"weight-equil-wl-delta (%d) is ignored if lmc-weights-equil is not equal to %s",
+              expand->equil_samples,elmceq_names[elmceqWLDELTA]);
+      CHECK((expand->equil_wl_delta>0) && (expand->elmceq!=elmceqWLDELTA));
+
+      sprintf(err_buf,"weight-equil-count-ratio (%f) is ignored if lmc-weights-equil is not equal to %s",
+              expand->equil_ratio,elmceq_names[elmceqRATIO]);
+      CHECK((expand->equil_ratio>0) && (expand->elmceq!=elmceqRATIO));
+
+      sprintf(err_buf,"weight-equil-number-all-lambda (%d) must be a positive integer if lmc-weights-equil=%s",
+              expand->equil_n_at_lam,elmceq_names[elmceqNUMATLAM]);
+      CHECK((expand->equil_n_at_lam<=0) && (expand->elmceq==elmceqNUMATLAM));
+
+      sprintf(err_buf,"weight-equil-number-samples (%d) must be a positive integer if lmc-weights-equil=%s",
+              expand->equil_samples,elmceq_names[elmceqSAMPLES]);
+      CHECK((expand->equil_samples<=0) && (expand->elmceq==elmceqSAMPLES));
+
+      sprintf(err_buf,"weight-equil-number-steps (%d) must be a positive integer if lmc-weights-equil=%s",
+              expand->equil_steps,elmceq_names[elmceqSTEPS]);
+      CHECK((expand->equil_steps<=0) && (expand->elmceq==elmceqSTEPS));
+
+      sprintf(err_buf,"weight-equil-wl-delta (%f) must be > 0 if lmc-weights-equil=%s",
+              expand->equil_wl_delta,elmceq_names[elmceqWLDELTA]);
+      CHECK((expand->equil_wl_delta<=0) && (expand->elmceq==elmceqWLDELTA));
+
+      sprintf(err_buf,"weight-equil-count-ratio (%f) must be > 0 if lmc-weights-equil=%s",
+              expand->equil_ratio,elmceq_names[elmceqRATIO]);
+      CHECK((expand->equil_ratio<=0) && (expand->elmceq==elmceqRATIO));
+
+      sprintf(err_buf,"lmc-weights-equil=%s only possible when lmc-stats = %s or lmc-stats %s",
+              elmceq_names[elmceqWLDELTA],elamstats_names[elamstatsWL],elamstats_names[elamstatsWWL]);
+      CHECK((expand->elmceq==elmceqWLDELTA) && (!EWL(expand->elamstats)));
+
+      sprintf(err_buf,"lmc-repeats (%d) must be greater than 0",expand->lmc_repeats);
+      CHECK((expand->lmc_repeats <= 0));
+      sprintf(err_buf,"minimum-var-min (%d) must be greater than 0",expand->minvarmin);
+      CHECK((expand->minvarmin <= 0));
+      sprintf(err_buf,"weight-c-range (%d) must be greater or equal to 0",expand->c_range);
+      CHECK((expand->c_range < 0));
+      sprintf(err_buf,"init-lambda-state (%d) must be zero if lmc-forced-nstart (%d)> 0 and lmc-move != 'no'",
+              fep->init_fep_state, expand->lmc_forced_nstart);
+      CHECK((fep->init_fep_state!=0) && (expand->lmc_forced_nstart>0) && (expand->elmcmove!=elmcmoveNO));
+      sprintf(err_buf,"lmc-forced-nstart (%d) must not be negative",expand->lmc_forced_nstart);
+      CHECK((expand->lmc_forced_nstart < 0));
+      sprintf(err_buf,"init-lambda-state (%d) must be in the interval [0,number of lambdas)",fep->init_fep_state);
+      CHECK((fep->init_fep_state < 0) || (fep->init_fep_state >= fep->n_lambda));
+
+      sprintf(err_buf,"init-wl-delta (%f) must be greater than or equal to 0",expand->init_wl_delta);
+      CHECK((expand->init_wl_delta < 0));
+      sprintf(err_buf,"wl-ratio (%f) must be between 0 and 1",expand->wl_ratio);
+      CHECK((expand->wl_ratio <= 0) || (expand->wl_ratio >= 1));
+      sprintf(err_buf,"wl-scale (%f) must be between 0 and 1",expand->wl_scale);
+      CHECK((expand->wl_scale <= 0) || (expand->wl_scale >= 1));
+
+      /* if there is no temperature control, we need to specify an MC temperature */
+      sprintf(err_buf,"If there is no temperature control, and lmc-mcmove!= 'no',mc_temperature must be set to a positive number");
+      if (expand->nstTij > 0)
+      {
+          sprintf(err_buf,"nst-transition-matrix (%d) must be an integer multiple of nstlog (%d)",
+                  expand->nstTij,ir->nstlog);
+          CHECK((mod(expand->nstTij,ir->nstlog)!=0));
+      }
+  }
+
   /* PBC/WALLS */
   sprintf(err_buf,"walls only work with pbc=%s",epbc_names[epbcXY]);
   CHECK(ir->nwall && ir->ePBC!=epbcXY);
@@ -300,7 +536,7 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
     }
     sprintf(err_buf,"Can not have Ewald with pbc=%s",epbc_names[ir->ePBC]);
     CHECK(EEL_FULL(ir->coulombtype));
-    
+
     sprintf(err_buf,"Can not have dispersion correction with pbc=%s",
            epbc_names[ir->ePBC]);
     CHECK(ir->eDispCorr != edispcNO);
@@ -313,7 +549,7 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
            "rcoulomb and rvdw set to zero",
            eel_names[eelCUT],eel_names[eelUSER],epbc_names[epbcNONE]);
     CHECK(((ir->coulombtype != eelCUT) && (ir->coulombtype != eelUSER)) ||
-         (ir->ePBC     != epbcNONE) || 
+         (ir->ePBC     != epbcNONE) ||
          (ir->rcoulomb != 0.0)      || (ir->rvdw != 0.0));
 
     if (ir->nstlist < 0) {
@@ -333,10 +569,10 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
         warning(wi,"If you want to remove the rotation around the center of mass, you should set comm_mode = Angular instead of setting nstcomm < 0. nstcomm is modified to its absolute value");
       ir->nstcomm = abs(ir->nstcomm);
     }
-    
+
     if (ir->nstcalcenergy > 0 && ir->nstcomm < ir->nstcalcenergy) {
         warning_note(wi,"nstcomm < nstcalcenergy defeats the purpose of nstcalcenergy, setting nstcomm to nstcalcenergy");
-      ir->nstcomm = ir->nstcalcenergy;
+        ir->nstcomm = ir->nstcalcenergy;
     }
 
     if (ir->comm_mode == ecmANGULAR) {
@@ -346,30 +582,27 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
           warning(wi,"Removing the rotation around the center of mass in a periodic system (this is not a problem when you have only one molecule).");
     }
   }
-    
+
   if (EI_STATE_VELOCITY(ir->eI) && ir->ePBC == epbcNONE && ir->comm_mode != ecmANGULAR) {
       warning_note(wi,"Tumbling and or flying ice-cubes: We are not removing rotation around center of mass in a non-periodic system. You should probably set comm_mode = ANGULAR.");
   }
   
-  sprintf(err_buf,"Free-energy not implemented for Ewald");
-  CHECK((ir->coulombtype==eelEWALD) && (ir->efep!=efepNO));
-  
   sprintf(err_buf,"Twin-range neighbour searching (NS) with simple NS"
          " algorithm not implemented");
-  CHECK(((ir->rcoulomb > ir->rlist) || (ir->rvdw > ir->rlist)) 
+  CHECK(((ir->rcoulomb > ir->rlist) || (ir->rvdw > ir->rlist))
        && (ir->ns_type == ensSIMPLE));
-  
-    /* TEMPERATURE COUPLING */
-    if (ir->etc == etcYES)
+
+  /* TEMPERATURE COUPLING */
+  if (ir->etc == etcYES)
     {
         ir->etc = etcBERENDSEN;
         warning_note(wi,"Old option for temperature coupling given: "
                      "changing \"yes\" to \"Berendsen\"\n");
     }
-  
-    if (ir->etc == etcNOSEHOOVER)
+
+    if ((ir->etc == etcNOSEHOOVER) || (ir->epc == epcMTTK))
     {
-        if (ir->opts.nhchainlength < 1) 
+        if (ir->opts.nhchainlength < 1)
         {
             sprintf(warn_buf,"number of Nose-Hoover chains (currently %d) cannot be less than 1,reset to 1\n",ir->opts.nhchainlength);
             ir->opts.nhchainlength =1;
@@ -387,6 +620,40 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
         ir->opts.nhchainlength = 0;
     }
 
+    if (ir->eI == eiVVAK) {
+        sprintf(err_buf,"%s implemented primarily for validation, and requires nsttcouple = 1 and nstpcouple = 1.",
+                ei_names[eiVVAK]);
+        CHECK((ir->nsttcouple != 1) || (ir->nstpcouple != 1));
+    }
+
+    if (ETC_ANDERSEN(ir->etc))
+    {
+        sprintf(err_buf,"%s temperature control not supported for integrator %s.",etcoupl_names[ir->etc],ei_names[ir->eI]);
+        CHECK(!(EI_VV(ir->eI)));
+
+        for (i=0;i<ir->opts.ngtc;i++)
+        {
+            sprintf(err_buf,"all tau_t must currently be equal using Andersen temperature control, violated for group %d",i);
+            CHECK(ir->opts.tau_t[0] != ir->opts.tau_t[i]);
+            sprintf(err_buf,"all tau_t must be postive using Andersen temperature control, tau_t[%d]=%10.6f",
+                    i,ir->opts.tau_t[i]);
+            CHECK(ir->opts.tau_t[i]<0);
+        }
+        if (ir->nstcomm > 0 && (ir->etc == etcANDERSEN)) {
+            sprintf(warn_buf,"Center of mass removal not necessary for %s.  All velocities of coupled groups are rerandomized periodically, so flying ice cube errors will not occur.",etcoupl_names[ir->etc]);
+            warning_note(wi,warn_buf);
+        }
+
+        sprintf(err_buf,"nstcomm must be 1, not %d for %s, as velocities of atoms in coupled groups are randomized every time step",ir->nstcomm,etcoupl_names[ir->etc]);
+        CHECK(ir->nstcomm > 1 && (ir->etc == etcANDERSEN));
+
+        for (i=0;i<ir->opts.ngtc;i++)
+        {
+            int nsteps = (int)(ir->opts.tau_t[i]/ir->delta_t);
+            sprintf(err_buf,"tau_t/delta_t for group %d for temperature control method %s must be a multiple of nstcomm (%d), as velocities of atoms in coupled groups are randomized every time step. The input tau_t (%8.3f) leads to %d steps per randomization",i,etcoupl_names[ir->etc],ir->nstcomm,ir->opts.tau_t[i],nsteps);
+            CHECK((nsteps % ir->nstcomm) && (ir->etc == etcANDERSENMASSIVE));
+        }
+    }
     if (ir->etc == etcBERENDSEN)
     {
         sprintf(warn_buf,"The %s thermostat does not generate the correct kinetic energy distribution. You might want to consider using the %s thermostat.",
@@ -394,7 +661,7 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
         warning_note(wi,warn_buf);
     }
 
-    if ((ir->etc==etcNOSEHOOVER || ir->etc==etcANDERSEN || ir->etc==etcANDERSENINTERVAL) 
+    if ((ir->etc==etcNOSEHOOVER || ETC_ANDERSEN(ir->etc))
         && ir->epc==epcBERENDSEN)
     {
         sprintf(warn_buf,"Using Berendsen pressure coupling invalidates the "
@@ -416,18 +683,18 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
 
         sprintf(err_buf,"tau-p must be > 0 instead of %g\n",ir->tau_p);
         CHECK(ir->tau_p <= 0);
-        
+
         if (ir->tau_p/dt_pcoupl < pcouple_min_integration_steps(ir->epc))
         {
             sprintf(warn_buf,"For proper integration of the %s barostat, tau-p (%g) should be at least %d times larger than nstpcouple*dt (%g)",
                     EPCOUPLTYPE(ir->epc),ir->tau_p,pcouple_min_integration_steps(ir->epc),dt_pcoupl);
             warning(wi,warn_buf);
-        }      
-        
-        sprintf(err_buf,"compressibility must be > 0 when using pressure" 
+        }
+
+        sprintf(err_buf,"compressibility must be > 0 when using pressure"
                 " coupling %s\n",EPCOUPLTYPE(ir->epc));
-        CHECK(ir->compress[XX][XX] < 0 || ir->compress[YY][YY] < 0 || 
-              ir->compress[ZZ][ZZ] < 0 || 
+        CHECK(ir->compress[XX][XX] < 0 || ir->compress[YY][YY] < 0 ||
+              ir->compress[ZZ][ZZ] < 0 ||
               (trace(ir->compress) == 0 && ir->compress[YY][XX] <= 0 &&
                ir->compress[ZZ][XX] <= 0 && ir->compress[ZZ][YY] <= 0));
         
@@ -444,14 +711,14 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
             warning(wi,warn_buf);
         }
     }
-    
+
     if (EI_VV(ir->eI))
     {
         if (ir->epc > epcNO)
         {
-            if (ir->epc!=epcMTTK)
+            if ((ir->epc!=epcBERENDSEN) && (ir->epc!=epcMTTK))
             {
-                warning_error(wi,"NPT only defined for vv using Martyna-Tuckerman-Tobias-Klein equations");          
+                warning_error(wi,"for md-vv and md-vv-avek, can only use Berendsen and Martyna-Tuckerman-Tobias-Klein (MTTK) equations for pressure control; MTTK is equivalent to Parrinello-Rahman.");
             }
         }
     }
@@ -603,30 +870,23 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
     warning(wi,"Using L-BFGS with nbfgscorr<=0 just gets you steepest descent.");
   }
 
-  /* FREE ENERGY */
-  if (ir->efep != efepNO) {
-    sprintf(err_buf,"The soft-core power is %d and can only be 1 or 2",
-           ir->sc_power);
-    CHECK(ir->sc_alpha!=0 && ir->sc_power!=1 && ir->sc_power!=2);
+  /* ENERGY CONSERVATION */
+  if (ir_NVE(ir))
+  {
+      if (!EVDW_MIGHT_BE_ZERO_AT_CUTOFF(ir->vdwtype) && ir->rvdw > 0)
+      {
+          sprintf(warn_buf,"You are using a cut-off for VdW interactions with NVE, for good energy conservation use vdwtype = %s (possibly with DispCorr)",
+                  evdw_names[evdwSHIFT]);
+          warning_note(wi,warn_buf);
+      }
+      if (!EEL_MIGHT_BE_ZERO_AT_CUTOFF(ir->coulombtype) && ir->rcoulomb > 0)
+      {
+          sprintf(warn_buf,"You are using a cut-off for electrostatics with NVE, for good energy conservation use coulombtype = %s or %s",
+                  eel_names[eelPMESWITCH],eel_names[eelRF_ZERO]);
+          warning_note(wi,warn_buf);
+      }
   }
 
-    /* ENERGY CONSERVATION */
-    if (ir_NVE(ir))
-    {
-        if (!EVDW_MIGHT_BE_ZERO_AT_CUTOFF(ir->vdwtype) && ir->rvdw > 0)
-        {
-            sprintf(warn_buf,"You are using a cut-off for VdW interactions with NVE, for good energy conservation use vdwtype = %s (possibly with DispCorr)",
-                    evdw_names[evdwSHIFT]);
-            warning_note(wi,warn_buf);
-        }
-        if (!EEL_MIGHT_BE_ZERO_AT_CUTOFF(ir->coulombtype) && ir->rcoulomb > 0)
-        {
-            sprintf(warn_buf,"You are using a cut-off for electrostatics with NVE, for good energy conservation use coulombtype = %s or %s",
-                    eel_names[eelPMESWITCH],eel_names[eelRF_ZERO]);
-            warning_note(wi,warn_buf);
-        }
-    }
-  
   /* IMPLICIT SOLVENT */
   if(ir->coulombtype==eelGB_NOTUSED)
   {
@@ -703,6 +963,11 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
 
 }
 
+/* count the number of text elemets separated by whitespace in a string.
+    str = the input string
+    maxptr = the maximum number of allowed elements
+    ptr = the output array of pointers to the first character of each element
+    returns: the number of elements. */
 int str_nelem(const char *str,int maxptr,char *ptr[])
 {
   int  np=0;
@@ -732,7 +997,12 @@ int str_nelem(const char *str,int maxptr,char *ptr[])
   return np;
 }
 
-static void parse_n_double(char *str,int *n,double **r)
+/* interpret a number of doubles from a string and put them in an array,
+   after allocating space for them.
+   str = the input string
+   n = the (pre-allocated) number of doubles read
+   r = the output array of doubles. */
+static void parse_n_real(char *str,int *n,real **r)
 {
   char *ptr[MAXPTR];
   int  i;
@@ -745,6 +1015,181 @@ static void parse_n_double(char *str,int *n,double **r)
   }
 }
 
+static void do_fep_params(t_inputrec *ir, char fep_lambda[][STRLEN],char weights[STRLEN]) {
+
+    int i,j,max_n_lambda,nweights,nfep[efptNR];
+    t_lambda *fep = ir->fepvals;
+    t_expanded *expand = ir->expandedvals;
+    real **count_fep_lambdas;
+    gmx_bool bOneLambda = TRUE;
+
+    snew(count_fep_lambdas,efptNR);
+
+    /* FEP input processing */
+    /* first, identify the number of lambda values for each type.
+       All that are nonzero must have the same number */
+
+    for (i=0;i<efptNR;i++)
+    {
+        parse_n_real(fep_lambda[i],&(nfep[i]),&(count_fep_lambdas[i]));
+    }
+
+    /* now, determine the number of components.  All must be either zero, or equal. */
+
+    max_n_lambda = 0;
+    for (i=0;i<efptNR;i++)
+    {
+        if (nfep[i] > max_n_lambda) {
+            max_n_lambda = nfep[i];  /* here's a nonzero one.  All of them
+                                        must have the same number if its not zero.*/
+            break;
+        }
+    }
+
+    for (i=0;i<efptNR;i++)
+    {
+        if (nfep[i] == 0)
+        {
+            ir->fepvals->separate_dvdl[i] = FALSE;
+        }
+        else if (nfep[i] == max_n_lambda)
+        {
+            if (i!=efptTEMPERATURE)  /* we treat this differently -- not really a reason to compute the derivative with
+                                        respect to the temperature currently */
+            {
+                ir->fepvals->separate_dvdl[i] = TRUE;
+            }
+        }
+        else
+        {
+            gmx_fatal(FARGS,"Number of lambdas (%d) for FEP type %s not equal to number of other types (%d)",
+                      nfep[i],efpt_names[i],max_n_lambda);
+        }
+    }
+    /* we don't print out dhdl if the temperature is changing, since we can't correctly define dhdl in this case */
+    ir->fepvals->separate_dvdl[efptTEMPERATURE] = FALSE;
+
+    /* the number of lambdas is the number we've read in, which is either zero
+       or the same for all */
+    fep->n_lambda = max_n_lambda;
+
+    /* allocate space for the array of lambda values */
+    snew(fep->all_lambda,efptNR);
+    /* if init_lambda is defined, we need to set lambda */
+    if ((fep->init_lambda > 0) && (fep->n_lambda == 0))
+    {
+        ir->fepvals->separate_dvdl[efptFEP] = TRUE;
+    }
+    /* otherwise allocate the space for all of the lambdas, and transfer the data */
+    for (i=0;i<efptNR;i++)
+    {
+        snew(fep->all_lambda[i],fep->n_lambda);
+        if (nfep[i] > 0)  /* if it's zero, then the count_fep_lambda arrays
+                             are zero */
+        {
+            for (j=0;j<fep->n_lambda;j++)
+            {
+                fep->all_lambda[i][j] = (double)count_fep_lambdas[i][j];
+            }
+            sfree(count_fep_lambdas[i]);
+        }
+    }
+    sfree(count_fep_lambdas);
+
+    /* "fep-vals" is either zero or the full number. If zero, we'll need to define fep-lambdas for internal
+       bookkeeping -- for now, init_lambda */
+
+    if ((nfep[efptFEP] == 0) && (fep->init_lambda >= 0) && (fep->init_lambda <= 1))
+    {
+        for (i=0;i<fep->n_lambda;i++)
+        {
+            fep->all_lambda[efptFEP][i] = fep->init_lambda;
+        }
+    }
+
+    /* check to see if only a single component lambda is defined, and soft core is defined.
+       In this case, turn on coulomb soft core */
+
+    if (max_n_lambda == 0)
+    {
+        bOneLambda = TRUE;
+    }
+    else
+    {
+        for (i=0;i<efptNR;i++)
+        {
+            if ((nfep[i] != 0) && (i!=efptFEP))
+            {
+                bOneLambda = FALSE;
+            }
+        }
+    }
+    if ((bOneLambda) && (fep->sc_alpha > 0))
+    {
+        fep->bScCoul = TRUE;
+    }
+
+    /* Fill in the others with the efptFEP if they are not explicitly
+       specified (i.e. nfep[i] == 0).  This means if fep is not defined,
+       they are all zero. */
+
+    for (i=0;i<efptNR;i++)
+    {
+        if ((nfep[i] == 0) && (i!=efptFEP))
+        {
+            for (j=0;j<fep->n_lambda;j++)
+            {
+                fep->all_lambda[i][j] = fep->all_lambda[efptFEP][j];
+            }
+        }
+    }
+
+
+    /* make it easier if sc_r_power = 48 by increasing it to the 4th power, to be in the right scale. */
+    if (fep->sc_r_power == 48)
+    {
+        if (fep->sc_alpha > 0.1)
+        {
+            gmx_fatal(FARGS,"sc_alpha (%f) for sc_r_power = 48 should usually be between 0.001 and 0.004", fep->sc_alpha);
+        }
+    }
+
+    expand = ir->expandedvals;
+    /* now read in the weights */
+    parse_n_real(weights,&nweights,&(expand->init_lambda_weights));
+    if (nweights == 0)
+    {
+        expand->bInit_weights = FALSE;
+        snew(expand->init_lambda_weights,fep->n_lambda); /* initialize to zero */
+    }
+    else if (nweights != fep->n_lambda)
+    {
+        gmx_fatal(FARGS,"Number of weights (%d) is not equal to number of lambda values (%d)",
+                  nweights,fep->n_lambda);
+    }
+    else
+    {
+        expand->bInit_weights = TRUE;
+    }
+    if ((expand->nstexpanded < 0) && (ir->efep != efepNO)) {
+        expand->nstexpanded = fep->nstdhdl;
+        /* if you don't specify nstexpanded when doing expanded ensemble free energy calcs, it is set to nstdhdl */
+    }
+    if ((expand->nstexpanded < 0) && ir->bSimTemp) {
+        expand->nstexpanded = ir->nstlist;
+        /* if you don't specify nstexpanded when doing expanded ensemble simulated tempering, it is set to nstlist*/
+    }
+}
+
+
+static void do_simtemp_params(t_inputrec *ir) {
+
+    snew(ir->simtempvals->temperatures,ir->fepvals->n_lambda);
+    GetSimTemps(ir->fepvals->n_lambda,ir->simtempvals,ir->fepvals->all_lambda[efptTEMPERATURE]);
+
+    return;
+}
+
 static void do_wall_params(t_inputrec *ir,
                            char *wall_atomtype, char *wall_density,
                            t_gromppopts *opts)
@@ -811,6 +1256,47 @@ static void add_wall_energrps(gmx_groups_t *groups,int nwall,t_symtab *symtab)
   }
 }
 
+void read_expandedparams(int *ninp_p,t_inpfile **inp_p,
+                         t_expanded *expand,warninp_t wi)
+{
+  int  ninp,nerror=0;
+  t_inpfile *inp;
+
+  ninp   = *ninp_p;
+  inp    = *inp_p;
+
+  /* read expanded ensemble parameters */
+  CCTYPE ("expanded ensemble variables");
+  ITYPE ("nstexpanded",expand->nstexpanded,-1);
+  EETYPE("lmc-stats", expand->elamstats, elamstats_names);
+  EETYPE("lmc-move", expand->elmcmove, elmcmove_names);
+  EETYPE("lmc-weights-equil",expand->elmceq,elmceq_names);
+  ITYPE ("weight-equil-number-all-lambda",expand->equil_n_at_lam,-1);
+  ITYPE ("weight-equil-number-samples",expand->equil_samples,-1);
+  ITYPE ("weight-equil-number-steps",expand->equil_steps,-1);
+  RTYPE ("weight-equil-wl-delta",expand->equil_wl_delta,-1);
+  RTYPE ("weight-equil-count-ratio",expand->equil_ratio,-1);
+  CCTYPE("Seed for Monte Carlo in lambda space");
+  ITYPE ("lmc-seed",expand->lmc_seed,-1);
+  RTYPE ("mc-temperature",expand->mc_temp,-1);
+  ITYPE ("lmc-repeats",expand->lmc_repeats,1);
+  ITYPE ("lmc-gibbsdelta",expand->gibbsdeltalam,-1);
+  ITYPE ("lmc-forced-nstart",expand->lmc_forced_nstart,0);
+  EETYPE("symmetrized-transition-matrix", expand->bSymmetrizedTMatrix, yesno_names);
+  ITYPE("nst-transition-matrix", expand->nstTij, -1);
+  ITYPE ("mininum-var-min",expand->minvarmin, 100); /*default is reasonable */
+  ITYPE ("weight-c-range",expand->c_range, 0); /* default is just C=0 */
+  RTYPE ("wl-scale",expand->wl_scale,0.8);
+  RTYPE ("wl-ratio",expand->wl_ratio,0.8);
+  RTYPE ("init-wl-delta",expand->init_wl_delta,1.0);
+  EETYPE("wl-oneovert",expand->bWLoneovert,yesno_names);
+
+  *ninp_p   = ninp;
+  *inp_p    = inp;
+
+  return;
+}
+
 void get_ir(const char *mdparin,const char *mdparout,
             t_inputrec *ir,t_gromppopts *opts,
             warninp_t wi)
@@ -821,20 +1307,29 @@ void get_ir(const char *mdparin,const char *mdparout,
   const char *tmp;
   int       i,j,m,ninp;
   char      warn_buf[STRLEN];
-  
+  t_lambda  *fep = ir->fepvals;
+  t_expanded *expand = ir->expandedvals;
+
   inp = read_inpfile(mdparin, &ninp, NULL, wi);
 
   snew(dumstr[0],STRLEN);
   snew(dumstr[1],STRLEN);
 
+  /* remove the following deprecated commands */
   REM_TYPE("title");
   REM_TYPE("cpp");
   REM_TYPE("domain-decomposition");
-  REPL_TYPE("unconstrained-start","continuation");
+  REM_TYPE("andersen-seed");
+  REM_TYPE("dihre");
+  REM_TYPE("dihre-fc");
   REM_TYPE("dihre-tau");
   REM_TYPE("nstdihreout");
   REM_TYPE("nstcheckpoint");
 
+  /* replace the following commands with the clearer new versions*/
+  REPL_TYPE("unconstrained-start","continuation");
+  REPL_TYPE("foreign-lambda","fep-lambdas");
+
   CCTYPE ("VARIOUS PREPROCESSING OPTIONS");
   CTYPE ("Preprocessor information: use cpp syntax.");
   CTYPE ("e.g.: -I/home/joe/doe -I/home/mary/roe");
@@ -981,6 +1476,7 @@ void get_ir(const char *mdparin,const char *mdparout,
   EETYPE("tcoupl",     ir->etc,        etcoupl_names);
   ITYPE ("nsttcouple", ir->nsttcouple,  -1);
   ITYPE("nh-chain-length",     ir->opts.nhchainlength, NHCHAINLENGTH);
+  EETYPE("print-nose-hoover-chain-variables", ir->bPrintNHChains, yesno_names);
   CTYPE ("Groups to couple separately");
   STYPE ("tc-grps",     tcgrps,         NULL);
   CTYPE ("Time constant (ps) and reference temperature (K)");
@@ -997,9 +1493,6 @@ void get_ir(const char *mdparin,const char *mdparout,
   CTYPE ("Scaling of reference coordinates, No, All or COM");
   EETYPE ("refcoord-scaling",ir->refcoord_scaling,erefscaling_names);
 
-  CTYPE ("Random seed for Andersen thermostat");
-  ITYPE ("andersen-seed", ir->andersen_seed, 815131);
-
   /* QMMM */
   CCTYPE ("OPTIONS FOR QMMM calculations");
   EETYPE("QMMM", ir->bQMMM, yesno_names);
@@ -1122,30 +1615,43 @@ void get_ir(const char *mdparin,const char *mdparout,
   STYPE ("orire-fitgrp",orirefitgrp,    NULL);
   CTYPE ("Output frequency for trace(SD) and S to energy file");
   ITYPE ("nstorireout", ir->nstorireout, 100);
-  CTYPE ("Dihedral angle restraints: No or Yes");
-  EETYPE("dihre",       opts->bDihre,   yesno_names);
-  RTYPE ("dihre-fc",   ir->dihre_fc,   1000.0);
-
-  /* Free energy stuff */
-  CCTYPE ("Free energy control stuff");
-  EETYPE("free-energy",        ir->efep, efep_names);
-  RTYPE ("init-lambda",        ir->init_lambda,0.0);
-  RTYPE ("delta-lambda",ir->delta_lambda,0.0);
-  STYPE ("foreign-lambda", foreign_lambda, NULL);
-  RTYPE ("sc-alpha",ir->sc_alpha,0.0);
-  ITYPE ("sc-power",ir->sc_power,0);
-  RTYPE ("sc-sigma",ir->sc_sigma,0.3);
-  ITYPE ("nstdhdl",     ir->nstdhdl, 10);
-  EETYPE("separate-dhdl-file", ir->separate_dhdl_file, 
-                               separate_dhdl_file_names);
-  EETYPE("dhdl-derivatives", ir->dhdl_derivatives, dhdl_derivatives_names);
-  ITYPE ("dh-hist-size", ir->dh_hist_size, 0);
-  RTYPE ("dh-hist-spacing", ir->dh_hist_spacing, 0.1);
+
+  /* free energy variables */
+  CCTYPE ("Free energy variables");
+  EETYPE("free-energy", ir->efep, efep_names);
   STYPE ("couple-moltype",  couple_moltype,  NULL);
   EETYPE("couple-lambda0", opts->couple_lam0, couple_lam);
   EETYPE("couple-lambda1", opts->couple_lam1, couple_lam);
   EETYPE("couple-intramol", opts->bCoupleIntra, yesno_names);
 
+  RTYPE ("init-lambda", fep->init_lambda,-1); /* start with -1 so
+                                                 we can recognize if
+                                                 it was not entered */
+  ITYPE ("init-lambda-state", fep->init_fep_state,0);
+  RTYPE ("delta-lambda",fep->delta_lambda,0.0);
+  ITYPE ("nstdhdl",fep->nstdhdl, 10);
+  STYPE ("fep-lambdas", fep_lambda[efptFEP], NULL);
+  STYPE ("mass-lambdas", fep_lambda[efptMASS], NULL);
+  STYPE ("coul-lambdas", fep_lambda[efptCOUL], NULL);
+  STYPE ("vdw-lambdas", fep_lambda[efptVDW], NULL);
+  STYPE ("bonded-lambdas", fep_lambda[efptBONDED], NULL);
+  STYPE ("restraint-lambdas", fep_lambda[efptRESTRAINT], NULL);
+  STYPE ("temperature-lambdas", fep_lambda[efptTEMPERATURE], NULL);
+  STYPE ("init-lambda-weights",lambda_weights,NULL);
+  EETYPE("dhdl-print-energy", fep->bPrintEnergy, yesno_names);
+  RTYPE ("sc-alpha",fep->sc_alpha,0.0);
+  ITYPE ("sc-power",fep->sc_power,1);
+  RTYPE ("sc-r-power",fep->sc_r_power,6.0);
+  RTYPE ("sc-sigma",fep->sc_sigma,0.3);
+  EETYPE("sc-coul",fep->bScCoul,yesno_names);
+  ITYPE ("dh_hist_size", fep->dh_hist_size, 0);
+  RTYPE ("dh_hist_spacing", fep->dh_hist_spacing, 0.1);
+  EETYPE("separate-dhdl-file", fep->separate_dhdl_file,
+                               separate_dhdl_file_names);
+  EETYPE("dhdl-derivatives", fep->dhdl_derivatives, dhdl_derivatives_names);
+  ITYPE ("dh_hist_size", fep->dh_hist_size, 0);
+  RTYPE ("dh_hist_spacing", fep->dh_hist_spacing, 0.1);
+
   /* Non-equilibrium MD stuff */  
   CCTYPE("Non-equilibrium MD stuff");
   STYPE ("acc-grps",    accgrps,        NULL);
@@ -1155,6 +1661,19 @@ void get_ir(const char *mdparin,const char *mdparout,
   RTYPE ("cos-acceleration", ir->cos_accel, 0);
   STYPE ("deform",      deform,         NULL);
 
+  /* simulated tempering variables */
+  CCTYPE("simulated tempering variables");
+  EETYPE("simulated-tempering",ir->bSimTemp,yesno_names);
+  EETYPE("simulated-tempering-scaling",ir->simtempvals->eSimTempScale,esimtemp_names);
+  RTYPE("sim-temp-low",ir->simtempvals->simtemp_low,300.0);
+  RTYPE("sim-temp-high",ir->simtempvals->simtemp_high,300.0);
+
+  /* expanded ensemble variables */
+  if (ir->efep==efepEXPANDED || ir->bSimTemp)
+  {
+      read_expandedparams(&ninp,&inp,expand,wi);
+  }
+
   /* Electric fields */
   CCTYPE("Electric fields");
   CTYPE ("Format is number of terms (int) and for all terms an amplitude (real)");
@@ -1256,34 +1775,80 @@ void get_ir(const char *mdparin,const char *mdparout,
     ir->nstcomm = 0;
 
   opts->couple_moltype = NULL;
-  if (strlen(couple_moltype) > 0) {
-    if (ir->efep != efepNO) {
-      opts->couple_moltype = strdup(couple_moltype);
-      if (opts->couple_lam0 == opts->couple_lam1)
-       warning(wi,"The lambda=0 and lambda=1 states for coupling are identical");
-      if (ir->eI == eiMD && (opts->couple_lam0 == ecouplamNONE ||
-                            opts->couple_lam1 == ecouplamNONE)) {
-       warning(wi,"For proper sampling of the (nearly) decoupled state, stochastic dynamics should be used");
+  if (strlen(couple_moltype) > 0) 
+  {
+      if (ir->efep != efepNO) 
+      {
+          opts->couple_moltype = strdup(couple_moltype);
+          if (opts->couple_lam0 == opts->couple_lam1)
+          {
+              warning(wi,"The lambda=0 and lambda=1 states for coupling are identical");
+          }
+          if (ir->eI == eiMD && (opts->couple_lam0 == ecouplamNONE ||
+                                 opts->couple_lam1 == ecouplamNONE)) 
+          {
+              warning(wi,"For proper sampling of the (nearly) decoupled state, stochastic dynamics should be used");
+          }
+      }
+      else
+      {
+          warning(wi,"Can not couple a molecule with free_energy = no");
       }
-    } else {
-      warning(wi,"Can not couple a molecule with free-energy = no");
-    }
+  }
+  /* FREE ENERGY AND EXPANDED ENSEMBLE OPTIONS */
+  if (ir->efep != efepNO) {
+      if (fep->delta_lambda > 0) {
+          ir->efep = efepSLOWGROWTH;
+      }
+  }
+
+  if (ir->bSimTemp) {
+      fep->bPrintEnergy = TRUE;
+      /* always print out the energy to dhdl if we are doing expanded ensemble, since we need the total energy
+         if the temperature is changing. */
   }
 
+  if ((ir->efep != efepNO) || ir->bSimTemp)
+  {
+      ir->bExpanded = FALSE;
+      if ((ir->efep == efepEXPANDED) || ir->bSimTemp)
+      {
+          ir->bExpanded = TRUE;
+      }
+      do_fep_params(ir,fep_lambda,lambda_weights);
+      if (ir->bSimTemp) { /* done after fep params */
+          do_simtemp_params(ir);
+      }
+  }
+  else
+  {
+      ir->fepvals->n_lambda = 0;
+  }
+
+  /* WALL PARAMETERS */
+
   do_wall_params(ir,wall_atomtype,wall_density,opts);
+
+  /* ORIENTATION RESTRAINT PARAMETERS */
   
   if (opts->bOrire && str_nelem(orirefitgrp,MAXPTR,NULL)!=1) {
       warning_error(wi,"ERROR: Need one orientation restraint fit group\n");
   }
 
+  /* DEFORMATION PARAMETERS */
+
   clear_mat(ir->deform);
   for(i=0; i<6; i++)
-    dumdub[0][i] = 0;
+  {
+      dumdub[0][i] = 0;
+  }
   m = sscanf(deform,"%lf %lf %lf %lf %lf %lf",
             &(dumdub[0][0]),&(dumdub[0][1]),&(dumdub[0][2]),
             &(dumdub[0][3]),&(dumdub[0][4]),&(dumdub[0][5]));
   for(i=0; i<3; i++)
-    ir->deform[i][i] = dumdub[0][i];
+  {
+      ir->deform[i][i] = dumdub[0][i];
+  }
   ir->deform[YY][XX] = dumdub[0][3];
   ir->deform[ZZ][XX] = dumdub[0][4];
   ir->deform[ZZ][YY] = dumdub[0][5];
@@ -1304,15 +1869,6 @@ void get_ir(const char *mdparin,const char *mdparout,
        }
   }
 
-  if (ir->efep != efepNO) {
-    parse_n_double(foreign_lambda,&ir->n_flambda,&ir->flambda);
-    if (ir->n_flambda > 0 && ir->rlist < max(ir->rvdw,ir->rcoulomb)) {
-      warning_note(wi,"For foreign lambda free energy differences it is assumed that the soft-core interactions have no effect beyond the neighborlist cut-off");
-    }
-  } else {
-    ir->n_flambda = 0;
-  }
-
   sfree(dumstr[0]);
   sfree(dumstr[1]);
 }
@@ -1897,8 +2453,12 @@ void do_index(const char* mdparin, const char *ndx,
       {
             ir->nsttcouple = ir_optimal_nsttcouple(ir);
       }
+
       if (EI_VV(ir->eI)) 
       {
+          if ((ir->etc==etcNOSEHOOVER) && (ir->epc==epcBERENDSEN)) {
+              gmx_fatal(FARGS,"Cannot do Nose-Hoover temperature with Berendsen pressure control with md-vv; use either vrescale temperature with berendsen pressure or Nose-Hoover temperature with MTTK pressure");
+          }
           if ((ir->epc==epcMTTK) && (ir->etc>etcNO))
           {
               int mincouple;
@@ -1909,7 +2469,18 @@ void do_index(const char* mdparin, const char *ndx,
               }
               ir->nstpcouple = mincouple;
               ir->nsttcouple = mincouple;
-              warning_note(wi,"for current Trotter decomposition methods with vv, nsttcouple and nstpcouple must be equal.  Both have been reset to min(nsttcouple,nstpcouple)");
+              sprintf(warn_buf,"for current Trotter decomposition methods with vv, nsttcouple and nstpcouple must be equal.  Both have been reset to min(nsttcouple,nstpcouple) = %d",mincouple);
+              warning_note(wi,warn_buf);
+          }
+      }
+      /* velocity verlet with averaged kinetic energy KE = 0.5*(v(t+1/2) - v(t-1/2)) is implemented
+         primarily for testing purposes, and does not work with temperature coupling other than 1 */
+
+      if (ETC_ANDERSEN(ir->etc)) {
+          if (ir->nsttcouple != 1) {
+              ir->nsttcouple = 1;
+              sprintf(warn_buf,"Andersen temperature control methods assume nsttcouple = 1; there is no need for larger nsttcouple > 1, since no global parameters are computed. nsttcouple has been reset to 1");
+              warning_note(wi,warn_buf);
           }
       }
       nstcmin = tcouple_min_integration_steps(ir->etc);
@@ -1932,8 +2503,14 @@ void do_index(const char* mdparin, const char *ndx,
               gmx_fatal(FARGS,"ref-t for group %d negative",i);
           }
       }
+      /* set the lambda mc temperature to the md integrator temperature (which should be defined
+         if we are in this conditional) if mc_temp is negative */
+      if (ir->expandedvals->mc_temp < 0)
+      {
+          ir->expandedvals->mc_temp = ir->opts.ref_t[0];  /*for now, set to the first reft */
+      }
   }
-    
+
   /* Simulated annealing for each group. There are nr groups */
   nSA = str_nelem(anneal,MAXPTR,ptr1);
   if (nSA == 1 && (ptr1[0][0]=='n' || ptr1[0][0]=='N'))
@@ -2400,7 +2977,7 @@ void triple_check(const char *mdparin,t_inputrec *ir,gmx_mtop_t *sys,
   }
   else {
     sprintf(err_buf,"When using coulombtype = %s"
-           " ref_t for temperature coupling should be > 0",
+           " ref-t for temperature coupling should be > 0",
            eel_names[eelGRF]);
     CHECK((ir->coulombtype == eelGRF) && (ir->opts.ref_t[0] <= 0));
   }
@@ -2450,7 +3027,7 @@ void triple_check(const char *mdparin,t_inputrec *ir,gmx_mtop_t *sys,
     sfree(mgrp);
   }
 
-  if (ir->efep != efepNO && ir->sc_alpha != 0 &&
+  if (ir->efep != efepNO && ir->fepvals->sc_alpha != 0 &&
       !gmx_within_tol(sys->ffparams.reppow,12.0,10*GMX_DOUBLE_EPS)) {
     gmx_fatal(FARGS,"Soft-core interactions are only supported with VdW repulsion power 12");
   }
index 384ff0bc6eab400a27dbd01cd23a1b6aa7c36a20..9e904a2b5259845a8bdb275759f9b301f8f650ce 100644 (file)
@@ -64,7 +64,6 @@ typedef struct {
   real tempi;
   int  seed;
   gmx_bool bOrire;
-  gmx_bool bDihre;
   gmx_bool bMorse;
   char *wall_atomtype[2];
   gmx_bool pull_start;
index f7092de28ace93fdd995ea0a980a15031193c4d1..efe746c61d74bf627c28a2dea53c785de18c5a9a 100644 (file)
@@ -289,14 +289,17 @@ void set_pull_init(t_inputrec *ir,gmx_mtop_t *mtop,rvec *x,matrix box,
   t_pbc     pbc;
   int       ndim,g,m;
   double    t_start,tinvrate;
+  real      lambda;
   rvec      init;
   dvec      dr,dev;
 
-  init_pull(NULL,ir,0,NULL,mtop,NULL,oenv,FALSE,0);
+  /* need to pass in the correct masses if free energy is on*/
+  lambda = ir->fepvals->all_lambda[efptMASS][ir->fepvals->init_fep_state];
+  init_pull(NULL,ir,0,NULL,mtop,NULL,oenv,lambda,FALSE,0); 
   md = init_mdatoms(NULL,mtop,ir->efep);
   atoms2md(mtop,ir,0,NULL,0,mtop->natoms,md);
   if (ir->efep)
-    update_mdatoms(md,ir->init_lambda);
+    update_mdatoms(md,ir->fepvals->init_lambda);
   
   pull = ir->pull;
   if (pull->eGeom == epullgPOS)
index 73c53fb85e1c91119ecfde06169587f3a6d3cb01..d20b189df38730bf6980d3803c4ccdb6d026f9c1 100644 (file)
 #include "domdec.h"
 #include "partdec.h"
 
+#define PROBABILITYCUTOFF 100
+/* we don't bother evaluating if events are more rare than exp(-100) = 3.7x10^-44 */
+
+enum { ereTEMP, ereLAMBDA, ereENDSINGLE ,ereTL, ereNR };
+const char *erename[ereNR] = { "temperature", "lambda", "end_single_marker", "temperature and lambda"};
+
 typedef struct gmx_repl_ex
 {
     int  repl;
     int  nrepl;
     real temp;
     int  type;
-    real *q;
+    real **q;
     gmx_bool bNPT;
     real *pres;
     int  *ind;
+    int *allswaps;
     int  nst;
+    int nex;
     int  seed;
     int  nattempt[2];
     real *prob_sum;
+    int  **nmoves;
     int  *nexchange;
 } t_gmx_repl_ex;
 
-enum { ereTEMP, ereLAMBDA, ereNR };
-const char *erename[ereNR] = { "temperature", "lambda" };
-
-static void repl_quantity(FILE *fplog,const gmx_multisim_t *ms,
-                          struct gmx_repl_ex *re,int ere,real q)
+static gmx_bool repl_quantity(FILE *fplog,const gmx_multisim_t *ms,
+                              struct gmx_repl_ex *re,int ere,real q)
 {
     real *qall;
     gmx_bool bDiff;
-    int  s;
+    int  i,s;
 
     snew(qall,ms->nsim);
     qall[re->repl] = q;
     gmx_sum_sim(ms->nsim,qall,ms);
 
     bDiff = FALSE;
-    for(s=1; s<ms->nsim; s++)
+    for (s=1; s<ms->nsim; s++)
     {
         if (qall[s] != qall[0])
         {
-            bDiff = TRUE;
+            bDiff = TRUE;   
         }
     }
+
     if (bDiff)
     {
-        if (re->type >= 0 && re->type < ereNR)
-        {
-            gmx_fatal(FARGS,"For replica exchange both %s and %s differ",
-                      erename[re->type],erename[ere]);
-        }
         /* Set the replica exchange type and quantities */
         re->type = ere;
-        snew(re->q,re->nrepl);
+
+        snew(re->q[ere],re->nrepl);
         for(s=0; s<ms->nsim; s++)
         {
-            re->q[s] = qall[s];
+            re->q[ere][s] = qall[s];
         }
     }
-
     sfree(qall);
+    return bDiff;
 }
 
 gmx_repl_ex_t init_replica_exchange(FILE *fplog,
                                     const gmx_multisim_t *ms,
                                     const t_state *state,
                                     const t_inputrec *ir,
-                                    int nst,int init_seed)
+                                    int nst, int nex, int init_seed)
 {
     real temp,pres;
     int  i,j,k;
     struct gmx_repl_ex *re;
+    gmx_bool bTemp;
+    gmx_bool bLambda=FALSE;
 
     fprintf(fplog,"\nInitializing Replica Exchange\n");
 
@@ -130,6 +135,7 @@ gmx_repl_ex_t init_replica_exchange(FILE *fplog,
 
     re->repl     = ms->sim;
     re->nrepl    = ms->nsim;
+    snew(re->q,ereENDSINGLE);
 
     fprintf(fplog,"Repl  There are %d replicas:\n",re->nrepl);
 
@@ -143,6 +149,7 @@ gmx_repl_ex_t init_replica_exchange(FILE *fplog,
                     "the number of temperature coupling groups");
     check_multi_int(fplog,ms,ir->epc,"the pressure coupling");
     check_multi_int(fplog,ms,ir->efep,"free energy");
+    check_multi_int(fplog,ms,ir->fepvals->n_lambda,"number of lambda states");
 
     re->temp = ir->opts.ref_t[0];
     for(i=1; (i<ir->opts.ngtc); i++)
@@ -155,31 +162,21 @@ gmx_repl_ex_t init_replica_exchange(FILE *fplog,
     }
 
     re->type = -1;
-    for(i=0; i<ereNR; i++)
+    bTemp = repl_quantity(fplog,ms,re,ereTEMP,re->temp);
+    if (ir->efep != efepNO)
     {
-        switch (i)
-        {
-        case ereTEMP:
-            repl_quantity(fplog,ms,re,i,re->temp);
-            break;
-        case ereLAMBDA:
-            if (ir->efep != efepNO)
-            {
-                repl_quantity(fplog,ms,re,i,ir->init_lambda);
-            }
-            break;
-        default:
-            gmx_incons("Unknown replica exchange quantity");
-        }
+        bLambda = repl_quantity(fplog,ms,re,ereLAMBDA,(real)ir->fepvals->init_fep_state);
     }
-    if (re->type == -1)
+    if (re->type == -1)  /* nothing was assigned */
     {
         gmx_fatal(FARGS,"The properties of the %d systems are all the same, there is nothing to exchange",re->nrepl);
     }
+    if (bLambda && bTemp) {
+        re->type = ereTL;
+    }
 
-    switch (re->type)
+    if (bTemp)
     {
-    case ereTEMP:
         please_cite(fplog,"Hukushima96a");
         if (ir->epc != epcNO)
         {
@@ -192,15 +189,13 @@ gmx_repl_ex_t init_replica_exchange(FILE *fplog,
             gmx_fatal(FARGS,"REMD with the %s thermostat does not produce correct potential energy distributions, consider using the %s thermostat instead",
                       ETCOUPLTYPE(ir->etc),ETCOUPLTYPE(etcVRESCALE));
         }
-        break;
-    case ereLAMBDA:
-        if (ir->delta_lambda != 0)
+    }
+    if (bLambda) {
+        if (ir->fepvals->delta_lambda != 0)   /* check this? */
         {
             gmx_fatal(FARGS,"delta_lambda is not zero");
         }
-        break;
     }
-
     if (re->bNPT)
     {
         snew(re->pres,re->nrepl);
@@ -226,48 +221,72 @@ gmx_repl_ex_t init_replica_exchange(FILE *fplog,
         gmx_sum_sim(re->nrepl,re->pres,ms);
     }
 
+    /* Make an index for increasing replica order */
+    /* only makes sense if one or the other is varying, not both!
+       if both are varying, we trust the order the person gave. */
     snew(re->ind,re->nrepl);
-    /* Make an index for increasing temperature order */
     for(i=0; i<re->nrepl; i++)
     {
         re->ind[i] = i;
     }
-    for(i=0; i<re->nrepl; i++)
-    {
-        for(j=i+1; j<re->nrepl; j++)
+
+    if (re->type<ereENDSINGLE) {
+
+        for(i=0; i<re->nrepl; i++)
         {
-            if (re->q[re->ind[j]] < re->q[re->ind[i]])
+            for(j=i+1; j<re->nrepl; j++)
             {
-                k = re->ind[i];
-                re->ind[i] = re->ind[j];
-                re->ind[j] = k;
-            }
-            else if (re->q[re->ind[j]] == re->q[re->ind[i]])
-            {
-                gmx_fatal(FARGS,"Two replicas have identical %ss",erename[re->type]);
+                if (re->q[re->type][re->ind[j]] < re->q[re->type][re->ind[i]])
+                {
+                    k = re->ind[i];
+                    re->ind[i] = re->ind[j];
+                    re->ind[j] = k;
+                }
+                else if (re->q[re->type][re->ind[j]] == re->q[re->type][re->ind[i]])
+                {
+                    gmx_fatal(FARGS,"Two replicas have identical %ss",erename[re->type]);
+                }
             }
         }
     }
-    fprintf(fplog,"Repl   ");
+
+    /* keep track of all the swaps, starting with the initial placement. */
+    snew(re->allswaps,re->nrepl);
     for(i=0; i<re->nrepl; i++)
     {
-        fprintf(fplog," %3d  ",re->ind[i]);
+        re->allswaps[i] = re->ind[i];
     }
+
     switch (re->type)
     {
     case ereTEMP:
-        fprintf(fplog,"\nRepl  T");
+        fprintf(fplog,"\nReplica exchange in temperature\n");
         for(i=0; i<re->nrepl; i++)
         {
-            fprintf(fplog," %5.1f",re->q[re->ind[i]]);
+            fprintf(fplog," %5.1f",re->q[re->type][re->ind[i]]);
         }
+        fprintf(fplog,"\n");
         break;
     case ereLAMBDA:
-        fprintf(fplog,"\nRepl  l");
+        fprintf(fplog,"\nReplica exchange in lambda\n");
+        for(i=0; i<re->nrepl; i++)
+        {
+            fprintf(fplog," %3d",(int)re->q[re->type][re->ind[i]]);
+        }
+        fprintf(fplog,"\n");
+        break;
+    case ereTL:
+        fprintf(fplog,"\nReplica exchange in temperature and lambda state\n");
+        for(i=0; i<re->nrepl; i++)
+        {
+            fprintf(fplog," %5.1f",re->q[ereTEMP][re->ind[i]]);
+        }
+        fprintf(fplog,"\n");
         for(i=0; i<re->nrepl; i++)
         {
-            fprintf(fplog," %5.3f",re->q[re->ind[i]]);
+            fprintf(fplog," %5d",(int)re->q[ereLAMBDA][re->ind[i]]);
         }
+        fprintf(fplog,"\n");
         break;
     default:
         gmx_incons("Unknown replica exchange quantity");
@@ -284,12 +303,11 @@ gmx_repl_ex_t init_replica_exchange(FILE *fplog,
         {
             if ((i > 0) && (re->pres[re->ind[i]] < re->pres[re->ind[i-1]]))
             {
-                gmx_fatal(FARGS,"The reference pressure decreases with increasing temperature");
+                fprintf(fplog,"\nWARNING: The reference pressures decrease with increasing temperatures\n\n");
+                fprintf(stderr,"\nWARNING: The reference pressures decrease with increasing temperatures\n\n");
             }
         }
     }
-    fprintf(fplog,"\nRepl  ");
-  
     re->nst = nst;
     if (init_seed == -1)
     {
@@ -307,16 +325,22 @@ gmx_repl_ex_t init_replica_exchange(FILE *fplog,
     {
         re->seed = init_seed;
     }
-    fprintf(fplog,"\nRepl  exchange interval: %d\n",re->nst);
-    fprintf(fplog,"\nRepl  random seed: %d\n",re->seed);
+    fprintf(fplog,"\nReplica exchange interval: %d\n",re->nst);
+    fprintf(fplog,"\nReplica random seed: %d\n",re->seed);
 
     re->nattempt[0] = 0;
     re->nattempt[1] = 0;
+
     snew(re->prob_sum,re->nrepl);
     snew(re->nexchange,re->nrepl);
+    snew(re->nmoves,re->nrepl);
+    for (i=0;i<re->nrepl;i++) 
+    {
+        snew(re->nmoves[i],re->nrepl);
+    }
+    fprintf(fplog,"Replica exchange information below: x=exchange, pr=probability\n");
 
-    fprintf(fplog,"Repl  below: x=exchange, pr=probability\n");
-
+    re->nex = nex;
     return re;
 }
 
@@ -352,6 +376,38 @@ static void exchange_reals(const gmx_multisim_t *ms,int b,real *v,int n)
     }
 }
 
+
+static void exchange_ints(const gmx_multisim_t *ms,int b,int *v,int n)
+{
+  int *buf;
+  int  i;
+
+  if (v) {
+    snew(buf,n);
+#ifdef GMX_MPI
+    /*
+    MPI_Sendrecv(v,  n*sizeof(int),MPI_BYTE,MSRANK(ms,b),0,
+                buf,n*sizeof(int),MPI_BYTE,MSRANK(ms,b),0,
+                ms->mpi_comm_masters,MPI_STATUS_IGNORE);
+    */
+    {
+      MPI_Request mpi_req;
+
+      MPI_Isend(v,n*sizeof(int),MPI_BYTE,MSRANK(ms,b),0,
+               ms->mpi_comm_masters,&mpi_req);
+      MPI_Recv(buf,n*sizeof(int),MPI_BYTE,MSRANK(ms,b),0,
+              ms->mpi_comm_masters,MPI_STATUS_IGNORE);
+      MPI_Wait(&mpi_req,MPI_STATUS_IGNORE);
+    }
+#endif
+    for(i=0; i<n; i++) 
+    {
+        v[i] = buf[i];
+    }
+    sfree(buf);
+  }
+}
+
 static void exchange_doubles(const gmx_multisim_t *ms,int b,double *v,int n)
 {
     double *buf;
@@ -466,8 +522,36 @@ static void copy_doubles(const double *s,double *d,int n)
     }
 }
 
-#define scopy_rvecs(v,n)   copy_rvecs(state->v,state_local->v,n)
-#define scopy_doubles(v,n) copy_doubles(state->v,state_local->v,n)
+static void copy_reals(const real *s,real *d,int n)
+{
+    int i;
+
+    if (d != NULL)
+    {
+        for(i=0; i<n; i++)
+        {
+            d[i] = s[i];
+        }
+    }
+}
+
+static void copy_ints(const int *s,int *d,int n)
+{
+    int i;
+
+    if (d != NULL)
+    {
+        for(i=0; i<n; i++)
+        {
+            d[i] = s[i];
+        }
+    }
+}
+
+#define scopy_rvecs(v,n)   copy_rvecs(state->v,state_local->v,n);
+#define scopy_doubles(v,n) copy_doubles(state->v,state_local->v,n);
+#define scopy_reals(v,n) copy_reals(state->v,state_local->v,n);
+#define scopy_ints(v,n)   copy_ints(state->v,state_local->v,n);
 
 static void copy_state_nonatomdata(t_state *state,t_state *state_local)
 {
@@ -491,6 +575,8 @@ static void copy_state_nonatomdata(t_state *state,t_state *state_local)
     scopy_rvecs(x,state->natoms);
     scopy_rvecs(v,state->natoms);
     scopy_rvecs(sd_X,state->natoms);
+    copy_ints(&(state->fep_state),&(state_local->fep_state),1);
+    scopy_reals(lambda,efptNR);
 }
 
 static void scale_velocities(t_state *state,real fac)
@@ -526,6 +612,34 @@ static void pd_collect_state(const t_commrec *cr,t_state *state)
     }
 }
 
+static void print_matrix(FILE *fplog,const char *leg,int n,int **nmoves, int *nattempt)
+{
+    int i,j,ntot;
+    float Tprint;
+
+    ntot = nattempt[0] + nattempt[1];
+
+    fprintf(fplog,"                  Empirical Transition Matrix\n");
+    for (i=0;i<n;i++)
+    {
+        fprintf(fplog,"%8d",(i+1));
+    }
+    fprintf(fplog,"\n");
+    for (i=0;i<n;i++)
+    {
+        for (j=0;j<n;j++)
+        {
+            Tprint = 0.0;
+            if (nmoves[i][j] > 0)
+            {
+                Tprint = nmoves[i][j]/(2.0*ntot);
+            }
+            fprintf(fplog,"%8.4f",Tprint);
+        }
+        fprintf(fplog,"%3d\n",i);
+    }
+}
+
 static void print_ind(FILE *fplog,const char *leg,int n,int *ind,gmx_bool *bEx)
 {
     int i;
@@ -538,6 +652,38 @@ static void print_ind(FILE *fplog,const char *leg,int n,int *ind,gmx_bool *bEx)
     fprintf(fplog,"\n");
 }
 
+static void print_allswitchind(FILE *fplog,int n,int *ind,int *pind, int *allswaps)
+{
+    int i;
+    int *tmpswap;
+
+    snew(tmpswap,n); /* need to save the data */
+    for (i=0;i<n;i++)
+    {
+        tmpswap[i] = allswaps[i];
+    }
+    for (i=0;i<n;i++)
+    {
+        allswaps[i] = tmpswap[pind[i]];
+    }
+
+    fprintf(fplog,"\nAccepted Exchanges:   ");
+    for (i=0;i<n;i++)
+    {
+        fprintf(fplog,"%d ",pind[i]);
+    }
+    fprintf(fplog,"\n");
+
+    fprintf(fplog,"Order After Exchange: ");
+    for (i=0;i<n;i++)
+    {
+        fprintf(fplog,"%d ",allswaps[i]);
+    }
+    fprintf(fplog,"\n\n");
+
+    sfree(tmpswap);
+}
+
 static void print_prob(FILE *fplog,const char *leg,int n,real *prob)
 {
     int  i;
@@ -571,156 +717,465 @@ static void print_count(FILE *fplog,const char *leg,int n,int *count)
     fprintf(fplog,"\n");
 }
 
-static int get_replica_exchange(FILE *fplog,const gmx_multisim_t *ms,
-                                struct gmx_repl_ex *re,real *ener,real vol,
-                                int step,real time)
-{
-    int  m,i,a,b;
-    real *Epot=NULL,*Vol=NULL,*dvdl=NULL,*prob;
-    real ediff=0,delta=0,dpV=0,betaA=0,betaB=0;
-    gmx_bool *bEx,bPrint;
-    int  exchange;
+static real calc_delta(FILE *fplog, gmx_bool bPrint, struct gmx_repl_ex *re, real *Epot, real **df, real* Vol, real *beta, int a, int b, int ap, int bp) {
+
+    real ediff,dpV,delta=0;
+
+    /* Two cases; we are permuted and not.  In all cases, setting ap = a and bp = b will reduce
+       to the non permuted case */
 
-    fprintf(fplog,"Replica exchange at step %d time %g\n",step,time);
-  
     switch (re->type)
     {
     case ereTEMP:
-        snew(Epot,re->nrepl);
-        snew(Vol,re->nrepl);
-        Epot[re->repl] = ener[F_EPOT];
-        Vol[re->repl]  = vol;
-        gmx_sum_sim(re->nrepl,Epot,ms);
-        gmx_sum_sim(re->nrepl,Vol,ms);
+        /*
+         * Okabe et. al. Chem. Phys. Lett. 335 (2001) 435-439
+         */
+        ediff = Epot[b] - Epot[a];
+        delta = -(beta[bp] - beta[ap])*ediff;
         break;
     case ereLAMBDA:
-        snew(dvdl,re->nrepl);
-        dvdl[re->repl] = ener[F_DVDL];
-        gmx_sum_sim(re->nrepl,dvdl,ms);
+        /* two cases:  when we are permuted, and not.  */
+        /* non-permuted:
+           ediff =  E_new - E_old
+                 =  [H_b(x_a) + H_a(x_b)] - [H_b(x_b) + H_a(x_a)]
+                 =  [H_b(x_a) - H_a(x_a)] + [H_a(x_b) - H_b(x_b)]
+                 =  df[b][a] + df[a][b] */
+        /* permuted:
+           ediff =  E_new - E_old
+                 =  [H_bp(x_a) + H_ap(x_b)] - [H_bp(x_b) + H_ap(x_a)]
+                 =  [H_bp(x_a) - H_ap(x_a)] + [H_ap(x_b) - H_bp(x_b)]
+                 =  [H_bp(x_a) - H_a(x_a) + H_a(x_a) - H_ap(x_a)] + [H_ap(x_b) - H_b(x_b) + H_b(x_b) - H_bp(x_b)]
+                 =  [H_bp(x_a) - H_a(x_a)] - [H_ap(x_a) - H_a(x_a)] + [H_ap(x_b) - H_b(x_b)] - H_bp(x_b) - H_b(x_b)]
+                 =  (df[bp][a] - df[ap][a]) + (df[ap][b] - df[bp][b])    */
+        ediff = (df[bp][a] - df[ap][a]) + (df[ap][b] - df[bp][b]);
+        delta = ediff*beta[a]; /* assume all same temperature in this case */
         break;
+    case ereTL:
+        /* not permuted:  */
+        /* delta =  reduced E_new - reduced E_old
+                 =  [beta_b H_b(x_a) + beta_a H_a(x_b)] - [beta_b H_b(x_b) + beta_a H_a(x_a)]
+                 =  [beta_b H_b(x_a) - beta_a H_a(x_a)] + [beta_a H_a(x_b) - beta_b H_b(x_b)]
+                 =  [beta_b dH_b(x_a) + beta_b H_a(x_a) - beta_a H_a(x_a)] +
+                    [beta_a dH_a(x_b) + beta_a H_b(x_b) - beta_b H_b(x_b)]
+                 =  [beta_b dH_b(x_a) + [beta_a dH_a(x_b) +
+                    beta_b (H_a(x_a) - H_b(x_b)]) - beta_a (H_a(x_a) - H_b(x_b))
+                 =  beta_b dH_b(x_a) + beta_a dH_a(x_b) - (beta_b - beta_a)(H_b(x_b) - H_a(x_a) */
+        /* delta = beta[b]*df[b][a] + beta[a]*df[a][b] - (beta[b] - beta[a])*(Epot[b] - Epot[a]; */
+        /* permuted (big breath!) */
+        /*   delta =  reduced E_new - reduced E_old
+                 =  [beta_bp H_bp(x_a) + beta_ap H_ap(x_b)] - [beta_bp H_bp(x_b) + beta_ap H_ap(x_a)]
+                 =  [beta_bp H_bp(x_a) - beta_ap H_ap(x_a)] + [beta_ap H_ap(x_b) - beta_bp H_bp(x_b)]
+                 =  [beta_bp H_bp(x_a) - beta_ap H_ap(x_a)] + [beta_ap H_ap(x_b) - beta_bp H_bp(x_b)]
+                    - beta_pb H_a(x_a) + beta_ap H_a(x_a) + beta_pb H_a(x_a) - beta_ap H_a(x_a)
+                    - beta_ap H_b(x_b) + beta_bp H_b(x_b) + beta_ap H_b(x_b) - beta_bp H_b(x_b)
+                 =  [(beta_bp H_bp(x_a) - beta_bp H_a(x_a)) - (beta_ap H_ap(x_a) - beta_ap H_a(x_a))] +
+                    [(beta_ap H_ap(x_b)  - beta_ap H_b(x_b)) - (beta_bp H_bp(x_b) - beta_bp H_b(x_b))]
+                    + beta_pb H_a(x_a) - beta_ap H_a(x_a) + beta_ap H_b(x_b) - beta_bp H_b(x_b)
+                 =  [beta_bp (H_bp(x_a) - H_a(x_a)) - beta_ap (H_ap(x_a) - H_a(x_a))] +
+                    [beta_ap (H_ap(x_b) - H_b(x_b)) - beta_bp (H_bp(x_b) - H_b(x_b))]
+                    + beta_pb (H_a(x_a) - H_b(x_b))  - beta_ap (H_a(x_a) - H_b(x_b))
+                 =  ([beta_bp df[bp][a] - beta_ap df[ap][a]) + beta_ap df[ap][b]  - beta_bp df[bp][b])
+                 + (beta_pb-beta_ap)(H_a(x_a) - H_b(x_b))  */
+        delta = beta[bp]*(df[bp][a] - df[bp][b]) + beta[ap]*(df[ap][b] - df[ap][a]) - (beta[bp]-beta[ap])*(Epot[b]-Epot[a]);
+        break;
+    default:
+        gmx_incons("Unknown replica exchange quantity");
+    }
+    if (bPrint)
+    {
+        fprintf(fplog,"Repl %d <-> %d  dE_term = %10.3e (kT)\n",a,b,delta);
+    }
+    if (re->bNPT)
+    {
+        /* revist the calculation for 5.0.  Might be some improvements. */
+        dpV = (beta[ap]*re->pres[ap]-beta[bp]*re->pres[bp])*(Vol[b]-Vol[a])/PRESFAC;
+        if (bPrint) 
+        {
+            fprintf(fplog,"  dpV = %10.3e  d = %10.3e\nb",dpV,delta + dpV);
+        }
+        delta += dpV;
+    }
+    return delta;
+}
+
+static void get_replica_exchange(FILE *fplog,const gmx_multisim_t *ms,
+                                 struct gmx_repl_ex *re,gmx_enerdata_t *enerd,real vol,
+                                 int step,real time,int *pind)
+{
+    int  m,i,a,b,ap,bp,i0,i1,tmp;
+    real *Epot=NULL,*Vol=NULL,**flambda=NULL,*beta=NULL,*prob;
+    real ediff=0,delta=0,dpV=0;
+    gmx_bool *bEx,bPrint,bMultiEx;
+    gmx_bool bEpot=FALSE;
+    gmx_bool bFLambda=FALSE;
+    gmx_bool bVol=FALSE;
+
+    bMultiEx = (re->nex > 1);  /* multiple exchanges at each state */
+    fprintf(fplog,"Replica exchange at step %d time %g\n",step,time);
+
+    snew(beta,re->nrepl);
+    if (re->bNPT)
+    {
+        bVol = TRUE;
+        snew(Vol,re->nrepl);
+        Vol[re->repl]  = vol;
+    }
+
+    if ((re->type == ereTEMP || re->type == ereTL))
+    {
+        bEpot = TRUE;
+        snew(Epot,re->nrepl);
+        Epot[re->repl] = enerd->term[F_EPOT];
+        /* temperatures of different states*/
+        for (i=0;i<re->nrepl;i++)
+        {
+            beta[i] = 1.0/(re->q[ereTEMP][i]*BOLTZ);
+        }
+    }
+    else
+    {
+        for (i=0;i<re->nrepl;i++)
+        {
+            beta[i] = 1.0/(re->temp*BOLTZ);  /* we have a single temperature */
+        }
+    }
+    if (re->type == ereLAMBDA || re->type == ereTL)
+    {
+        bFLambda = TRUE;
+        /* lambda differences. */
+        /* flambda[i][j] is the energy of the jth simulation in the ith Hamiltonian
+           minus the energy of the jth simulation in the jth Hamiltonian */
+        snew(flambda,re->nrepl);
+        for (i=0;i<re->nrepl;i++)
+        {
+            snew(flambda[i],re->nrepl);
+            flambda[i][re->repl] = (enerd->enerpart_lambda[(int)re->q[ereLAMBDA][i]+1]-enerd->enerpart_lambda[0]);
+        }
     }
 
+    /* now actually do the communication */
+    if (bVol)
+    {
+        gmx_sum_sim(re->nrepl,Vol,ms);
+    }
+    if (bEpot)
+    {
+        gmx_sum_sim(re->nrepl,Epot,ms);
+    }
+    if (bFLambda)
+    {
+        for (i=0;i<re->nrepl;i++)
+        {
+            gmx_sum_sim(re->nrepl,flambda[i],ms);
+        }
+    }
     snew(bEx,re->nrepl);
     snew(prob,re->nrepl);
 
-    exchange = -1;
-    m = (step / re->nst) % 2;
-    for(i=1; i<re->nrepl; i++)
+    /* make a duplicate set of indices for shuffling */
+    for(i=0;i<re->nrepl;i++)
+    {
+        pind[i] = re->ind[i];
+    }
+
+    if (bMultiEx)
     {
-        a = re->ind[i-1];
-        b = re->ind[i];
-        bPrint = (re->repl==a || re->repl==b);
-        if (i % 2 == m)
+        /* multiple random switch exchange */
+        for (i=0;i<re->nex;i++)
         {
-            switch (re->type)
+            /* randomly select a pair  */
+            /* find out which state it is from, and what label that state currently has */
+            i0 = (int)(re->nrepl*rando(&(re->seed)));
+            i1 = (int)(re->nrepl*rando(&(re->seed)));
+            if (i0==i1)
             {
-            case ereTEMP:
-                /* Use equations from:
-                 * Okabe et. al. Chem. Phys. Lett. 335 (2001) 435-439
-                 */
-                ediff = Epot[b] - Epot[a];
-                betaA = 1.0/(re->q[a]*BOLTZ);
-                betaB = 1.0/(re->q[b]*BOLTZ);
-                delta = (betaA - betaB)*ediff;
-                break;
-            case ereLAMBDA:
-                /* Here we exchange based on a linear extrapolation of dV/dlambda.
-                 * We would like to have the real energies
-                 * from foreign lambda calculations.
-                 */
-                ediff = (dvdl[a] - dvdl[b])*(re->q[b] - re->q[a]);
-                delta = ediff/(BOLTZ*re->temp);
-                break;
-            default:
-                gmx_incons("Unknown replica exchange quantity");
+                i--;
+                continue;  /* got the same pair, back up and do it again */
             }
-            if (bPrint)
+
+            a = re->ind[i0];
+            b = re->ind[i1];
+            ap = pind[i0];
+            bp = pind[i1];
+
+            bPrint = FALSE; /* too noisy */
+            delta = calc_delta(fplog,bPrint,re,Epot,flambda,Vol,beta,a,b,ap,bp); /* calculate the energy difference */
+
+            /* we actually only use the first space, since there are actually many switches between pairs. */
+
+            if (delta <= 0)
             {
-                fprintf(fplog,"Repl %d <-> %d  dE = %10.3e",a,b,delta);
+                /* accepted */
+                prob[0] = 1;
+                bEx[0] = TRUE;
             }
-            if (re->bNPT)
+            else
             {
-                dpV = (betaA*re->pres[a]-betaB*re->pres[b])*(Vol[b]-Vol[a])/PRESFAC;
-                if (bPrint)
+                if (delta > PROBABILITYCUTOFF)
                 {
-                    fprintf(fplog,"  dpV = %10.3e  d = %10.3e",dpV,delta + dpV);
+                    prob[0] = 0;
                 }
-                delta += dpV;
-            }
-            if (bPrint)
-            {
-                fprintf(fplog,"\n");
+                else
+                {
+                    prob[0] = exp(-delta);
+                }
+                /* roll a number to determine if accepted */
+                bEx[0] = (rando(&(re->seed)) < prob[0]);
             }
-            if (delta <= 0)
+            re->prob_sum[0] += prob[0];
+
+            if (bEx[0])
             {
-                prob[i] = 1;
-                bEx[i] = TRUE;
+                /* swap the states */
+                tmp = pind[i0];
+                pind[i0] = pind[i1];
+                pind[i1] = tmp;
             }
-            else
+        }
+        re->nattempt[0]++;  /* keep track of total permutation trials here */
+        print_allswitchind(fplog,re->nrepl,re->ind,pind,re->allswaps);
+    }
+    else
+    {
+        /* standard nearest neighbor replica exchange */
+        m = (step / re->nst) % 2;
+        for(i=1; i<re->nrepl; i++)
+        {
+            a = re->ind[i-1];
+            b = re->ind[i];
+            
+            bPrint = (re->repl==a || re->repl==b);
+            if (i % 2 == m)
             {
-                if (delta > 100)
-                {
-                    prob[i] = 0;
+                delta = calc_delta(fplog,bPrint,re,Epot,flambda,Vol,beta,a,b,a,b);
+                if (delta <= 0) {
+                    /* accepted */
+                    prob[i] = 1;
+                    bEx[i] = TRUE;
                 }
                 else
                 {
-                    prob[i] = exp(-delta);
+                    if (delta > PROBABILITYCUTOFF)
+                    {
+                        prob[i] = 0;
+                    }
+                    else
+                    {
+                        prob[i] = exp(-delta);
+                    }
+                    /* roll a number to determine if accepted */
+                    bEx[i] = (rando(&(re->seed)) < prob[i]);
                 }
-                bEx[i] = (rando(&(re->seed)) < prob[i]);
-            }
-            re->prob_sum[i] += prob[i];    
-            if (bEx[i])
-            {
-                if (a == re->repl)
+                re->prob_sum[i] += prob[i];
+
+                if (bEx[i])
                 {
-                    exchange = b;
+                    /* swap these two */
+                    tmp = pind[i-1];
+                    pind[i-1] = pind[i];
+                    pind[i] = tmp;
                 }
-                else if (b == re->repl)
+            }
+            else
+            {
+                prob[i] = -1;
+                bEx[i] = FALSE;
+            }
+        }
+        /* print some statistics */
+        print_ind(fplog,"ex",re->nrepl,re->ind,bEx);
+        print_prob(fplog,"pr",re->nrepl,prob);
+        fprintf(fplog,"\n");
+        re->nattempt[m]++;
+    }
+
+    /* record which moves were made and accepted */
+    for (i=0;i<re->nrepl;i++)
+    {
+        re->nmoves[re->ind[i]][pind[i]] +=1;
+        re->nmoves[pind[i]][re->ind[i]] +=1;
+    }
+    /* free up data */
+    sfree(bEx);
+    sfree(prob);
+    sfree(beta);
+    if (re->bNPT)
+    {
+        sfree(Vol);
+    }
+    if ((re->type == ereTEMP || re->type == ereTL))
+    {
+        sfree(Epot);
+    }
+    if ((re->type == ereLAMBDA || re->type == ereTL))
+    {
+        for (i=0;i<re->nrepl;i++)
+        {
+            sfree(flambda[i]);
+        }
+        sfree(flambda);
+    }
+}
+
+static void write_debug_x(t_state *state)
+{
+    int i;
+
+    if (debug)
+    {
+        for(i=0; i<state->natoms; i+=10)
+        {
+            fprintf(debug,"dx %5d %10.5f %10.5f %10.5f\n",i,state->x[i][XX],state->x[i][YY],state->x[i][ZZ]);
+        }
+    }
+}
+
+static void cyclic_decomposition(FILE *fplog, int *pind, int **cyclic, int n, int *nswap)
+{
+
+    int i,j,c,p;
+    int *incycle;
+    int maxlen = 1;
+    snew(incycle,n);
+
+    /* compute cyclic decompositions */
+    for (i=0;i<n;i++)
+    {
+        snew(cyclic[i],n);
+        for (j=0;j<n;j++)
+        {
+            cyclic[i][j] = -1;
+        }
+    }
+
+    for (i=0;i<n;i++)  /* one cycle for each replica */
+    {
+        if (incycle[i])
+        {
+            cyclic[i][0] = -1;
+            continue;
+        }
+        cyclic[i][0] = i;
+        incycle[i] = TRUE;
+        c = 1;
+        p = i;
+        for (j=0;j<n;j++)  /* potentially all cycles are part, but we will break first */
+        {
+            p = pind[p]; /* start permuting */
+            if (p==i)
+            {
+                cyclic[i][c] = -1;
+                if (c > maxlen)
                 {
-                    exchange = a;
+                    maxlen = c;
                 }
-                re->nexchange[i]++;
+                break; /* we've reached the original element, the cycle is complete, and we marked the end. */
+            }
+            else
+            {
+                cyclic[i][c] = p;  /* each permutation gives a new member of the cycle */
+                incycle[p] = TRUE;
+                c++;
             }
         }
-        else
+    }
+    *nswap = maxlen - 1;
+
+    if (debug)
+    {
+        for (i=0;i<n;i++)
         {
-            prob[i] = -1;
-            bEx[i] = FALSE;
+            fprintf(fplog,"Cycle %d:",i);
+            for (j=0;j<n;j++)
+            {
+                if (cyclic[i][j] < 0)
+                {
+                    break;
+                }
+                fprintf(fplog,"%2d",cyclic[i][j]);
+            }
+            fprintf(fplog,"\n");
         }
+        fflush(fplog);
     }
-    print_ind(fplog,"ex",re->nrepl,re->ind,bEx);
-    print_prob(fplog,"pr",re->nrepl,prob);
-    fprintf(fplog,"\n");
+}
 
-    sfree(bEx);
-    sfree(prob);
-    sfree(Epot);
-    sfree(Vol);
-    sfree(dvdl);
-  
-    re->nattempt[m]++;
+static void compute_exchange_order(FILE *fplog, int **cyclic,int **order, int n, int maxswap)
+{
+    int i,j;
 
-    return exchange;
+    for (i=0;i<n;i++)
+    {
+        snew(order[i],maxswap);
+        for (j=0;j<maxswap;j++)
+        {
+            order[i][j] = -1;
+        }
+    }
+    for (j=0;j<maxswap;j++)
+    {
+        for (i=0;i<n;i++)
+        {
+            if (cyclic[i][j+1] >= 0)
+            {
+                order[cyclic[i][j+1]][j] = cyclic[i][j];
+                order[cyclic[i][j]][j] = cyclic[i][j+1];
+            }
+        }
+        for (i=0;i<n;i++)
+        {
+            if (order[i][j] < 0)
+            {
+                order[i][j] = i; /* if it's not exchanging, it should stay this round*/
+            }
+        }
+    }
+    if (debug)
+    {
+        fprintf(fplog,"Replica Exchange Order\n");
+        for (i=0;i<n;i++)
+        {
+            fprintf(fplog,"Replica %d:",i);
+            for (j=0;j<maxswap;j++)
+            {
+                if (order[i][j] < 0) break;
+                fprintf(fplog,"%2d",order[i][j]);
+            }
+            fprintf(fplog,"\n");
+        }
+        fflush(fplog);
+    }
 }
 
 gmx_bool replica_exchange(FILE *fplog,const t_commrec *cr,struct gmx_repl_ex *re,
-                          t_state *state,real *ener,
-                          t_state *state_local,
-                          int step,real time)
+                          t_state *state,gmx_enerdata_t *enerd,
+                          t_state *state_local,int step,real time)
 {
     gmx_multisim_t *ms;
-    int  exchange=-1,shift;
+    int exchange=-1,shift;
+    int i,j,maxswap=0;
+    int *exchanges=NULL;
+    int **cyclic=NULL;
+    int **order=NULL;
     gmx_bool bExchanged=FALSE;
-    
+
     ms = cr->ms;
-  
     if (MASTER(cr))
     {
-        exchange = get_replica_exchange(fplog,ms,re,ener,det(state->box),
-                                        step,time);
-        bExchanged = (exchange >= 0);
+        snew(exchanges,re->nrepl);
+        get_replica_exchange(fplog,ms,re,enerd,det(state->box),step,time,exchanges);
+        bExchanged = (exchanges[re->repl] != re->nrepl);  /* only mark as exchanged if it has a shuffled index */
+        snew(cyclic,re->nrepl);
+        snew(order,re->nrepl);
+
+        /* identify the cyclic decomposition of the permutation (very easy if neighbor replica exchange) */
+        cyclic_decomposition(fplog,exchanges,cyclic,re->nrepl,&maxswap); 
+
+        /* now translate the decompsition into a replica exchange order at each step */
+        compute_exchange_order(fplog,cyclic,order,re->nrepl,maxswap);
+
+        sfree(cyclic); /* don't need this anymore */
     }
-    
     if (PAR(cr))
     {
 #ifdef GMX_MPI
@@ -728,7 +1183,6 @@ gmx_bool replica_exchange(FILE *fplog,const t_commrec *cr,struct gmx_repl_ex *re
                   cr->mpi_comm_mygroup);
 #endif
     }
-    
     if (bExchanged)
     {
         /* Exchange the states */
@@ -748,17 +1202,25 @@ gmx_bool replica_exchange(FILE *fplog,const t_commrec *cr,struct gmx_repl_ex *re
         
         if (MASTER(cr))
         {
-            /* Exchange the global states between the master nodes */
-            if (debug)
+            for (i=0;i<maxswap;i++) /* there will be only one swap cycle with standard replica exchange */
             {
-                fprintf(debug,"Exchanging %d with %d\n",ms->sim,exchange);
+                exchange = order[ms->sim][i];
+
+                if (exchange != ms->sim)
+                {
+                    /* Exchange the global states between the master nodes */
+                    if (debug)
+                    {
+                        fprintf(debug,"Exchanging %d with %d\n",ms->sim,exchange);
+                    }
+                    exchange_state(ms,exchange,state);
+                }
             }
-            exchange_state(ms,exchange,state);
-            
-            if (re->type == ereTEMP)
+            if (re->type == ereTEMP || re->type == ereTL)
             {
-                scale_velocities(state,sqrt(re->q[ms->sim]/re->q[exchange]));
+                scale_velocities(state,sqrt(re->q[ereTEMP][ms->sim]/re->q[ereTEMP][exchanges[ms->sim]]));
             }
+            sfree(order);
         }
 
         /* With domain decomposition the global state is distributed later */
@@ -773,7 +1235,6 @@ gmx_bool replica_exchange(FILE *fplog,const t_commrec *cr,struct gmx_repl_ex *re
             }
         }
     }
-        
     return bExchanged;
 }
 
@@ -781,48 +1242,50 @@ void print_replica_exchange_statistics(FILE *fplog,struct gmx_repl_ex *re)
 {
     real *prob;
     int  i;
-  
+
     fprintf(fplog,"\nReplica exchange statistics\n");
-    fprintf(fplog,"Repl  %d attempts, %d odd, %d even\n",
-            re->nattempt[0]+re->nattempt[1],re->nattempt[1],re->nattempt[0]);
 
-    snew(prob,re->nrepl);
-  
-    fprintf(fplog,"Repl  average probabilities:\n");
-    for(i=1; i<re->nrepl; i++)
+    if (re->nex == 0)
     {
-        if (re->nattempt[i%2] == 0)
-        {
-            prob[i] = 0;
-        }
-        else
-        {
-            prob[i] =  re->prob_sum[i]/re->nattempt[i%2];
-        }
-    }
-    print_ind(fplog,"",re->nrepl,re->ind,NULL);
-    print_prob(fplog,"",re->nrepl,prob);
+        fprintf(fplog,"Repl  %d attempts, %d odd, %d even\n",
+                re->nattempt[0]+re->nattempt[1],re->nattempt[1],re->nattempt[0]);
 
-    fprintf(fplog,"Repl  number of exchanges:\n");
-    print_ind(fplog,"",re->nrepl,re->ind,NULL);
-    print_count(fplog,"",re->nrepl,re->nexchange);
-  
-    fprintf(fplog,"Repl  average number of exchanges:\n");
-    for(i=1; i<re->nrepl; i++)
-    {
-        if (re->nattempt[i%2] == 0)
+        snew(prob,re->nrepl);
+        for(i=1; i<re->nrepl; i++)
         {
-            prob[i] = 0;
+            if (re->nattempt[i%2] == 0)
+            {
+                prob[i] = 0;
+            }
+            else
+            {
+                prob[i] =  re->prob_sum[i]/re->nattempt[i%2];
+            }
         }
-        else
+        print_ind(fplog,"",re->nrepl,re->ind,NULL);
+        print_prob(fplog,"",re->nrepl,prob);
+
+        fprintf(fplog,"Repl  number of exchanges:\n");
+        print_ind(fplog,"",re->nrepl,re->ind,NULL);
+        print_count(fplog,"",re->nrepl,re->nexchange);
+
+        fprintf(fplog,"Repl  average number of exchanges:\n");
+        for(i=1; i<re->nrepl; i++) 
         {
-            prob[i] =  ((real)re->nexchange[i])/re->nattempt[i%2];
+            if (re->nattempt[i%2] == 0)
+            {
+                prob[i] = 0;
+            }
+            else
+            {
+                prob[i] =  ((real)re->nexchange[i])/re->nattempt[i%2];
+            }
         }
+        print_ind(fplog,"",re->nrepl,re->ind,NULL);
+        print_prob(fplog,"",re->nrepl,prob);
+        sfree(prob);
+        fprintf(fplog,"\n");
     }
-    print_ind(fplog,"",re->nrepl,re->ind,NULL);
-    print_prob(fplog,"",re->nrepl,prob);
-
-    sfree(prob);
-  
-    fprintf(fplog,"\n");
+    /* print the transition matrix */
+    print_matrix(fplog,"",re->nrepl,re->nmoves,re->nattempt);
 }
index 4ddc1746aedb3dae79f7d621ef9acfa83e2e9c06..bc5006d13dfc1fe5865755a70a7260250e784d16 100644 (file)
@@ -45,13 +45,13 @@ extern gmx_repl_ex_t init_replica_exchange(FILE *fplog,
                                           const gmx_multisim_t *ms,
                                           const t_state *state,
                                           const t_inputrec *ir,
-                                          int nst,int init_seed);
+                                          int nst, int nmultiex, int init_seed);
 /* Should only be called on the master nodes */
 
 extern gmx_bool replica_exchange(FILE *fplog,
                             const t_commrec *cr,
                             gmx_repl_ex_t re,
-                            t_state *state,real *ener,
+                            t_state *state,gmx_enerdata_t *enerd,
                             t_state *state_local,
                             int step,real time);
 /* Attempts replica exchange, should be called on all nodes.
index 968e75f2d4cdd1115aa8bad31954769d81a020dd..1cb9a4bbcad085a6a0597a26a15b4d5486e89ff0 100644 (file)
@@ -54,7 +54,6 @@
 #include "names.h"
 #include "disre.h"
 #include "orires.h"
-#include "dihre.h"
 #include "pme.h"
 #include "mdatoms.h"
 #include "repl_ex.h"
@@ -136,6 +135,7 @@ struct mdrunner_arglist
     int resetstep;
     int nmultisim;
     int repl_ex_nst;
+    int repl_ex_nex;
     int repl_ex_seed;
     real pforce;
     real cpt_period;
@@ -174,7 +174,7 @@ static void mdrunner_start_fn(void *arg)
                       mc.ddxyz, mc.dd_node_order, mc.rdd,
                       mc.rconstr, mc.dddlb_opt, mc.dlb_scale, 
                       mc.ddcsx, mc.ddcsy, mc.ddcsz, mc.nstepout, mc.resetstep, 
-                      mc.nmultisim, mc.repl_ex_nst, mc.repl_ex_seed, mc.pforce, 
+                      mc.nmultisim, mc.repl_ex_nst, mc.repl_ex_nex, mc.repl_ex_seed, mc.pforce,
                       mc.cpt_period, mc.max_hours, mc.deviceOptions, mc.Flags);
 }
 
@@ -190,7 +190,7 @@ static t_commrec *mdrunner_start_threads(int nthreads,
               const char *dddlb_opt,real dlb_scale,
               const char *ddcsx,const char *ddcsy,const char *ddcsz,
               int nstepout,int resetstep,int nmultisim,int repl_ex_nst,
-              int repl_ex_seed, real pforce,real cpt_period, real max_hours, 
+              int repl_ex_nex, int repl_ex_seed, real pforce,real cpt_period, real max_hours,
               const char *deviceOptions, unsigned long Flags)
 {
     int ret;
@@ -230,6 +230,7 @@ static t_commrec *mdrunner_start_threads(int nthreads,
     mda->resetstep=resetstep;
     mda->nmultisim=nmultisim;
     mda->repl_ex_nst=repl_ex_nst;
+    mda->repl_ex_nex=repl_ex_nex;
     mda->repl_ex_seed=repl_ex_seed;
     mda->pforce=pforce;
     mda->cpt_period=cpt_period;
@@ -340,7 +341,7 @@ int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
              ivec ddxyz,int dd_node_order,real rdd,real rconstr,
              const char *dddlb_opt,real dlb_scale,
              const char *ddcsx,const char *ddcsy,const char *ddcsz,
-             int nstepout,int resetstep,int nmultisim,int repl_ex_nst,
+             int nstepout,int resetstep,int nmultisim, int repl_ex_nst, int repl_ex_nex,
              int repl_ex_seed, real pforce,real cpt_period,real max_hours,
              const char *deviceOptions, unsigned long Flags)
 {
@@ -407,7 +408,7 @@ int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
                                       ddxyz, dd_node_order, rdd, rconstr, 
                                       dddlb_opt, dlb_scale, ddcsx, ddcsy, ddcsz,
                                       nstepout, resetstep, nmultisim, 
-                                      repl_ex_nst, repl_ex_seed, pforce, 
+                                      repl_ex_nst, repl_ex_nex, repl_ex_seed, pforce,
                                       cpt_period, max_hours, deviceOptions, 
                                       Flags);
             /* the main thread continues here with a new cr. We don't deallocate
@@ -446,6 +447,13 @@ int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
     /* now make sure the state is initialized and propagated */
     set_state_entries(state,inputrec,cr->nnodes);
 
+    /* remove when vv and rerun works correctly! */
+    if (PAR(cr) && EI_VV(inputrec->eI) && ((Flags & MD_RERUN) || (Flags & MD_RERUN_VSITE)))
+    {
+        gmx_fatal(FARGS,
+                  "Currently can't do velocity verlet with rerun in parallel.");
+    }
+
     /* A parallel command line option consistency check that we can
        only do after any threads have started. */
     if (!PAR(cr) &&
@@ -709,12 +717,6 @@ int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
             }
         }
 
-        /* Dihedral Restraints */
-        if (gmx_mtop_ftype_count(mtop,F_DIHRES) > 0)
-        {
-            init_dihres(fplog,mtop,inputrec,fcd);
-        }
-
         /* Initiate forcerecord */
         fr = mk_forcerec();
         init_forcerec(fplog,oenv,fr,fcd,inputrec,mtop,cr,box,FALSE,
@@ -869,7 +871,7 @@ int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
         if (inputrec->ePull != epullNO)
         {
             /* Initialize pull code */
-            init_pull(fplog,inputrec,nfile,fnm,mtop,cr,oenv,
+            init_pull(fplog,inputrec,nfile,fnm,mtop,cr,oenv, inputrec->fepvals->init_lambda,
                       EI_DYNAMICS(inputrec->eI) && MASTER(cr),Flags);
         }
         
@@ -900,7 +902,7 @@ int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
                                       nstepout,inputrec,mtop,
                                       fcd,state,
                                       mdatoms,nrnb,wcycle,ed,fr,
-                                      repl_ex_nst,repl_ex_seed,
+                                      repl_ex_nst,repl_ex_nex,repl_ex_seed,
                                       membed,
                                       cpt_period,max_hours,
                                       deviceOptions,
index 426d479fe87ba6c8a2b92a03e07d147536aaa032..60d80e1b6619adcfb278ed42eaaca2768d2484ed 100644 (file)
@@ -496,10 +496,82 @@ static void cmp_pull(FILE *fp,t_pull *pull1,t_pull *pull2,real ftol, real abstol
   fprintf(fp,"WARNING: Both files use COM pulling, but comparing of the pull struct is not implemented (yet). The pull parameters could be the same or different.\n");
 }
 
-static void cmp_inputrec(FILE *fp,t_inputrec *ir1,t_inputrec *ir2,real ftol, real abstol)
+static void cmp_simtempvals(FILE *fp,t_simtemp *simtemp1,t_simtemp *simtemp2, int n_lambda, real ftol, real abstol)
+{
+  int i;
+  cmp_int(fp,"inputrec->simtempvals->eSimTempScale",-1,simtemp1->eSimTempScale,simtemp2->eSimTempScale);
+  cmp_real(fp,"inputrec->simtempvals->simtemp_high",-1,simtemp1->simtemp_high,simtemp2->simtemp_high,ftol,abstol);
+  cmp_real(fp,"inputrec->simtempvals->simtemp_low",-1,simtemp1->simtemp_low,simtemp2->simtemp_low,ftol,abstol);
+  for(i=0; i<n_lambda; i++)
+  {
+      cmp_real(fp,"inputrec->simtempvals->temperatures",-1,simtemp1->temperatures[i],simtemp2->temperatures[i],ftol,abstol);
+  }
+}
+
+static void cmp_expandedvals(FILE *fp,t_expanded *expand1,t_expanded *expand2,int n_lambda, real ftol, real abstol)
 {
   int i;
 
+  cmp_bool(fp,"inputrec->fepvals->bInit_weights",-1,expand1->bInit_weights,expand2->bInit_weights);
+  cmp_bool(fp,"inputrec->fepvals->bWLoneovert",-1,expand1->bWLoneovert,expand2->bWLoneovert);
+
+  for(i=0; i<n_lambda; i++)
+  {
+      cmp_real(fp,"inputrec->expandedvals->init_lambda_weights",-1,
+               expand1->init_lambda_weights[i],expand2->init_lambda_weights[i],ftol,abstol);
+  }
+
+  cmp_int(fp,"inputrec->expandedvals->lambda-stats", -1,expand1->elamstats,expand2->elamstats);
+  cmp_int(fp,"inputrec->expandedvals->lambda-mc-move", -1,expand1->elmcmove,expand2->elmcmove);
+  cmp_int(fp,"inputrec->expandedvals->lmc-repeats",-1,expand1->lmc_repeats,expand2->lmc_repeats);
+  cmp_int(fp,"inputrec->expandedvals->lmc-gibbsdelta",-1,expand1->gibbsdeltalam,expand2->gibbsdeltalam);
+  cmp_int(fp,"inputrec->expandedvals->lmc-forced-nstart",-1,expand1->lmc_forced_nstart,expand2->lmc_forced_nstart);
+  cmp_int(fp,"inputrec->expandedvals->lambda-weights-equil",-1,expand1->elmceq,expand2->elmceq);
+  cmp_int(fp,"inputrec->expandedvals->,weight-equil-number-all-lambda",-1,expand1->equil_n_at_lam,expand2->equil_n_at_lam);
+  cmp_int(fp,"inputrec->expandedvals->weight-equil-number-samples",-1,expand1->equil_samples,expand2->equil_samples);
+  cmp_int(fp,"inputrec->expandedvals->weight-equil-number-steps",-1,expand1->equil_steps,expand2->equil_steps);
+  cmp_real(fp,"inputrec->expandedvals->weight-equil-wl-delta",-1,expand1->equil_wl_delta,expand2->equil_wl_delta,ftol,abstol);
+  cmp_real(fp,"inputrec->expandedvals->weight-equil-count-ratio",-1,expand1->equil_ratio,expand2->equil_ratio,ftol,abstol);
+  cmp_bool(fp,"inputrec->expandedvals->symmetrized-transition-matrix",-1,expand1->bSymmetrizedTMatrix,expand2->bSymmetrizedTMatrix);
+  cmp_int(fp,"inputrec->expandedvals->nstTij",-1,expand1->nstTij,expand2->nstTij);
+  cmp_int(fp,"inputrec->expandedvals->mininum-var-min",-1,expand1->minvarmin,expand2->minvarmin); /*default is reasonable */
+  cmp_int(fp,"inputrec->expandedvals->weight-c-range",-1,expand1->c_range,expand2->c_range); /* default is just C=0 */
+  cmp_real(fp,"inputrec->expandedvals->wl-scale",-1,expand1->wl_scale,expand2->wl_scale,ftol,abstol);
+  cmp_real(fp,"inputrec->expandedvals->init-wl-delta",-1,expand1->init_wl_delta,expand2->init_wl_delta,ftol,abstol);
+  cmp_real(fp,"inputrec->expandedvals->wl-ratio",-1,expand1->wl_ratio,expand2->wl_ratio,ftol,abstol);
+  cmp_int(fp,"inputrec->expandedvals->nstexpanded",-1,expand1->nstexpanded,expand2->nstexpanded);
+  cmp_int(fp,"inputrec->expandedvals->lmc-seed",-1,expand1->lmc_seed,expand2->lmc_seed);
+  cmp_real(fp,"inputrec->expandedvals->mc-temperature",-1,expand1->mc_temp,expand2->mc_temp,ftol,abstol);
+}
+
+static void cmp_fepvals(FILE *fp,t_lambda *fep1,t_lambda *fep2,real ftol, real abstol)
+{
+  int i,j;
+  cmp_int(fp,"inputrec->nstdhdl",-1,fep1->nstdhdl,fep2->nstdhdl);
+  cmp_double(fp,"inputrec->fepvals->init_fep_state",-1,fep1->init_fep_state,fep2->init_fep_state,ftol,abstol);
+  cmp_double(fp,"inputrec->fepvals->delta_lambda",-1,fep1->delta_lambda,fep2->delta_lambda,ftol,abstol);
+  cmp_int(fp,"inputrec->fepvals->n_lambda",-1,fep1->n_lambda,fep2->n_lambda);
+  for(i=0; i<efptNR;i++)
+  {
+      for(j=0; j<min(fep1->n_lambda,fep2->n_lambda); j++)
+      {
+          cmp_double(fp,"inputrec->fepvals->all_lambda",-1,fep1->all_lambda[i][j],fep2->all_lambda[i][j],ftol,abstol);
+      }
+  }
+  cmp_real(fp,"inputrec->fepvals->sc_alpha",-1,fep1->sc_alpha,fep2->sc_alpha,ftol,abstol);
+  cmp_int(fp,"inputrec->fepvals->sc_power",-1,fep1->sc_power,fep2->sc_power);
+  cmp_real(fp,"inputrec->fepvals->sc_r_power",-1,fep1->sc_r_power,fep2->sc_r_power,ftol,abstol);
+  cmp_real(fp,"inputrec->fepvals->sc_sigma",-1,fep1->sc_sigma,fep2->sc_sigma,ftol,abstol);
+  cmp_bool(fp,"inputrec->fepvals->bPrintEnergy",-1,fep1->bPrintEnergy,fep1->bPrintEnergy);
+  cmp_bool(fp,"inputrec->fepvals->bScCoul",-1,fep1->bScCoul,fep1->bScCoul);
+  cmp_int(fp,"inputrec->separate_dhdl_file",-1,fep1->separate_dhdl_file,fep2->separate_dhdl_file);
+  cmp_int(fp,"inputrec->dhdl_derivatives",-1,fep1->dhdl_derivatives,fep2->dhdl_derivatives);
+  cmp_int(fp,"inputrec->dh_hist_size",-1,fep1->dh_hist_size,fep2->dh_hist_size);
+  cmp_double(fp,"inputrec->dh_hist_spacing",-1,fep1->dh_hist_spacing,fep2->dh_hist_spacing,ftol,abstol);
+}
+
+static void cmp_inputrec(FILE *fp,t_inputrec *ir1,t_inputrec *ir2,real ftol, real abstol)
+{
   fprintf(fp,"comparing inputrec\n");
 
   /* gcc 2.96 doesnt like these defines at all, but issues a huge list
@@ -542,6 +614,7 @@ static void cmp_inputrec(FILE *fp,t_inputrec *ir1,t_inputrec *ir2,real ftol, rea
   cmp_int(fp,"inputrec->bContinuation",-1,ir1->bContinuation,ir2->bContinuation);
   cmp_int(fp,"inputrec->bShakeSOR",-1,ir1->bShakeSOR,ir2->bShakeSOR);
   cmp_int(fp,"inputrec->etc",-1,ir1->etc,ir2->etc);
+  cmp_int(fp,"inputrec->bPrintNHChains",-1,ir1->bPrintNHChains,ir2->bPrintNHChains);
   cmp_int(fp,"inputrec->epc",-1,ir1->epc,ir2->epc);
   cmp_int(fp,"inputrec->epct",-1,ir1->epct,ir2->epct);
   cmp_real(fp,"inputrec->tau_p",-1,ir1->tau_p,ir2->tau_p,ftol,abstol);
@@ -552,9 +625,8 @@ static void cmp_inputrec(FILE *fp,t_inputrec *ir1,t_inputrec *ir2,real ftol, rea
   cmp_rvec(fp,"inputrec->compress(y)",-1,ir1->compress[YY],ir2->compress[YY],ftol,abstol);
   cmp_rvec(fp,"inputrec->compress(z)",-1,ir1->compress[ZZ],ir2->compress[ZZ],ftol,abstol);
   cmp_int(fp,"refcoord_scaling",-1,ir1->refcoord_scaling,ir2->refcoord_scaling);
-   cmp_rvec(fp,"inputrec->posres_com",-1,ir1->posres_com,ir2->posres_com,ftol,abstol);
-   cmp_rvec(fp,"inputrec->posres_comB",-1,ir1->posres_comB,ir2->posres_comB,ftol,abstol);
-   cmp_int(fp,"inputrec->andersen_seed",-1,ir1->andersen_seed,ir2->andersen_seed);
+  cmp_rvec(fp,"inputrec->posres_com",-1,ir1->posres_com,ir2->posres_com,ftol,abstol);
+  cmp_rvec(fp,"inputrec->posres_comB",-1,ir1->posres_comB,ir2->posres_comB,ftol,abstol);
   cmp_real(fp,"inputrec->rlist",-1,ir1->rlist,ir2->rlist,ftol,abstol);
   cmp_real(fp,"inputrec->rlistlong",-1,ir1->rlistlong,ir2->rlistlong,ftol,abstol);
   cmp_real(fp,"inputrec->rtpi",-1,ir1->rtpi,ir2->rtpi,ftol,abstol);
@@ -583,22 +655,17 @@ static void cmp_inputrec(FILE *fp,t_inputrec *ir1,t_inputrec *ir2,real ftol, rea
   cmp_int(fp,"inputrec->eDispCorr",-1,ir1->eDispCorr,ir2->eDispCorr);
   cmp_real(fp,"inputrec->shake_tol",-1,ir1->shake_tol,ir2->shake_tol,ftol,abstol);
   cmp_int(fp,"inputrec->efep",-1,ir1->efep,ir2->efep);
-  cmp_double(fp,"inputrec->init_lambda",-1,ir1->init_lambda,ir2->init_lambda,ftol,abstol);
-  cmp_double(fp,"inputrec->delta_lambda",-1,ir1->delta_lambda,ir2->delta_lambda,ftol,abstol);
-  cmp_int(fp,"inputrec->n_foreign_lambda",-1,ir1->n_flambda,ir2->n_flambda);
-  for(i=0; i<min(ir1->n_flambda,ir2->n_flambda); i++) {
-    cmp_double(fp,"inputrec->foreign_lambda",-1,ir1->flambda[i],ir2->flambda[i],ftol,abstol);
+  cmp_fepvals(fp,ir1->fepvals,ir2->fepvals,ftol,abstol);
+  cmp_int(fp,"inputrec->bSimTemp",-1,ir1->bSimTemp,ir2->bSimTemp);
+  if ((ir1->bSimTemp == ir2->bSimTemp) && (ir1->bSimTemp))
+  {
+      cmp_simtempvals(fp,ir1->simtempvals,ir2->simtempvals,min(ir1->fepvals->n_lambda,ir2->fepvals->n_lambda),ftol,abstol);
+  }
+  cmp_int(fp,"inputrec->bExpanded",-1,ir1->bExpanded,ir2->bExpanded);
+  if ((ir1->bExpanded == ir2->bExpanded) && (ir1->bExpanded))
+  {
+      cmp_expandedvals(fp,ir1->expandedvals,ir2->expandedvals,min(ir1->fepvals->n_lambda,ir2->fepvals->n_lambda),ftol,abstol);
   }
-  cmp_real(fp,"inputrec->sc_alpha",-1,ir1->sc_alpha,ir2->sc_alpha,ftol,abstol);
-  cmp_int(fp,"inputrec->sc_power",-1,ir1->sc_power,ir2->sc_power);
-  cmp_real(fp,"inputrec->sc_sigma",-1,ir1->sc_sigma,ir2->sc_sigma,ftol,abstol);
-  cmp_real(fp,"inputrec->sc_sigma_min",-1,ir1->sc_sigma_min,ir2->sc_sigma_min,ftol,abstol);
-  cmp_int(fp,"inputrec->nstdhdl",-1,ir1->nstdhdl,ir2->nstdhdl);
-  cmp_int(fp,"inputrec->separate_dhdl_file",-1,ir1->separate_dhdl_file,ir2->separate_dhdl_file);
-  cmp_int(fp,"inputrec->dhdl_derivatives",-1,ir1->dhdl_derivatives,ir2->dhdl_derivatives);
-  cmp_int(fp,"inputrec->dh_hist_size",-1,ir1->dh_hist_size,ir2->dh_hist_size);
-  cmp_double(fp,"inputrec->dh_hist_spacing",-1,ir1->dh_hist_spacing,ir2->dh_hist_spacing,ftol,abstol);
-
   cmp_int(fp,"inputrec->nwall",-1,ir1->nwall,ir2->nwall);
   cmp_int(fp,"inputrec->wall_type",-1,ir1->wall_type,ir2->wall_type);
   cmp_int(fp,"inputrec->wall_atomtype[0]",-1,ir1->wall_atomtype[0],ir2->wall_atomtype[0]);
index 40946c1126fb824d1e542ff2e5c2dd5816b0dd5b..552444e933db5fe916447ab505e931b1be09a695 100644 (file)
@@ -325,8 +325,8 @@ int main (int argc, char *argv[])
   int          i;
   gmx_large_int_t   nsteps_req,run_step,frame;
   double       run_t,state_t;
-  gmx_bool         bOK,bNsteps,bExtend,bUntil,bTime,bTraj;
-  gmx_bool         bFrame,bUse,bSel,bNeedEner,bReadEner,bScanEner;
+  gmx_bool     bOK,bNsteps,bExtend,bUntil,bTime,bTraj;
+  gmx_bool     bFrame,bUse,bSel,bNeedEner,bReadEner,bScanEner,bFepState;
   gmx_mtop_t   mtop;
   t_atoms      atoms;
   t_inputrec   *ir,*irnew=NULL;
@@ -354,6 +354,7 @@ int main (int argc, char *argv[])
   /* Command line options */
   static int  nsteps_req_int = 0;
   static real start_t = -1.0, extend_t = 0.0, until_t = 0.0;
+  static int init_fep_state = 0;
   static gmx_bool bContinuation = TRUE,bZeroQ = FALSE,bVel=TRUE;
   static t_pargs pa[] = {
     { "-extend",        FALSE, etREAL, {&extend_t}, 
@@ -369,7 +370,9 @@ int main (int argc, char *argv[])
     { "-vel",           FALSE, etBOOL, {&bVel},
       "Require velocities from trajectory" },
     { "-cont",          FALSE, etBOOL, {&bContinuation},
-      "For exact continuation, the constraints should not be applied before the first step" }
+      "For exact continuation, the constraints should not be applied before the first step" },
+    { "-init_fep_state",FALSE, etINT, {&init_fep_state},
+      "fep state to initialize from" },
   };
   int nerror = 0;
   
@@ -381,11 +384,12 @@ int main (int argc, char *argv[])
 
   /* Convert int to gmx_large_int_t */
   nsteps_req = nsteps_req_int;
-  bNsteps = opt2parg_bSet("-nsteps",asize(pa),pa);
-  bExtend = opt2parg_bSet("-extend",asize(pa),pa);
-  bUntil  = opt2parg_bSet("-until",asize(pa),pa);
-  bTime   = opt2parg_bSet("-time",asize(pa),pa);
-  bTraj   = (opt2bSet("-f",NFILE,fnm) || bTime);
+  bNsteps   = opt2parg_bSet("-nsteps",asize(pa),pa);
+  bExtend   = opt2parg_bSet("-extend",asize(pa),pa);
+  bUntil    = opt2parg_bSet("-until",asize(pa),pa);
+  bFepState = opt2parg_bSet("-init_fep_state",asize(pa),pa);
+  bTime     = opt2parg_bSet("-time",asize(pa),pa);
+  bTraj     = (opt2bSet("-f",NFILE,fnm) || bTime);
 
   top_fn = ftp2fn(efTPX,NFILE,fnm);
   fprintf(stderr,"Reading toplogy and stuff from %s\n",top_fn);
@@ -432,195 +436,214 @@ int main (int argc, char *argv[])
 
     frame_fn = ftp2fn(efTRN,NFILE,fnm);
 
-        if (fn2ftp(frame_fn) == efCPT)
-        {
-            int sim_part;
+    if (fn2ftp(frame_fn) == efCPT)
+    {
+        int sim_part;
 
-            fprintf(stderr,
-                    "\nREADING STATE FROM CHECKPOINT %s...\n\n",
-                    frame_fn);
+        fprintf(stderr,
+                "\nREADING STATE FROM CHECKPOINT %s...\n\n",
+                frame_fn);
 
-            read_checkpoint_state(frame_fn,&sim_part,
-                                  &run_step,&run_t,&state);
-        }
-        else
+        read_checkpoint_state(frame_fn,&sim_part,
+                              &run_step,&run_t,&state);
+    }
+    else
+    {
+        fprintf(stderr,
+                "\nREADING COORDS, VELS AND BOX FROM TRAJECTORY %s...\n\n",
+                frame_fn);
+
+        fp = open_trn(frame_fn,"r");
+        if (bScanEner)
         {
-            fprintf(stderr,
-                    "\nREADING COORDS, VELS AND BOX FROM TRAJECTORY %s...\n\n",
-                    frame_fn);
+            fp_ener = open_enx(ftp2fn(efEDR,NFILE,fnm),"r");
+            do_enxnms(fp_ener,&nre,&enm);
+            snew(fr_ener,1);
+            fr_ener->t = -1e-12;
+        }
 
-            fp = open_trn(frame_fn,"r");
-            if (bScanEner)
+        /* Now scan until the last set of x and v (step == 0)
+         * or the ones at step step.
+         */
+        bFrame = TRUE;
+        frame  = 0;
+        while (bFrame)
+        {
+            bFrame = fread_trnheader(fp,&head,&bOK);
+            if (bOK && frame == 0)
             {
-                fp_ener = open_enx(ftp2fn(efEDR,NFILE,fnm),"r");
-                do_enxnms(fp_ener,&nre,&enm);
-                snew(fr_ener,1);
-                fr_ener->t = -1e-12;
+                if (mtop.natoms != head.natoms)
+                    gmx_fatal(FARGS,"Number of atoms in Topology (%d) "
+                              "is not the same as in Trajectory (%d)\n",
+                              mtop.natoms,head.natoms);
+                snew(newx,head.natoms);
+                snew(newv,head.natoms);
             }
-
-            /* Now scan until the last set of x and v (step == 0)
-             * or the ones at step step.
-             */
-            bFrame = TRUE;
-            frame  = 0;
-            while (bFrame)
+            bFrame = bFrame && bOK;
+            if (bFrame)
             {
-                bFrame = fread_trnheader(fp,&head,&bOK);
-                if (bOK && frame == 0)
-                {
-                    if (mtop.natoms != head.natoms) 
-                        gmx_fatal(FARGS,"Number of atoms in Topology (%d) "
-                                  "is not the same as in Trajectory (%d)\n",
-                                  mtop.natoms,head.natoms);
-                    snew(newx,head.natoms);
-                    snew(newv,head.natoms);
-                }
-                bFrame = bFrame && bOK;
-                if (bFrame)
-                {
-                    bOK = fread_htrn(fp,&head,newbox,newx,newv,NULL);
-                }
-                bFrame = bFrame && bOK;
-                bUse = FALSE;
-                if (bFrame &&
-                    (head.x_size) && (head.v_size || !bVel))
+                bOK = fread_htrn(fp,&head,newbox,newx,newv,NULL);
+            }
+            bFrame = bFrame && bOK;
+            bUse = FALSE;
+            if (bFrame &&
+                (head.x_size) && (head.v_size || !bVel))
+            {
+                bUse = TRUE;
+                if (bScanEner)
                 {
-                    bUse = TRUE;
-                    if (bScanEner)
-                    {
-                        /* Read until the energy time is >= the trajectory time */
-                        while (fr_ener->t < head.t && do_enx(fp_ener,fr_ener));
-                        bUse = (fr_ener->t == head.t);
-                    }
-                    if (bUse)
-                    {
-                        tmpx    = newx;
-                        newx    = state.x;
-                        state.x = tmpx;
-                        tmpv    = newv;
-                        newv    = state.v;
-                        state.v = tmpv;
-                        run_t        = head.t;
-                        run_step     = head.step;
-                        state.lambda = head.lambda;
-                        copy_mat(newbox,state.box);
-                    }
+                    /* Read until the energy time is >= the trajectory time */
+                    while (fr_ener->t < head.t && do_enx(fp_ener,fr_ener));
+                    bUse = (fr_ener->t == head.t);
                 }
-                if (bFrame || !bOK)
+                if (bUse)
                 {
-                    sprintf(buf,"\r%s %s frame %s%s: step %s%s time %s",
-                            "%s","%s","%6",gmx_large_int_fmt,"%6",gmx_large_int_fmt," %8.3f");
-                    fprintf(stderr,buf,
-                            bUse ? "Read   " : "Skipped",ftp2ext(fn2ftp(frame_fn)),
-                            frame,head.step,head.t);
-                    frame++;
-                    if (bTime && (head.t >= start_t))
-                        bFrame = FALSE;
+                    tmpx    = newx;
+                    newx    = state.x;
+                    state.x = tmpx;
+                    tmpv    = newv;
+                    newv    = state.v;
+                    state.v = tmpv;
+                    run_t        = head.t;
+                    run_step     = head.step;
+                    state.fep_state = head.fep_state;
+                    state.lambda[efptFEP] = head.lambda;
+                    copy_mat(newbox,state.box);
                 }
             }
-            if (bScanEner)
+            if (bFrame || !bOK)
             {
-                close_enx(fp_ener);
-                free_enxframe(fr_ener);
-                free_enxnms(nre,enm);
+                sprintf(buf,"\r%s %s frame %s%s: step %s%s time %s",
+                        "%s","%s","%6",gmx_large_int_fmt,"%6",gmx_large_int_fmt," %8.3f");
+                fprintf(stderr,buf,
+                        bUse ? "Read   " : "Skipped",ftp2ext(fn2ftp(frame_fn)),
+                        frame,head.step,head.t);
+                frame++;
+                if (bTime && (head.t >= start_t))
+                    bFrame = FALSE;
             }
-            close_trn(fp);
-            fprintf(stderr,"\n");
+        }
+        if (bScanEner)
+        {
+            close_enx(fp_ener);
+            free_enxframe(fr_ener);
+            free_enxnms(nre,enm);
+        }
+        close_trn(fp);
+        fprintf(stderr,"\n");
 
-            if (!bOK)
+        if (!bOK)
+        {
+            fprintf(stderr,"%s frame %s (step %s, time %g) is incomplete\n",
+                    ftp2ext(fn2ftp(frame_fn)),gmx_step_str(frame-1,buf2),
+                    gmx_step_str(head.step,buf),head.t);
+        }
+        fprintf(stderr,"\nUsing frame of step %s time %g\n",
+                gmx_step_str(run_step,buf),run_t);
+
+        if (bNeedEner)
+        {
+            if (bReadEner)
             {
-                fprintf(stderr,"%s frame %s (step %s, time %g) is incomplete\n",
-                        ftp2ext(fn2ftp(frame_fn)),gmx_step_str(frame-1,buf2),
-                        gmx_step_str(head.step,buf),head.t);
+                get_enx_state(ftp2fn(efEDR,NFILE,fnm),run_t,&mtop.groups,ir,&state);
             }
-            fprintf(stderr,"\nUsing frame of step %s time %g\n",
-                    gmx_step_str(run_step,buf),run_t);
-
-            if (bNeedEner)
+            else
             {
-                if (bReadEner)
-                {
-                    get_enx_state(ftp2fn(efEDR,NFILE,fnm),run_t,&mtop.groups,ir,&state);
-                }
-                else
-                {
-                    fprintf(stderr,"\nWARNING: The simulation uses %s temperature and/or %s pressure coupling,\n"
-                            "         the continuation will only be exact when an energy file is supplied\n\n",
-                            ETCOUPLTYPE(etcNOSEHOOVER),
-                            EPCOUPLTYPE(epcPARRINELLORAHMAN));
-                }
+                fprintf(stderr,"\nWARNING: The simulation uses %s temperature and/or %s pressure coupling,\n"
+                        "         the continuation will only be exact when an energy file is supplied\n\n",
+                        ETCOUPLTYPE(etcNOSEHOOVER),
+                        EPCOUPLTYPE(epcPARRINELLORAHMAN));
             }
         }
+        if (bFepState)
+        {
+            ir->fepvals->init_fep_state = init_fep_state;
+        }
+    }
   }
 
   if (bNsteps) {
     fprintf(stderr,"Setting nsteps to %s\n",gmx_step_str(nsteps_req,buf));
     ir->nsteps = nsteps_req;
   } else {
-    /* Determine total number of steps remaining */
-    if (bExtend) {
-      ir->nsteps = ir->nsteps - (run_step - ir->init_step) + (gmx_large_int_t)(extend_t/ir->delta_t + 0.5);
-      printf("Extending remaining runtime of by %g ps (now %s steps)\n",
-            extend_t,gmx_step_str(ir->nsteps,buf));
-    }
-    else if (bUntil) {
-      printf("nsteps = %s, run_step = %s, current_t = %g, until = %g\n",
-            gmx_step_str(ir->nsteps,buf),
-            gmx_step_str(run_step,buf2),
-            run_t,until_t);
-      ir->nsteps = (gmx_large_int_t)((until_t - run_t)/ir->delta_t + 0.5);
-      printf("Extending remaining runtime until %g ps (now %s steps)\n",
-            until_t,gmx_step_str(ir->nsteps,buf));
-    }
-    else {
-      ir->nsteps -= run_step - ir->init_step; 
-      /* Print message */
-      printf("%s steps (%g ps) remaining from first run.\n",
-            gmx_step_str(ir->nsteps,buf),ir->nsteps*ir->delta_t);
-         
-    }
-  }
-
-  if (bNsteps || bZeroQ || (ir->nsteps > 0)) {
-    ir->init_step = run_step;
-    
-    if (ftp2bSet(efNDX,NFILE,fnm) || 
-       !(bNsteps || bExtend || bUntil || bTraj)) {
-      atoms = gmx_mtop_global_atoms(&mtop);
-      get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm),1,
-               &gnx,&index,&grpname);
-      if (!bZeroQ) {
-       bSel = (gnx != state.natoms);
-       for (i=0; ((i<gnx) && (!bSel)); i++)
-         bSel = (i!=index[i]);
+      /* Determine total number of steps remaining */
+      if (bExtend)
+      {
+          ir->nsteps = ir->nsteps - (run_step - ir->init_step) + (gmx_large_int_t)(extend_t/ir->delta_t + 0.5);
+          printf("Extending remaining runtime of by %g ps (now %s steps)\n",
+                 extend_t,gmx_step_str(ir->nsteps,buf));
       }
-      else
-       bSel = FALSE;
-      if (bSel) {
-       fprintf(stderr,"Will write subset %s of original tpx containing %d "
-               "atoms\n",grpname,gnx);
-       reduce_topology_x(gnx,index,&mtop,state.x,state.v);
-       state.natoms = gnx;
-      } 
-      else if (bZeroQ) {
-       zeroq(gnx,index,&mtop);
-       fprintf(stderr,"Zero-ing charges for group %s\n",grpname);
+      else if (bUntil)
+      {
+          printf("nsteps = %s, run_step = %s, current_t = %g, until = %g\n",
+                 gmx_step_str(ir->nsteps,buf),
+                 gmx_step_str(run_step,buf2),
+                 run_t,until_t);
+          ir->nsteps = (gmx_large_int_t)((until_t - run_t)/ir->delta_t + 0.5);
+          printf("Extending remaining runtime until %g ps (now %s steps)\n",
+                 until_t,gmx_step_str(ir->nsteps,buf));
       }
       else
-       fprintf(stderr,"Will write full tpx file (no selection)\n");
-    }    
+      {
+          ir->nsteps -= run_step - ir->init_step;
+          /* Print message */
+          printf("%s steps (%g ps) remaining from first run.\n",
+                 gmx_step_str(ir->nsteps,buf),ir->nsteps*ir->delta_t);
+      }
+  }
+
+  if (bNsteps || bZeroQ || (ir->nsteps > 0))
+  {
+      ir->init_step = run_step;
+
+    if (ftp2bSet(efNDX,NFILE,fnm) ||
+        !(bNsteps || bExtend || bUntil || bTraj))
+    {
+        atoms = gmx_mtop_global_atoms(&mtop);
+        get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm),1,
+                  &gnx,&index,&grpname);
+        if (!bZeroQ)
+        {
+            bSel = (gnx != state.natoms);
+            for (i=0; ((i<gnx) && (!bSel)); i++)
+            {
+                bSel = (i!=index[i]);
+            }
+        }
+        else
+        {
+            bSel = FALSE;
+        }
+        if (bSel)
+        {
+            fprintf(stderr,"Will write subset %s of original tpx containing %d "
+                    "atoms\n",grpname,gnx);
+            reduce_topology_x(gnx,index,&mtop,state.x,state.v);
+            state.natoms = gnx;
+        }
+        else if (bZeroQ)
+        {
+            zeroq(gnx,index,&mtop);
+            fprintf(stderr,"Zero-ing charges for group %s\n",grpname);
+        }
+        else
+        {
+            fprintf(stderr,"Will write full tpx file (no selection)\n");
+        }
+    }
 
     state_t = ir->init_t + ir->init_step*ir->delta_t;
     sprintf(buf,   "Writing statusfile with starting step %s%s and length %s%s steps...\n","%10",gmx_large_int_fmt,"%10",gmx_large_int_fmt);
     fprintf(stderr,buf,ir->init_step,ir->nsteps);
     fprintf(stderr,"                                 time %10.3f and length %10.3f ps\n",
-           state_t,ir->nsteps*ir->delta_t);
+            state_t,ir->nsteps*ir->delta_t);
     write_tpx_state(opt2fn("-o",NFILE,fnm),ir,&state,&mtop);
   }
   else
-    printf("You've simulated long enough. Not writing tpr file\n");
-             
+  {
+      printf("You've simulated long enough. Not writing tpr file\n");
+  }
   thanx(stderr);
-  
+
   return 0;
 }
index 6997e13c31e4184645521004b1d4e3cfe2aeaad2..a0b47b4e41cb4d0505b77518a078c91e9e8c8ec4 100644 (file)
@@ -341,7 +341,7 @@ gmx_bool constrain(FILE *fplog,gmx_bool bLog,gmx_bool bEner,
         /* Set the constraint lengths for the step at which this configuration
          * is meant to be. The invmasses should not be changed.
          */
-        lambda += delta_step*ir->delta_lambda;
+        lambda += delta_step*ir->fepvals->delta_lambda;
     }
     
     if (vir != NULL)
@@ -911,12 +911,12 @@ static real constr_r_max_moltype(FILE *fplog,
       constr_recur(&at2con,molt->ilist,iparams,
                   TRUE,at,0,1+ir->nProjOrder,path,r0,r1,&r2maxB,&count);
     }
-    lam0 = ir->init_lambda;
+    lam0 = ir->fepvals->init_lambda;
     if (EI_DYNAMICS(ir->eI))
-      lam0 += ir->init_step*ir->delta_lambda;
+      lam0 += ir->init_step*ir->fepvals->delta_lambda;
     rmax = (1 - lam0)*sqrt(r2maxA) + lam0*sqrt(r2maxB);
     if (EI_DYNAMICS(ir->eI)) {
-      lam1 = ir->init_lambda + (ir->init_step + ir->nsteps)*ir->delta_lambda;
+      lam1 = ir->fepvals->init_lambda + (ir->init_step + ir->nsteps)*ir->fepvals->delta_lambda;
       rmax = max(rmax,(1 - lam1)*sqrt(r2maxA) + lam1*sqrt(r2maxB));
     }
   }
@@ -1146,3 +1146,17 @@ gmx_bool inter_charge_group_constraints(gmx_mtop_t *mtop)
 
   return bInterCG;
 }
+
+/* helper functions for andersen temperature control, because the
+ * gmx_constr construct is only defined in constr.c. Return the list
+ * of blocks (get_sblock) and the number of blocks (get_nblocks).  */
+
+extern int *get_sblock(struct gmx_constr *constr)
+{
+    return constr->sblock;
+}
+
+extern int get_nblocks(struct gmx_constr *constr)
+{
+    return constr->nblocks;
+}
index 4875d62622bf5f63cc2be0e5d3eb9c8aa3c83634..aaef4f57f7b51ad891d66d9e7cecd21ed21187d0 100644 (file)
@@ -84,7 +84,7 @@ static void NHC_trotter(t_grpopts *opts,int nvar, gmx_ekindata_t *ekind,real dtf
 
     for (i=0; i<nvar; i++) 
     {
-    
+
         /* make it easier to iterate by selecting 
            out the sub-array that corresponds to this T group */
         
@@ -92,7 +92,7 @@ static void NHC_trotter(t_grpopts *opts,int nvar, gmx_ekindata_t *ekind,real dtf
         ixi = &xi[i*nh];
         if (bBarostat) {
             iQinv = &(MassQ->QPinv[i*nh]); 
-            nd = 1; /* THIS WILL CHANGE IF NOT ISOTROPIC */
+            nd = 1.0; /* THIS WILL CHANGE IF NOT ISOTROPIC */
             reft = max(0.0,opts->ref_t[0]);
             Ekin = sqr(*veta)/MassQ->Winv;
         } else {
@@ -212,12 +212,14 @@ static void boxv_trotter(t_inputrec *ir, real *veta, real dt, tensor box,
     alpha = 1.0 + DIM/((double)ir->opts.nrdf[0]);
     alpha *= ekind->tcstat[0].ekinscalef_nhc;
     msmul(ekind->ekin,alpha,ekinmod);  
-    
-    pscal   = calc_pres(ir->ePBC,nwall,box,ekinmod,vir,localpres) + pcorr;
-    
+    /* for now, we use Elr = 0, because if you want to get it right, you
+       really should be using PME. Maybe print a warning? */
+
+    pscal   = calc_pres(ir->ePBC,nwall,box,ekinmod,vir,localpres);
+
     vol = det(box);
     GW = (vol*(MassQ->Winv/PRESFAC))*(DIM*pscal - trace(ir->ref_p));   /* W is in ps^2 * bar * nm^3 */
-    
+
     *veta += 0.5*dt*GW;   
 }
 
@@ -575,23 +577,222 @@ void berendsen_tcoupl(t_inputrec *ir,gmx_ekindata_t *ekind,real dt)
         {
             T = ekind->tcstat[i].Th;
         }
-    
-    if ((opts->tau_t[i] > 0) && (T > 0.0)) {
-      reft = max(0.0,opts->ref_t[i]);
-      lll  = sqrt(1.0 + (dt/opts->tau_t[i])*(reft/T-1.0));
-      ekind->tcstat[i].lambda = max(min(lll,1.25),0.8);
+
+        if ((opts->tau_t[i] > 0) && (T > 0.0)) {  
+            reft = max(0.0,opts->ref_t[i]);
+            lll  = sqrt(1.0 + (dt/opts->tau_t[i])*(reft/T-1.0));
+            ekind->tcstat[i].lambda = max(min(lll,1.25),0.8);
+        }
+        else {
+            ekind->tcstat[i].lambda = 1.0;
+        }
+
+        if (debug)
+        {
+            fprintf(debug,"TC: group %d: T: %g, Lambda: %g\n",
+                    i,T,ekind->tcstat[i].lambda);
+        }
     }
-    else {
-       ekind->tcstat[i].lambda = 1.0;
+}
+
+static int poisson_variate(real lambda,gmx_rng_t rng) {
+
+    real L;
+    int k=0;
+    real p=1.0;
+
+    L = exp(-lambda);
+
+    do
+    {
+        k = k+1;
+        p *= gmx_rng_uniform_real(rng);
+    } while (p>L);
+
+    return k-1;
+}
+
+void andersen_tcoupl(t_inputrec *ir,t_mdatoms *md,t_state *state, gmx_rng_t rng, real rate, t_idef *idef, int nblocks, int *sblock,gmx_bool *randatom, int *randatom_list, gmx_bool *randomize, real *boltzfac)
+{
+    t_grpopts *opts;
+    int    i,j,k,d,len,n,ngtc,gc=0;
+    int    nshake, nsettle, nrandom, nrand_group;
+    real   boltz,scal,reft,prand;
+    t_iatom *iatoms;
+
+    /* convenience variables */
+    opts = &ir->opts;
+    ngtc = opts->ngtc;
+
+    /* idef is only passed in if it's chance-per-particle andersen, so
+       it essentially serves as a boolean to determine which type of
+       andersen is being used */
+    if (idef) {
+
+        /* randomly atoms to randomize.  However, all constraint
+           groups have to have either all of the atoms or none of the
+           atoms randomize.
+
+           Algorithm:
+           1. Select whether or not to randomize each atom to get the correct probability.
+           2. Cycle through the constraint groups.
+              2a. for each constraint group, determine the fraction f of that constraint group that are
+                  chosen to be randomized.
+              2b. all atoms in the constraint group are randomized with probability f.
+        */
+
+        nrandom = 0;
+        if ((rate < 0.05) && (md->homenr > 50))
+        {
+            /* if the rate is relatively high, use a standard method, if low rate,
+             * use poisson */
+            /* poisson distributions approxmation, more efficient for
+             * low rates, fewer random numbers required */
+            nrandom = poisson_variate(md->homenr*rate,rng);  /* how many do we randomize? Use Poisson. */
+            /* now we know how many, choose them randomly. No worries about repeats, at this rate, it's negligible.
+               worst thing that happens, it lowers the true rate an negligible amount */
+            for (i=0;i<nrandom;i++)
+            {
+                randatom[(int)(gmx_rng_uniform_real(rng)*md->homenr)] = TRUE;
+            }
+        }
+        else
+        {
+            for (i=0;i<md->homenr;i++)
+            {
+                if (gmx_rng_uniform_real(rng)<rate)
+                {
+                    randatom[i] = TRUE;
+                    nrandom++;
+                }
+            }
+        }
+
+        /* instead of looping over the constraint groups, if we had a
+           list of which atoms were in which constraint groups, we
+           could then loop over only the groups that are randomized
+           now.  But that is not available now.  Create later after
+           determining whether there actually is any slowing. */
+
+        /* first, loop through the settles to make sure all groups either entirely randomized, or not randomized. */
+
+        nsettle  = idef->il[F_SETTLE].nr/2;
+        for (i=0;i<nsettle;i++)
+        {
+            iatoms = idef->il[F_SETTLE].iatoms;
+            nrand_group = 0;
+            for (k=0;k<3;k++)  /* settles are always 3 atoms, hardcoded */
+            {
+                if (randatom[iatoms[2*i+1]+k])
+                {
+                    nrand_group++;     /* count the number of atoms to be shaken in the settles group */
+                    randatom[iatoms[2*i+1]+k] = FALSE;
+                    nrandom--;
+                }
+            }
+            if (nrand_group > 0)
+            {
+                prand = (nrand_group)/3.0;  /* use this fraction to compute the probability the
+                                               whole group is randomized */
+                if (gmx_rng_uniform_real(rng)<prand)
+                {
+                    for (k=0;k<3;k++)
+                    {
+                        randatom[iatoms[2*i+1]+k] = TRUE;   /* mark them all to be randomized */
+                    }
+                    nrandom+=3;
+                }
+            }
+        }
+
+        /* now loop through the shake groups */
+        nshake = nblocks;
+        for (i=0;i<nshake;i++)
+        {
+            iatoms = &(idef->il[F_CONSTR].iatoms[sblock[i]]);
+            len = sblock[i+1]-sblock[i];
+            nrand_group = 0;
+            for (k=0;k<len;k++)
+            {
+                if (k%3 != 0)
+                {  /* only 2/3 of the sblock items are atoms, the others are labels */
+                    if (randatom[iatoms[k]])
+                    {
+                        nrand_group++;
+                        randatom[iatoms[k]] = FALSE;  /* need to mark it false here in case the atom is in more than
+                                                         one group in the shake block */
+                        nrandom--;
+                    }
+                }
+            }
+            if (nrand_group > 0)
+            {
+                prand = (nrand_group)/(1.0*(2*len/3));
+                if (gmx_rng_uniform_real(rng)<prand)
+                {
+                    for (k=0;k<len;k++)
+                    {
+                        if (k%3 != 0)
+                        {  /* only 2/3 of the sblock items are atoms, the others are labels */
+                            randatom[iatoms[k]] = TRUE; /* randomize all of them */
+                            nrandom++;
+                        }
+                    }
+                }
+            }
+        }
+        if (nrandom > 0)
+        {
+            n = 0;
+            for (i=0;i<md->homenr;i++)  /* now loop over the list of atoms */
+            {
+                if (randatom[i])
+                {
+                    randatom_list[n] = i;
+                    n++;
+                }
+            }
+            nrandom = n;  /* there are some values of nrandom for which
+                             this algorithm won't work; for example all
+                             water molecules and nrandom =/= 3.  Better to
+                             recount and use this number (which we
+                             calculate anyway: it will not affect
+                             the average number of atoms accepted.
+                          */
+        }
+    }
+    else
+    {
+        /* if it's andersen-massive, then randomize all the atoms */
+        nrandom = md->homenr;
+        for (i=0;i<nrandom;i++)
+        {
+            randatom_list[i] = i;
+        }
     }
 
-    if (debug)
-      fprintf(debug,"TC: group %d: T: %g, Lambda: %g\n",
-             i,T,ekind->tcstat[i].lambda);
-  }
+    /* randomize the velocities of the selected particles */
+
+    for (i=0;i<nrandom;i++)  /* now loop over the list of atoms */
+    {
+        n = randatom_list[i];
+        if (md->cTC)
+        {
+            gc   = md->cTC[n];  /* assign the atom to a temperature group if there are more than one */
+        }
+        if (randomize[gc])
+        {
+            scal = sqrt(boltzfac[gc]*md->invmass[n]);
+            for (d=0;d<DIM;d++)
+            {
+                state->v[n][d] = scal*gmx_rng_gaussian_table(rng);
+            }
+        }
+        randatom[n] = FALSE; /* unmark this atom for randomization */
+    }
 }
 
+
 void nosehoover_tcoupl(t_grpopts *opts,gmx_ekindata_t *ekind,real dt,
                        double xi[],double vxi[], t_extmass *MassQ)
 {
@@ -600,7 +801,8 @@ void nosehoover_tcoupl(t_grpopts *opts,gmx_ekindata_t *ekind,real dt,
     
     /* note that this routine does not include Nose-hoover chains yet. Should be easy to add. */
     
-    for(i=0; (i<opts->ngtc); i++) {
+    for(i=0; (i<opts->ngtc); i++)
+    {
         reft = max(0.0,opts->ref_t[i]);
         oldvxi = vxi[i];
         vxi[i]  += dt*MassQ->Qinv[i]*(ekind->tcstat[i].Th - reft);
@@ -608,7 +810,7 @@ void nosehoover_tcoupl(t_grpopts *opts,gmx_ekindata_t *ekind,real dt,
     }
 }
 
-t_state *init_bufstate(const t_state *template_state) 
+t_state *init_bufstate(const t_state *template_state)
 {
     t_state *state;
     int nc = template_state->nhchainlength;
@@ -728,7 +930,7 @@ void trotter_update(t_inputrec *ir,gmx_large_int_t step, gmx_ekindata_t *ekind,
             /* modify the velocities as well */
             for (n=md->start;n<md->start+md->homenr;n++) 
             {
-                if (md->cTC) 
+                if (md->cTC)   /* does this conditional need to be here? is this always true?*/
                 { 
                     gc = md->cTC[n];
                 }
@@ -767,7 +969,8 @@ void trotter_update(t_inputrec *ir,gmx_large_int_t step, gmx_ekindata_t *ekind,
     sfree(scalefac);
 }
 
-int **init_npt_vars(t_inputrec *ir, t_state *state, t_extmass *MassQ, gmx_bool bTrotter) 
+
+extern void init_npt_masses(t_inputrec *ir, t_state *state, t_extmass *MassQ, gmx_bool bInit)
 {
     int n,i,j,d,ntgrp,ngtc,nnhpres,nh,gc=0;
     t_grp_tcstat *tcstat;
@@ -775,15 +978,17 @@ int **init_npt_vars(t_inputrec *ir, t_state *state, t_extmass *MassQ, gmx_bool b
     real ecorr,pcorr,dvdlcorr;
     real bmass,qmass,reft,kT,dt,ndj,nd;
     tensor dumpres,dumvir;
-    int **trotter_seq;
 
     opts = &(ir->opts); /* just for ease of referencing */
-    ngtc = state->ngtc;
+    ngtc = ir->opts.ngtc;
     nnhpres = state->nnhpres;
     nh = state->nhchainlength; 
 
     if (ir->eI == eiMD) {
-        snew(MassQ->Qinv,ngtc);
+        if (bInit)
+        {
+            snew(MassQ->Qinv,ngtc);
+        }
         for(i=0; (i<ngtc); i++) 
         { 
             if ((opts->tau_t[i] > 0) && (opts->ref_t[i] > 0)) 
@@ -799,15 +1004,20 @@ int **init_npt_vars(t_inputrec *ir, t_state *state, t_extmass *MassQ, gmx_bool b
     else if (EI_VV(ir->eI))
     {
     /* Set pressure variables */
-        
-        if (state->vol0 == 0) 
+
+        if (bInit)
         {
-            state->vol0 = det(state->box); /* because we start by defining a fixed compressibility, 
-                                              we need the volume at this compressibility to solve the problem */ 
+            if (state->vol0 == 0)
+            {
+                state->vol0 = det(state->box); 
+                /* because we start by defining a fixed
+                   compressibility, we need the volume at this
+                   compressibility to solve the problem. */
+            }
         }
 
         /* units are nm^3 * ns^2 / (nm^3 * bar / kJ/mol) = kJ/mol  */
-        /* Investigate this more -- is this the right mass to make it? */
+        /* Consider evaluating eventually if this the right mass to use.  All are correct, some might be more stable  */
         MassQ->Winv = (PRESFAC*trace(ir->compress)*BOLTZ*opts->ref_t[0])/(DIM*state->vol0*sqr(ir->tau_p/M_2PI));
         /* An alternate mass definition, from Tuckerman et al. */ 
         /* MassQ->Winv = 1.0/(sqr(ir->tau_p/M_2PI)*(opts->nrdf[0]+DIM)*BOLTZ*opts->ref_t[0]); */
@@ -816,43 +1026,65 @@ int **init_npt_vars(t_inputrec *ir, t_state *state, t_extmass *MassQ, gmx_bool b
             for (n=0;n<DIM;n++) 
             {
                 MassQ->Winvm[d][n]= PRESFAC*ir->compress[d][n]/(state->vol0*sqr(ir->tau_p/M_2PI)); 
-                /* not clear this is correct yet for the anisotropic case*/
-            } 
-        }           
+                /* not clear this is correct yet for the anisotropic case. Will need to reevaluate
+                 before using MTTK for anisotropic states.*/
+            }
+        }
         /* Allocate space for thermostat variables */
-        snew(MassQ->Qinv,ngtc*nh);
-        
+        if (bInit)
+        {
+            snew(MassQ->Qinv,ngtc*nh);
+        }
+
         /* now, set temperature variables */
-        for(i=0; i<ngtc; i++) 
+        for (i=0; i<ngtc; i++)
         {
-            if ((opts->tau_t[i] > 0) && (opts->ref_t[i] > 0)) 
+            if ((opts->tau_t[i] > 0) && (opts->ref_t[i] > 0))
             {
                 reft = max(0.0,opts->ref_t[i]);
                 nd = opts->nrdf[i];
                 kT = BOLTZ*reft;
-                for (j=0;j<nh;j++) 
+                for (j=0;j<nh;j++)
                 {
-                    if (j==0) 
+                    if (j==0)
                     {
                         ndj = nd;
-                    } 
-                    else 
+                    }
+                    else
                     {
                         ndj = 1;
                     }
                     MassQ->Qinv[i*nh+j]   = 1.0/(sqr(opts->tau_t[i]/M_2PI)*ndj*kT);
                 }
             }
-            else 
+            else
             {
                 reft=0.0;
-                for (j=0;j<nh;j++) 
+                for (j=0;j<nh;j++)
                 {
                     MassQ->Qinv[i*nh+j] = 0.0;
                 }
             }
         }
     }
+}
+
+int **init_npt_vars(t_inputrec *ir, t_state *state, t_extmass *MassQ, gmx_bool bTrotter)
+{
+    int n,i,j,d,ntgrp,ngtc,nnhpres,nh,gc=0;
+    t_grp_tcstat *tcstat;
+    t_grpopts *opts;
+    real ecorr,pcorr,dvdlcorr;
+    real bmass,qmass,reft,kT,dt,ndj,nd;
+    tensor dumpres,dumvir;
+    int **trotter_seq;
+
+    opts = &(ir->opts); /* just for ease of referencing */
+    ngtc = state->ngtc;
+    nnhpres = state->nnhpres;
+    nh = state->nhchainlength;
+
+    init_npt_masses(ir, state, MassQ, TRUE);
     
     /* first, initialize clear all the trotter calls */
     snew(trotter_seq,ettTSEQMAX);
@@ -884,41 +1116,59 @@ int **init_npt_vars(t_inputrec *ir, t_state *state, t_extmass *MassQ, gmx_bool b
             /* This is the complicated version - there are 4 possible calls, depending on ordering.
                We start with the initial one. */
             /* first, a round that estimates veta. */
-            trotter_seq[0][0] = etrtBAROV; 
-            
+            trotter_seq[0][0] = etrtBAROV;
+
             /* trotter_seq[1] is etrtNHC for 1/2 step velocities - leave zero */
-            
+
             /* The first half trotter update */
             trotter_seq[2][0] = etrtBAROV;
             trotter_seq[2][1] = etrtNHC;
             trotter_seq[2][2] = etrtBARONHC;
-            
+
             /* The second half trotter update */
             trotter_seq[3][0] = etrtBARONHC;
             trotter_seq[3][1] = etrtNHC;
             trotter_seq[3][2] = etrtBAROV;
 
             /* trotter_seq[4] is etrtNHC for second 1/2 step velocities - leave zero */
-
+            
         } 
-        else 
+        else if (IR_NVT_TROTTER(ir))
         {
-            if (IR_NVT_TROTTER(ir)) 
-            {
-                /* This is the easy version - there are only two calls, both the same. 
-                   Otherwise, even easier -- no calls  */
-                trotter_seq[2][0] = etrtNHC;
-                trotter_seq[3][0] = etrtNHC;
-            }
+            /* This is the easy version - there are only two calls, both the same.
+               Otherwise, even easier -- no calls  */
+            trotter_seq[2][0] = etrtNHC;
+            trotter_seq[3][0] = etrtNHC;
         }
-    } else if (ir->eI==eiVVAK) {
-        if (IR_NPT_TROTTER(ir)) 
+        else if (IR_NPH_TROTTER(ir))
         {
             /* This is the complicated version - there are 4 possible calls, depending on ordering.
                We start with the initial one. */
             /* first, a round that estimates veta. */
-            trotter_seq[0][0] = etrtBAROV; 
-            
+            trotter_seq[0][0] = etrtBAROV;
+
+            /* trotter_seq[1] is etrtNHC for 1/2 step velocities - leave zero */
+
+            /* The first half trotter update */
+            trotter_seq[2][0] = etrtBAROV;
+            trotter_seq[2][1] = etrtBARONHC;
+
+            /* The second half trotter update */
+            trotter_seq[3][0] = etrtBARONHC;
+            trotter_seq[3][1] = etrtBAROV;
+
+            /* trotter_seq[4] is etrtNHC for second 1/2 step velocities - leave zero */
+        }
+    }
+    else if (ir->eI==eiVVAK)
+    {
+        if (IR_NPT_TROTTER(ir))
+        {
+            /* This is the complicated version - there are 4 possible calls, depending on ordering.
+               We start with the initial one. */
+            /* first, a round that estimates veta. */
+            trotter_seq[0][0] = etrtBAROV;
+
             /* The first half trotter update, part 1 -- double update, because it commutes */
             trotter_seq[1][0] = etrtNHC;
 
@@ -930,22 +1180,39 @@ int **init_npt_vars(t_inputrec *ir, t_state *state, t_extmass *MassQ, gmx_bool b
             trotter_seq[3][0] = etrtBARONHC;
             trotter_seq[3][1] = etrtBAROV;
 
-            /* The second half trotter update -- blank for now */
+            /* The second half trotter update */
             trotter_seq[4][0] = etrtNHC;
         } 
-        else 
+        else if (IR_NVT_TROTTER(ir))
         {
-            if (IR_NVT_TROTTER(ir)) 
-            {
-                /* This is the easy version - there is only one call, both the same. 
-                   Otherwise, even easier -- no calls  */
-                trotter_seq[1][0] = etrtNHC;
-                trotter_seq[4][0] = etrtNHC;
-            }
+            /* This is the easy version - there is only one call, both the same.
+               Otherwise, even easier -- no calls  */
+            trotter_seq[1][0] = etrtNHC;
+            trotter_seq[4][0] = etrtNHC;
+        }
+        else if (IR_NPH_TROTTER(ir))
+        {
+            /* This is the complicated version - there are 4 possible calls, depending on ordering.
+               We start with the initial one. */
+            /* first, a round that estimates veta. */
+            trotter_seq[0][0] = etrtBAROV; 
+
+            /* The first half trotter update, part 1 -- leave zero */
+            trotter_seq[1][0] = etrtNHC;
+
+            /* The first half trotter update, part 2 */
+            trotter_seq[2][0] = etrtBAROV;
+            trotter_seq[2][1] = etrtBARONHC;
+
+            /* The second half trotter update, part 1 */
+            trotter_seq[3][0] = etrtBARONHC;
+            trotter_seq[3][1] = etrtBAROV;
+
+            /* The second half trotter update -- blank for now */
         }
     }
 
-    switch (ir->epct) 
+    switch (ir->epct)
     {
     case epctISOTROPIC:  
     default:
@@ -955,7 +1222,7 @@ int **init_npt_vars(t_inputrec *ir, t_state *state, t_extmass *MassQ, gmx_bool b
     snew(MassQ->QPinv,nnhpres*opts->nhchainlength);
 
     /* barostat temperature */
-    if ((ir->tau_p > 0) && (opts->ref_t[0] > 0)) 
+    if ((ir->tau_p > 0) && (opts->ref_t[0] > 0))
     {
         reft = max(0.0,opts->ref_t[0]);
         kT = BOLTZ*reft;
@@ -1028,7 +1295,7 @@ real NPT_energy(t_inputrec *ir, t_state *state, t_extmass *MassQ)
         }
     }
     
-    if (IR_NPT_TROTTER(ir)
+    if (IR_NPT_TROTTER(ir) || IR_NPH_TROTTER(ir))
     {
         /* add the energy from the barostat thermostat chain */
         for (i=0;i<state->nnhpres;i++) {
@@ -1216,7 +1483,7 @@ void vrescale_tcoupl(t_inputrec *ir,gmx_ekindata_t *ekind,real dt,
             Ek = trace(ekind->tcstat[i].ekinh);
         }
         
-        if (opts->tau_t[i] >= 0 && opts->nrdf[i] > 0 && Ek > 0)
+        if (opts->tau_t[i] > 0 && opts->nrdf[i] > 0 && Ek > 0)
         {
             Ek_ref1 = 0.5*opts->ref_t[i]*BOLTZ;
             Ek_ref  = Ek_ref1*opts->nrdf[i];
index f42a47cfa50ece20afc81e8a7f8914e08345a8f6..22c6ac4477ac4a4b48cecbc6b9683fd46140af49 100644 (file)
@@ -1454,7 +1454,10 @@ void dd_collect_state(gmx_domdec_t *dd,
 
     if (DDMASTER(dd))
     {
-        state->lambda = state_local->lambda;
+        for (i=0;i<efptNR;i++) {
+            state->lambda[i] = state_local->lambda[i];
+        }
+        state->fep_state = state_local->fep_state;
         state->veta = state_local->veta;
         state->vol0 = state_local->vol0;
         copy_mat(state_local->box,state->box);
@@ -1707,13 +1710,17 @@ static void dd_distribute_state(gmx_domdec_t *dd,t_block *cgs,
                                 t_state *state,t_state *state_local,
                                 rvec **f)
 {
-    int  i,j,ngtch,ngtcp,nh;
+    int  i,j,nh;
 
     nh = state->nhchainlength;
 
     if (DDMASTER(dd))
     {
-        state_local->lambda = state->lambda;
+        for(i=0;i<efptNR;i++)
+        {
+            state_local->lambda[i] = state->lambda[i];
+        }
+        state_local->fep_state = state->fep_state;
         state_local->veta   = state->veta;
         state_local->vol0   = state->vol0;
         copy_mat(state->box,state_local->box);
@@ -1737,7 +1744,8 @@ static void dd_distribute_state(gmx_domdec_t *dd,t_block *cgs,
             }
         }
     }
-    dd_bcast(dd,sizeof(real),&state_local->lambda);
+    dd_bcast(dd,((efptNR)*sizeof(real)),state_local->lambda);
+    dd_bcast(dd,sizeof(int),&state_local->fep_state);
     dd_bcast(dd,sizeof(real),&state_local->veta);
     dd_bcast(dd,sizeof(real),&state_local->vol0);
     dd_bcast(dd,sizeof(state_local->box),state_local->box);
index 45f921d16ba4cd5092575acc798835c59893b71a..e28a958c9f7b976a7389ab3f233e3e99e125c060 100644 (file)
@@ -37,6 +37,9 @@
 #include "vsite.h"
 #include "gmx_ga2la.h"
 
+/* for dd_init_local_state */
+#define NITEM_DD_INIT_LOCAL_STATE 5
+
 typedef struct {
     int  *index;  /* Index for each atom into il                  */ 
     int  *il;     /* ftype|type|a0|...|an|ftype|...               */
@@ -1573,7 +1576,7 @@ gmx_localtop_t *dd_init_local_top(gmx_mtop_t *top_global)
 void dd_init_local_state(gmx_domdec_t *dd,
                          t_state *state_global,t_state *state_local)
 {
-    int i,j, buf[4];
+    int buf[NITEM_DD_INIT_LOCAL_STATE];
     
     if (DDMASTER(dd))
     {
@@ -1581,10 +1584,11 @@ void dd_init_local_state(gmx_domdec_t *dd,
         buf[1] = state_global->ngtc;
         buf[2] = state_global->nnhpres;
         buf[3] = state_global->nhchainlength;
+        buf[4] = state_global->dfhist.nlambda;
     }
-    dd_bcast(dd,4*sizeof(int),buf);
-    
-    init_state(state_local,0,buf[1],buf[2],buf[3]);
+    dd_bcast(dd,NITEM_DD_INIT_LOCAL_STATE*sizeof(int),buf);
+
+    init_state(state_local,0,buf[1],buf[2],buf[3],buf[4]);
     state_local->flags = buf[0];
     
     /* With Langevin Dynamics we need to make proper storage space
diff --git a/src/mdlib/expanded.c b/src/mdlib/expanded.c
new file mode 100644 (file)
index 0000000..4421198
--- /dev/null
@@ -0,0 +1,1378 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2012, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * GROwing Monsters And Cloning Shrimps
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef GMX_CRAY_XT3
+#include<catamount/dclock.h>
+#endif
+
+
+#include <stdio.h>
+#include <time.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <math.h>
+#include "typedefs.h"
+#include "string2.h"
+#include "gmxfio.h"
+#include "smalloc.h"
+#include "names.h"
+#include "confio.h"
+#include "mvdata.h"
+#include "txtdump.h"
+#include "pbc.h"
+#include "chargegroup.h"
+#include "vec.h"
+#include "nrnb.h"
+#include "mshift.h"
+#include "mdrun.h"
+#include "update.h"
+#include "physics.h"
+#include "main.h"
+#include "mdatoms.h"
+#include "force.h"
+#include "bondf.h"
+#include "pme.h"
+#include "disre.h"
+#include "orires.h"
+#include "network.h"
+#include "calcmu.h"
+#include "constr.h"
+#include "xvgr.h"
+#include "trnio.h"
+#include "xtcio.h"
+#include "copyrite.h"
+#include "gmx_random.h"
+#include "domdec.h"
+#include "partdec.h"
+#include "gmx_wallcycle.h"
+
+#ifdef GMX_LIB_MPI
+#include <mpi.h>
+#endif
+#ifdef GMX_THREADS
+#include "tmpi.h"
+#endif
+
+void GenerateGibbsProbabilities(real *ene, real *p_k, real *pks, int minfep, int maxfep) {
+
+    int i;
+    real maxene;
+
+    *pks = 0.0;
+    maxene = ene[minfep];
+    /* find the maximum value */
+    for (i=minfep;i<=maxfep;i++)
+    {
+        if (ene[i]>maxene)
+        {
+            maxene = ene[i];
+        }
+    }
+    /* find the denominator */
+    for (i=minfep;i<=maxfep;i++)
+    {
+        *pks += exp(ene[i]-maxene);
+    }
+    /*numerators*/
+    for (i=minfep;i<=maxfep;i++)
+    {
+        p_k[i] = exp(ene[i]-maxene) / *pks;
+    }
+}
+
+void GenerateWeightedGibbsProbabilities(real *ene, real *p_k, real *pks, int nlim, real *nvals,real delta) {
+
+    int i;
+    real maxene;
+    real *nene;
+    *pks = 0.0;
+
+    snew(nene,nlim);
+    for (i=0;i<nlim;i++) {
+        if (nvals[i] == 0) {
+            /* add the delta, since we need to make sure it's greater than zero, and
+               we need a non-arbitrary number? */
+            nene[i] = ene[i] + log(nvals[i]+delta);
+        } else {
+            nene[i] = ene[i] + log(nvals[i]);
+        }
+    }
+
+    /* find the maximum value */
+    maxene = nene[0];
+    for (i=0;i<nlim;i++)
+    {
+        if (nene[i] > maxene) {
+            maxene = nene[i];
+        }
+    }
+
+    /* subtract off the maximum, avoiding overflow */
+    for (i=0;i<nlim;i++)
+    {
+        nene[i] -= maxene;
+    }
+
+    /* find the denominator */
+    for (i=0;i<nlim;i++)
+    {
+        *pks += exp(nene[i]);
+    }
+
+    /*numerators*/
+    for (i=0;i<nlim;i++)
+    {
+        p_k[i] = exp(nene[i]) / *pks;
+    }
+    sfree(nene);
+}
+
+real do_logsum(int N, real *a_n) {
+
+    /*     RETURN VALUE */
+    /* log(\sum_{i=0}^(N-1) exp[a_n]) */
+    real maxarg;
+    real sum;
+    int i;
+    real logsum;
+    /*     compute maximum argument to exp(.) */
+
+    maxarg = a_n[0];
+    for(i=1;i<N;i++)
+    {
+        maxarg = max(maxarg,a_n[i]);
+    }
+
+    /* compute sum of exp(a_n - maxarg) */
+    sum = 0.0;
+    for (i=0;i<N;i++)
+    {
+        sum = sum + exp(a_n[i] - maxarg);
+    }
+
+    /*     compute log sum */
+    logsum = log(sum) + maxarg;
+    return logsum;
+}
+
+int FindMinimum(real *min_metric, int N) {
+
+    real min_val;
+    int min_nval,nval;
+
+    min_nval = 0;
+    min_val = min_metric[0];
+
+    for (nval=0; nval<N; nval++)
+    {
+        if (min_metric[nval] < min_val)
+        {
+            min_val = min_metric[nval];
+            min_nval = nval;
+        }
+    }
+    return min_nval;
+}
+
+static gmx_bool CheckHistogramRatios(int nhisto, real *histo, real ratio)
+{
+
+    int i;
+    real nmean;
+    gmx_bool bIfFlat;
+
+    nmean = 0;
+    for (i=0;i<nhisto;i++)
+    {
+        nmean += histo[i];
+    }
+
+    if (nmean == 0)
+    {
+        /* no samples! is bad!*/
+        bIfFlat = FALSE;
+        return bIfFlat;
+    }
+    nmean /= (real)nhisto;
+
+    bIfFlat = TRUE;
+    for (i=0;i<nhisto;i++)
+    {
+        /* make sure that all points are in the ratio < x <  1/ratio range  */
+        if (!((histo[i]/nmean < 1.0/ratio) && (histo[i]/nmean > ratio)))
+        {
+            bIfFlat = FALSE;
+            break;
+        }
+    }
+    return bIfFlat;
+}
+
+static gmx_bool CheckIfDoneEquilibrating(int nlim, t_expanded *expand, df_history_t *dfhist, gmx_large_int_t step)
+{
+
+    int i,totalsamples;
+    gmx_bool bDoneEquilibrating=TRUE;
+    gmx_bool bIfFlat;
+
+    /* assume we have equilibrated the weights, then check to see if any of the conditions are not met */
+
+    /* calculate the total number of samples */
+    switch (expand->elmceq)
+    {
+    case elmceqNO:
+        /* We have not equilibrated, and won't, ever. */
+        return FALSE;
+    case elmceqYES:
+        /* we have equilibrated -- we're done */
+        return TRUE;
+    case elmceqSTEPS:
+        /* first, check if we are equilibrating by steps, if we're still under */
+        if (step < expand->equil_steps)
+        {
+            bDoneEquilibrating = FALSE;
+        }
+        break;
+    case elmceqSAMPLES:
+        totalsamples = 0;
+        for (i=0;i<nlim;i++)
+        {
+            totalsamples += dfhist->n_at_lam[i];
+        }
+        if (totalsamples < expand->equil_samples)
+        {
+            bDoneEquilibrating = FALSE;
+        }
+        break;
+    case elmceqNUMATLAM:
+        for (i=0;i<nlim;i++)
+        {
+            if (dfhist->n_at_lam[i] < expand->equil_n_at_lam) /* we are still doing the initial sweep, so we're definitely not
+                                                                 done equilibrating*/
+            {
+                bDoneEquilibrating  = FALSE;
+                break;
+            }
+        }
+        break;
+    case elmceqWLDELTA:
+        if (EWL(expand->elamstats)) /* This check is in readir as well, but
+                                    just to be sure */
+        {
+            if (dfhist->wl_delta > expand->equil_wl_delta)
+            {
+                bDoneEquilibrating = FALSE;
+            }
+        }
+        break;
+    case elmceqRATIO:
+        /* we can use the flatness as a judge of good weights, as long as
+           we're not doing minvar, or Wang-Landau.
+           But turn off for now until we figure out exactly how we do this.
+        */
+
+        if (!(EWL(expand->elamstats) || expand->elamstats==elamstatsMINVAR))
+        {
+            /* we want to use flatness -avoiding- the forced-through samples.  Plus, we need to convert to
+               floats for this histogram function. */
+
+            real *modhisto;
+            snew(modhisto,nlim);
+            for (i=0;i<nlim;i++)
+            {
+                modhisto[i] = 1.0*(dfhist->n_at_lam[i]-expand->lmc_forced_nstart);
+            }
+            bIfFlat = CheckHistogramRatios(nlim,modhisto,expand->equil_ratio);
+            sfree(modhisto);
+            if (!bIfFlat)
+            {
+                bDoneEquilibrating = FALSE;
+            }
+        }
+    default:
+        bDoneEquilibrating = TRUE;
+    }
+    /* one last case to go though, if we are doing slow growth to get initial values, we haven't finished equilibrating */
+
+    if (expand->lmc_forced_nstart > 0)
+    {
+        for (i=0;i<nlim;i++)
+        {
+            if (dfhist->n_at_lam[i] < expand->lmc_forced_nstart) /* we are still doing the initial sweep, so we're definitely not
+                                                                    done equilibrating*/
+            {
+                bDoneEquilibrating = FALSE;
+                break;
+            }
+        }
+    }
+    return bDoneEquilibrating;
+}
+
+static gmx_bool UpdateWeights(int nlim, t_expanded *expand, df_history_t *dfhist,
+                              int fep_state, real *scaled_lamee, real *weighted_lamee, gmx_large_int_t step)
+{
+    real maxdiff = 0.000000001;
+    gmx_bool bSufficientSamples;
+    int i, k, n, nz, indexi, indexk, min_n, max_n, nlam, totali;
+    int n0,np1,nm1,nval,min_nvalm,min_nvalp,maxc;
+    real omega_m1_0,omega_p1_m1,omega_m1_p1,omega_p1_0,clam_osum;
+    real de,de_function,dr,denom,maxdr,pks=0;
+    real min_val,cnval,zero_sum_weights;
+    real *omegam_array, *weightsm_array, *omegap_array, *weightsp_array, *varm_array, *varp_array, *dwp_array, *dwm_array;
+    real clam_varm, clam_varp, clam_weightsm, clam_weightsp, clam_minvar;
+    real *lam_weights, *lam_minvar_corr, *lam_variance, *lam_dg, *p_k;
+    real *numweighted_lamee, *logfrac;
+    int *nonzero;
+    real chi_m1_0,chi_p1_0,chi_m2_0,chi_p2_0,chi_p1_m1,chi_p2_m1,chi_m1_p1,chi_m2_p1;
+
+    /* if we have equilibrated the weights, exit now */
+    if (dfhist->bEquil)
+    {
+        return FALSE;
+    }
+
+    if (CheckIfDoneEquilibrating(nlim,expand,dfhist,step))
+    {
+        dfhist->bEquil = TRUE;
+        /* zero out the visited states so we know how many equilibrated states we have
+           from here on out.*/
+        for (i=0;i<nlim;i++)
+        {
+            dfhist->n_at_lam[i] = 0;
+        }
+        return TRUE;
+    }
+
+    /* If we reached this far, we have not equilibrated yet, keep on
+       going resetting the weights */
+
+    if (EWL(expand->elamstats))
+    {
+        if (expand->elamstats==elamstatsWL)  /* Standard Wang-Landau */
+        {
+            dfhist->sum_weights[fep_state] -= dfhist->wl_delta;
+            dfhist->wl_histo[fep_state] += 1.0;
+        }
+        else if (expand->elamstats==elamstatsWWL) /* Weighted Wang-Landau */
+        {
+            snew(p_k,nlim);
+
+            /* first increment count */
+            GenerateGibbsProbabilities(weighted_lamee,p_k,&pks,0,nlim-1);
+            for (i=0;i<nlim;i++) {
+                dfhist->wl_histo[i] += p_k[i];
+            }
+
+            /* then increment weights (uses count) */
+            pks = 0.0;
+            GenerateWeightedGibbsProbabilities(weighted_lamee,p_k,&pks,nlim,dfhist->wl_histo,dfhist->wl_delta);
+
+            for (i=0;i<nlim;i++)
+            {
+                dfhist->sum_weights[i] -= dfhist->wl_delta*p_k[i];
+            }
+            /* Alternate definition, using logarithms. Shouldn't make very much difference! */
+            /*
+              real di;
+              for (i=0;i<nlim;i++)
+              {
+                di = 1+dfhist->wl_delta*p_k[i];
+                dfhist->sum_weights[i] -= log(di);
+              }
+            */
+            sfree(p_k);
+        }
+
+        zero_sum_weights =  dfhist->sum_weights[0];
+        for (i=0;i<nlim;i++)
+        {
+            dfhist->sum_weights[i] -= zero_sum_weights;
+        }
+    }
+
+    if (expand->elamstats==elamstatsBARKER || expand->elamstats==elamstatsMETROPOLIS || expand->elamstats==elamstatsMINVAR) {
+
+        de_function = 0;  /* to get rid of warnings, but this value will not be used because of the logic */
+        maxc = 2*expand->c_range+1;
+
+        snew(lam_dg,nlim);
+        snew(lam_variance,nlim);
+
+        snew(omegap_array,maxc);
+        snew(weightsp_array,maxc);
+        snew(varp_array,maxc);
+        snew(dwp_array,maxc);
+
+        snew(omegam_array,maxc);
+        snew(weightsm_array,maxc);
+        snew(varm_array,maxc);
+        snew(dwm_array,maxc);
+
+        /* unpack the current lambdas -- we will only update 2 of these */
+
+        for (i=0;i<nlim-1;i++)
+        { /* only through the second to last */
+            lam_dg[i] = dfhist->sum_dg[i+1] - dfhist->sum_dg[i];
+            lam_variance[i] = pow(dfhist->sum_variance[i+1],2) - pow(dfhist->sum_variance[i],2);
+        }
+
+        /* accumulate running averages */
+        for (nval = 0; nval<maxc; nval++)
+        {
+            /* constants for later use */
+            cnval = (real)(nval-expand->c_range);
+            /* actually, should be able to rewrite it w/o exponential, for better numerical stability */
+            if (fep_state > 0)
+            {
+                de = exp(cnval - (scaled_lamee[fep_state]-scaled_lamee[fep_state-1]));
+                if (expand->elamstats==elamstatsBARKER || expand->elamstats==elamstatsMINVAR)
+                {
+                    de_function = 1.0/(1.0+de);
+                }
+                else if (expand->elamstats==elamstatsMETROPOLIS)
+                {
+                    if (de < 1.0)
+                    {
+                        de_function = 1.0;
+                    }
+                    else
+                    {
+                        de_function = 1.0/de;
+                    }
+                }
+                dfhist->accum_m[fep_state][nval] += de_function;
+                dfhist->accum_m2[fep_state][nval] += de_function*de_function;
+            }
+
+            if (fep_state < nlim-1)
+            {
+                de = exp(-cnval + (scaled_lamee[fep_state+1]-scaled_lamee[fep_state]));
+                if (expand->elamstats==elamstatsBARKER || expand->elamstats==elamstatsMINVAR)
+                {
+                    de_function = 1.0/(1.0+de);
+                }
+                else if (expand->elamstats==elamstatsMETROPOLIS)
+                {
+                    if (de < 1.0)
+                    {
+                        de_function = 1.0;
+                    }
+                    else
+                    {
+                        de_function = 1.0/de;
+                    }
+                }
+                dfhist->accum_p[fep_state][nval] += de_function;
+                dfhist->accum_p2[fep_state][nval] += de_function*de_function;
+            }
+
+            /* Metropolis transition and Barker transition (unoptimized Bennett) acceptance weight determination */
+
+            n0  = dfhist->n_at_lam[fep_state];
+            if (fep_state > 0) {nm1 = dfhist->n_at_lam[fep_state-1];} else {nm1 = 0;}
+            if (fep_state < nlim-1) {np1 = dfhist->n_at_lam[fep_state+1];} else {np1 = 0;}
+
+            /* logic SHOULD keep these all set correctly whatever the logic, but apparently it can't figure it out. */
+            chi_m1_0=chi_p1_0=chi_m2_0=chi_p2_0=chi_p1_m1=chi_p2_m1=chi_m1_p1=chi_m2_p1=0;
+
+            if (n0 > 0)
+            {
+                chi_m1_0 = dfhist->accum_m[fep_state][nval]/n0;
+                chi_p1_0 = dfhist->accum_p[fep_state][nval]/n0;
+                chi_m2_0 = dfhist->accum_m2[fep_state][nval]/n0;
+                chi_p2_0 = dfhist->accum_p2[fep_state][nval]/n0;
+            }
+
+            if ((fep_state > 0 ) && (nm1 > 0))
+            {
+                chi_p1_m1 = dfhist->accum_p[fep_state-1][nval]/nm1;
+                chi_p2_m1 = dfhist->accum_p2[fep_state-1][nval]/nm1;
+            }
+
+            if ((fep_state < nlim-1) && (np1 > 0))
+            {
+                chi_m1_p1 = dfhist->accum_m[fep_state+1][nval]/np1;
+                chi_m2_p1 = dfhist->accum_m2[fep_state+1][nval]/np1;
+            }
+
+            omega_m1_0 = 0;
+            omega_p1_0 = 0;
+            clam_weightsm = 0;
+            clam_weightsp = 0;
+            clam_varm = 0;
+            clam_varp = 0;
+
+            if (fep_state > 0)
+            {
+                if (n0 > 0)
+                {
+                    omega_m1_0 = chi_m2_0/(chi_m1_0*chi_m1_0) - 1.0;
+                }
+                if (nm1 > 0)
+                {
+                    omega_p1_m1 = chi_p2_m1/(chi_p1_m1*chi_p1_m1) - 1.0;
+                }
+                if ((n0 > 0) && (nm1 > 0))
+                {
+                    clam_weightsm = (log(chi_m1_0) - log(chi_p1_m1)) + cnval;
+                    clam_varm = (1.0/n0)*(omega_m1_0) + (1.0/nm1)*(omega_p1_m1);
+                }
+            }
+
+            if (fep_state < nlim-1)
+            {
+                if (n0 > 0)
+                {
+                    omega_p1_0 = chi_p2_0/(chi_p1_0*chi_p1_0) - 1.0;
+                }
+                if (np1 > 0)
+                {
+                    omega_m1_p1 = chi_m2_p1/(chi_m1_p1*chi_m1_p1) - 1.0;
+                }
+                if ((n0 > 0) && (np1 > 0))
+                {
+                    clam_weightsp = (log(chi_m1_p1) - log(chi_p1_0)) + cnval;
+                    clam_varp = (1.0/np1)*(omega_m1_p1) + (1.0/n0)*(omega_p1_0);
+                }
+            }
+
+            if (n0 > 0)
+            {
+                omegam_array[nval]             = omega_m1_0;
+            }
+            else
+            {
+                omegam_array[nval]             = 0;
+            }
+            weightsm_array[nval]           = clam_weightsm;
+            varm_array[nval]               = clam_varm;
+            if (nm1 > 0)
+            {
+                dwm_array[nval]  = fabs( (cnval + log((1.0*n0)/nm1)) - lam_dg[fep_state-1] );
+            }
+            else
+            {
+                dwm_array[nval]  = fabs( cnval - lam_dg[fep_state-1] );
+            }
+
+            if (n0 > 0)
+            {
+                omegap_array[nval]             = omega_p1_0;
+            }
+            else
+            {
+                omegap_array[nval]             = 0;
+            }
+            weightsp_array[nval]           = clam_weightsp;
+            varp_array[nval]               = clam_varp;
+            if ((np1 > 0) && (n0 > 0))
+            {
+                dwp_array[nval]  = fabs( (cnval + log((1.0*np1)/n0)) - lam_dg[fep_state] );
+            }
+            else
+            {
+                dwp_array[nval]  = fabs( cnval - lam_dg[fep_state] );
+            }
+
+        }
+
+        /* find the C's closest to the old weights value */
+
+        min_nvalm = FindMinimum(dwm_array,maxc);
+        omega_m1_0    = omegam_array[min_nvalm];
+        clam_weightsm = weightsm_array[min_nvalm];
+        clam_varm     = varm_array[min_nvalm];
+
+        min_nvalp = FindMinimum(dwp_array,maxc);
+        omega_p1_0    = omegap_array[min_nvalp];
+        clam_weightsp = weightsp_array[min_nvalp];
+        clam_varp     = varp_array[min_nvalp];
+
+        clam_osum = omega_m1_0 + omega_p1_0;
+        clam_minvar = 0;
+        if (clam_osum > 0)
+        {
+            clam_minvar = 0.5*log(clam_osum);
+        }
+
+        if (fep_state > 0)
+        {
+            lam_dg[fep_state-1] = clam_weightsm;
+            lam_variance[fep_state-1] = clam_varm;
+        }
+
+        if (fep_state < nlim-1)
+        {
+            lam_dg[fep_state] = clam_weightsp;
+            lam_variance[fep_state] = clam_varp;
+        }
+
+        if (expand->elamstats==elamstatsMINVAR)
+        {
+            bSufficientSamples = TRUE;
+            /* make sure they are all past a threshold */
+            for (i=0;i<nlim;i++)
+            {
+                if (dfhist->n_at_lam[i] < expand->minvarmin)
+                {
+                    bSufficientSamples = FALSE;
+                }
+            }
+            if (bSufficientSamples)
+            {
+                dfhist->sum_minvar[fep_state] = clam_minvar;
+                if (fep_state==0)
+                {
+                    for (i=0;i<nlim;i++)
+                    {
+                        dfhist->sum_minvar[i]+=(expand->minvar_const-clam_minvar);
+                    }
+                    expand->minvar_const = clam_minvar;
+                    dfhist->sum_minvar[fep_state] = 0.0;
+                }
+                else
+                {
+                    dfhist->sum_minvar[fep_state] -= expand->minvar_const;
+                }
+            }
+        }
+
+        /* we need to rezero minvar now, since it could change at fep_state = 0 */
+        dfhist->sum_dg[0] = 0.0;
+        dfhist->sum_variance[0] = 0.0;
+        dfhist->sum_weights[0] = dfhist->sum_dg[0] + dfhist->sum_minvar[0]; /* should be zero */
+
+        for (i=1;i<nlim;i++)
+        {
+            dfhist->sum_dg[i] = lam_dg[i-1] + dfhist->sum_dg[i-1];
+            dfhist->sum_variance[i] = sqrt(lam_variance[i-1] + pow(dfhist->sum_variance[i-1],2));
+            dfhist->sum_weights[i] = dfhist->sum_dg[i] + dfhist->sum_minvar[i];
+        }
+
+        sfree(lam_dg);
+        sfree(lam_variance);
+
+        sfree(omegam_array);
+        sfree(weightsm_array);
+        sfree(varm_array);
+        sfree(dwm_array);
+
+        sfree(omegap_array);
+        sfree(weightsp_array);
+        sfree(varp_array);
+        sfree(dwp_array);
+    }
+    return FALSE;
+}
+
+static int ChooseNewLambda(FILE *log, int nlim, t_expanded *expand, df_history_t *dfhist, int fep_state, real *weighted_lamee, real *p_k, gmx_rng_t rng)
+{
+    /* Choose new lambda value, and update transition matrix */
+
+    int i,ifep,jfep,minfep,maxfep,lamnew,lamtrial,starting_fep_state;
+    real r1,r2,pks,de_old,de_new,de,trialprob,tprob=0;
+    real **Tij;
+    real *propose,*accept,*remainder;
+    real sum,pnorm;
+    gmx_bool bRestricted;
+
+    starting_fep_state = fep_state;
+    lamnew = fep_state; /* so that there is a default setting -- stays the same */
+
+    if (!EWL(expand->elamstats))   /* ignore equilibrating the weights if using WL */
+    {
+        if ((expand->lmc_forced_nstart > 0) && (dfhist->n_at_lam[nlim-1] <= expand->lmc_forced_nstart))
+        {
+            /* Use a marching method to run through the lambdas and get preliminary free energy data,
+               before starting 'free' sampling.  We start free sampling when we have enough at each lambda */
+
+            /* if we have enough at this lambda, move on to the next one */
+
+            if (dfhist->n_at_lam[fep_state] == expand->lmc_forced_nstart)
+            {
+                lamnew = fep_state+1;
+                if (lamnew == nlim)  /* whoops, stepped too far! */
+                {
+                    lamnew -= 1;
+                }
+            }
+            else
+            {
+                lamnew = fep_state;
+            }
+            return lamnew;
+        }
+    }
+
+    snew(propose,nlim);
+    snew(accept,nlim);
+    snew(remainder,nlim);
+
+    for (i=0;i<expand->lmc_repeats;i++)
+    {
+
+        for(ifep=0;ifep<nlim;ifep++)
+        {
+            propose[ifep] = 0;
+            accept[ifep] = 0;
+        }
+
+        if ((expand->elmcmove==elmcmoveGIBBS) || (expand->elmcmove==elmcmoveMETGIBBS))
+        {
+            bRestricted = TRUE;
+            /* use the Gibbs sampler, with restricted range */
+            if (expand->gibbsdeltalam < 0)
+            {
+                minfep = 0;
+                maxfep = nlim-1;
+                bRestricted = FALSE;
+            }
+            else
+            {
+                minfep = fep_state - expand->gibbsdeltalam;
+                maxfep = fep_state + expand->gibbsdeltalam;
+                if (minfep < 0)
+                {
+                    minfep = 0;
+                }
+                if (maxfep > nlim-1)
+                {
+                    maxfep = nlim-1;
+                }
+            }
+
+            GenerateGibbsProbabilities(weighted_lamee,p_k,&pks,minfep,maxfep);
+
+            if (expand->elmcmove == elmcmoveGIBBS)
+            {
+                for (ifep=minfep;ifep<=maxfep;ifep++)
+                {
+                    propose[ifep] = p_k[ifep];
+                    accept[ifep] = 1.0;
+                }
+                /* Gibbs sampling */
+                r1 = gmx_rng_uniform_real(rng);
+                for (lamnew=minfep;lamnew<=maxfep;lamnew++)
+                {
+                    if (r1 <= p_k[lamnew])
+                    {
+                        break;
+                    }
+                    r1 -= p_k[lamnew];
+                }
+            }
+            else if (expand->elmcmove==elmcmoveMETGIBBS)
+            {
+
+                /* Metropolized Gibbs sampling */
+                for (ifep=minfep;ifep<=maxfep;ifep++)
+                {
+                    remainder[ifep] = 1 - p_k[ifep];
+                }
+
+                /* find the proposal probabilities */
+
+                if (remainder[fep_state] == 0) {
+                    /* only the current state has any probability */
+                    /* we have to stay at the current state */
+                    lamnew=fep_state;
+                } else {
+                    for (ifep=minfep;ifep<=maxfep;ifep++)
+                    {
+                        if (ifep != fep_state)
+                        {
+                            propose[ifep] = p_k[ifep]/remainder[fep_state];
+                        }
+                        else
+                        {
+                            propose[ifep] = 0;
+                        }
+                    }
+
+                    r1 = gmx_rng_uniform_real(rng);
+                    for (lamtrial=minfep;lamtrial<=maxfep;lamtrial++)
+                    {
+                        pnorm = p_k[lamtrial]/remainder[fep_state];
+                        if (lamtrial!=fep_state)
+                        {
+                            if (r1 <= pnorm)
+                            {
+                                break;
+                            }
+                            r1 -= pnorm;
+                        }
+                    }
+
+                    /* we have now selected lamtrial according to p(lamtrial)/1-p(fep_state) */
+                    tprob = 1.0;
+                    /* trial probability is min{1,\frac{1 - p(old)}{1-p(new)} MRS 1/8/2008 */
+                    trialprob = (remainder[fep_state])/(remainder[lamtrial]);
+                    if (trialprob < tprob)
+                    {
+                        tprob = trialprob;
+                    }
+                    r2 = gmx_rng_uniform_real(rng);
+                    if (r2 < tprob)
+                    {
+                        lamnew = lamtrial;
+                    }
+                    else
+                    {
+                        lamnew = fep_state;
+                    }
+                }
+
+                /* now figure out the acceptance probability for each */
+                for (ifep=minfep;ifep<=maxfep;ifep++)
+                {
+                    tprob = 1.0;
+                    if (remainder[ifep] != 0) {
+                        trialprob = (remainder[fep_state])/(remainder[ifep]);
+                    }
+                    else
+                    {
+                        trialprob = 1.0; /* this state is the only choice! */
+                    }
+                    if (trialprob < tprob)
+                    {
+                        tprob = trialprob;
+                    }
+                    /* probability for fep_state=0, but that's fine, it's never proposed! */
+                    accept[ifep] = tprob;
+                }
+            }
+
+            if (lamnew > maxfep)
+            {
+                /* it's possible some rounding is failing */
+                if (remainder[fep_state] < 2.0e-15)
+                {
+                    /* probably numerical rounding error -- no state other than the original has weight */
+                    lamnew = fep_state;
+                }
+                else
+                {
+                    /* probably not a numerical issue */
+                    int loc=0;
+                    int nerror = 200+(maxfep-minfep+1)*60;
+                    char *errorstr;
+                    snew(errorstr,nerror);
+                    /* if its greater than maxfep, then something went wrong -- probably underflow in the calculation
+                       of sum weights. Generated detailed info for failure */
+                    loc += sprintf(errorstr,"Something wrong in choosing new lambda state with a Gibbs move -- probably underflow in weight determination.\nDenominator is: %3d%17.10e\n  i                dE        numerator          weights\n",0,pks);
+                    for (ifep=minfep;ifep<=maxfep;ifep++)
+                    {
+                        loc += sprintf(&errorstr[loc],"%3d %17.10e%17.10e%17.10e\n",ifep,weighted_lamee[ifep],p_k[ifep],dfhist->sum_weights[ifep]);
+                    }
+                    gmx_fatal(FARGS,errorstr);
+                }
+            }
+        }
+        else if ((expand->elmcmove==elmcmoveMETROPOLIS) || (expand->elmcmove==elmcmoveBARKER))
+        {
+            /* use the metropolis sampler with trial +/- 1 */
+            r1 = gmx_rng_uniform_real(rng);
+            if (r1 < 0.5)
+            {
+                if (fep_state == 0) {
+                    lamtrial = fep_state;
+                }
+                else
+                {
+                    lamtrial = fep_state-1;
+                }
+            }
+            else
+            {
+                if (fep_state == nlim-1) {
+                    lamtrial = fep_state;
+                }
+                else
+                {
+                    lamtrial = fep_state+1;
+                }
+            }
+
+            de = weighted_lamee[lamtrial] - weighted_lamee[fep_state];
+            if (expand->elmcmove==elmcmoveMETROPOLIS)
+            {
+                tprob = 1.0;
+                trialprob = exp(de);
+                if (trialprob < tprob)
+                {
+                    tprob = trialprob;
+                }
+                propose[fep_state] = 0;
+                propose[lamtrial] = 1.0; /* note that this overwrites the above line if fep_state = ntrial, which only occurs at the ends */
+                accept[fep_state] = 1.0; /* doesn't actually matter, never proposed unless fep_state = ntrial, in which case it's 1.0 anyway */
+                accept[lamtrial] = tprob;
+
+            }
+            else if (expand->elmcmove==elmcmoveBARKER)
+            {
+                tprob = 1.0/(1.0+exp(-de));
+
+                propose[fep_state] = (1-tprob);
+                propose[lamtrial] += tprob; /* we add, to account for the fact that at the end, they might be the same point */
+                accept[fep_state] = 1.0;
+                accept[lamtrial] = 1.0;
+            }
+
+            r2 = gmx_rng_uniform_real(rng);
+            if (r2 < tprob) {
+                lamnew = lamtrial;
+            } else {
+                lamnew = fep_state;
+            }
+        }
+
+        for (ifep=0;ifep<nlim;ifep++)
+        {
+            dfhist->Tij[fep_state][ifep] += propose[ifep]*accept[ifep];
+            dfhist->Tij[fep_state][fep_state] += propose[ifep]*(1.0-accept[ifep]);
+        }
+        fep_state = lamnew;
+    }
+
+    dfhist->Tij_empirical[starting_fep_state][lamnew] += 1.0;
+
+    sfree(propose);
+    sfree(accept);
+    sfree(remainder);
+
+    return lamnew;
+}
+
+/* print out the weights to the log, along with current state */
+extern void PrintFreeEnergyInfoToFile(FILE *outfile, t_lambda *fep, t_expanded *expand, t_simtemp *simtemp, df_history_t *dfhist,
+                                      int nlam, int frequency, gmx_large_int_t step)
+{
+    int nlim,i,ifep,jfep;
+    real dw,dg,dv,dm,Tprint;
+    real *temps;
+    const char *print_names[efptNR] = {" FEPL","MassL","CoulL"," VdwL","BondL","RestT","Temp.(K)"};
+    gmx_bool bSimTemp = FALSE;
+
+    nlim = fep->n_lambda;
+    if (simtemp != NULL) {
+        bSimTemp = TRUE;
+    }
+
+    if (mod(step,frequency)==0)
+    {
+        fprintf(outfile,"             MC-lambda information\n");
+        if (EWL(expand->elamstats) && (!(dfhist->bEquil))) {
+            fprintf(outfile,"  Wang-Landau incrementor is: %11.5g\n",dfhist->wl_delta);
+        }
+        fprintf(outfile,"  N");
+        for (i=0;i<efptNR;i++)
+        {
+            if (fep->separate_dvdl[i])
+            {
+                fprintf(outfile,"%7s",print_names[i]);
+            }
+            else if ((i == efptTEMPERATURE) && bSimTemp)
+            {
+                fprintf(outfile,"%10s",print_names[i]); /* more space for temperature formats */
+            }
+        }
+        fprintf(outfile,"    Count   ");
+        if (expand->elamstats==elamstatsMINVAR)
+        {
+            fprintf(outfile,"W(in kT)   G(in kT)  dG(in kT)  dV(in kT)\n");
+        }
+        else
+        {
+            fprintf(outfile,"G(in kT)  dG(in kT)\n");
+        }
+        for (ifep=0;ifep<nlim;ifep++)
+        {
+            if (ifep==nlim-1)
+            {
+                dw=0.0;
+                dg=0.0;
+                dv=0.0;
+                dm=0.0;
+            }
+            else
+            {
+                dw = dfhist->sum_weights[ifep+1] - dfhist->sum_weights[ifep];
+                dg = dfhist->sum_dg[ifep+1] - dfhist->sum_dg[ifep];
+                dv = sqrt(pow(dfhist->sum_variance[ifep+1],2) - pow(dfhist->sum_variance[ifep],2));
+                dm = dfhist->sum_minvar[ifep+1] - dfhist->sum_minvar[ifep];
+
+            }
+            fprintf(outfile,"%3d",(ifep+1));
+            for (i=0;i<efptNR;i++)
+            {
+                if (fep->separate_dvdl[i])
+                {
+                    fprintf(outfile,"%7.3f",fep->all_lambda[i][ifep]);
+                } else if (i == efptTEMPERATURE && bSimTemp)
+                {
+                    fprintf(outfile,"%9.3f",simtemp->temperatures[ifep]);
+                }
+            }
+            if (EWL(expand->elamstats) && (!(dfhist->bEquil)))  /* if performing WL and still haven't equilibrated */
+            {
+                if (expand->elamstats == elamstatsWL)
+                {
+                    fprintf(outfile," %8d",(int)dfhist->wl_histo[ifep]);
+                } else {
+                    fprintf(outfile," %8.3f",dfhist->wl_histo[ifep]);
+                }
+            }
+            else   /* we have equilibrated weights */
+            {
+                fprintf(outfile," %8d",dfhist->n_at_lam[ifep]);
+            }
+            if (expand->elamstats==elamstatsMINVAR)
+            {
+                fprintf(outfile," %10.5f %10.5f %10.5f %10.5f",dfhist->sum_weights[ifep],dfhist->sum_dg[ifep],dg,dv);
+            }
+            else
+            {
+                fprintf(outfile," %10.5f %10.5f",dfhist->sum_weights[ifep],dw);
+            }
+            if (ifep == nlam) {
+                fprintf(outfile," <<\n");
+            }
+            else
+            {
+                fprintf(outfile,"   \n");
+            }
+        }
+        fprintf(outfile,"\n");
+
+        if ((mod(step,expand->nstTij)==0) && (expand->nstTij > 0) && (step > 0))
+        {
+            fprintf(outfile,"                     Transition Matrix\n");
+            for (ifep=0;ifep<nlim;ifep++)
+            {
+                fprintf(outfile,"%12d",(ifep+1));
+            }
+            fprintf(outfile,"\n");
+            for (ifep=0;ifep<nlim;ifep++)
+            {
+                for (jfep=0;jfep<nlim;jfep++)
+                {
+                    if (dfhist->n_at_lam[ifep] > 0)
+                    {
+                        if (expand->bSymmetrizedTMatrix)
+                        {
+                            Tprint = (dfhist->Tij[ifep][jfep]+dfhist->Tij[jfep][ifep])/(dfhist->n_at_lam[ifep]+dfhist->n_at_lam[jfep]);
+                        } else {
+                            Tprint = (dfhist->Tij[ifep][jfep])/(dfhist->n_at_lam[ifep]);
+                        }
+                    }
+                    else
+                    {
+                        Tprint = 0.0;
+                    }
+                    fprintf(outfile,"%12.8f",Tprint);
+                }
+                fprintf(outfile,"%3d\n",(ifep+1));
+            }
+
+            fprintf(outfile,"                  Empirical Transition Matrix\n");
+            for (ifep=0;ifep<nlim;ifep++)
+            {
+                fprintf(outfile,"%12d",(ifep+1));
+            }
+            fprintf(outfile,"\n");
+            for (ifep=0;ifep<nlim;ifep++)
+            {
+                for (jfep=0;jfep<nlim;jfep++)
+                {
+                    if (dfhist->n_at_lam[ifep] > 0)
+                    {
+                        if (expand->bSymmetrizedTMatrix)
+                        {
+                            Tprint = (dfhist->Tij_empirical[ifep][jfep]+dfhist->Tij_empirical[jfep][ifep])/(dfhist->n_at_lam[ifep]+dfhist->n_at_lam[jfep]);
+                        } else {
+                            Tprint = dfhist->Tij_empirical[ifep][jfep]/(dfhist->n_at_lam[ifep]);
+                        }
+                    }
+                    else
+                    {
+                        Tprint = 0.0;
+                    }
+                    fprintf(outfile,"%12.8f",Tprint);
+                }
+                fprintf(outfile,"%3d\n",(ifep+1));
+            }
+        }
+       }
+}
+
+extern void get_mc_state(gmx_rng_t rng,t_state *state)
+{
+    gmx_rng_get_state(rng,state->mc_rng,state->mc_rngi);
+}
+
+extern void set_mc_state(gmx_rng_t rng,t_state *state)
+{
+    gmx_rng_set_state(rng,state->mc_rng,state->mc_rngi[0]);
+}
+
+extern int ExpandedEnsembleDynamics(FILE *log,t_inputrec *ir, gmx_enerdata_t *enerd,
+                                    t_state *state, t_extmass *MassQ, df_history_t *dfhist,
+                                    gmx_large_int_t step, gmx_rng_t mcrng,
+                                    rvec *v, t_mdatoms *mdatoms)
+{
+    real *pfep_lamee,*p_k, *scaled_lamee, *weighted_lamee;
+    int i,nlam,nlim,lamnew,totalsamples;
+    real oneovert,maxscaled=0,maxweighted=0;
+    t_expanded *expand;
+    t_simtemp *simtemp;
+    double *temperature_lambdas;
+    gmx_bool bIfReset,bSwitchtoOneOverT,bDoneEquilibrating=FALSE;
+
+    expand = ir->expandedvals;
+    simtemp = ir->simtempvals;
+       nlim = ir->fepvals->n_lambda;
+    nlam = state->fep_state;
+
+    snew(scaled_lamee,nlim);
+    snew(weighted_lamee,nlim);
+    snew(pfep_lamee,nlim);
+    snew(p_k,nlim);
+
+    if (expand->bInit_weights)  /* if initialized weights, we need to fill them in */
+    {
+        dfhist->wl_delta = expand->init_wl_delta;  /* MRS -- this would fit better somewhere else? */
+        for (i=0;i<nlim;i++) {
+            dfhist->sum_weights[i] = expand->init_lambda_weights[i];
+            dfhist->sum_dg[i] = expand->init_lambda_weights[i];
+        }
+        expand->bInit_weights = FALSE;
+    }
+
+       /* update the count at the current lambda*/
+       dfhist->n_at_lam[nlam]++;
+
+    /* need to calculate the PV term somewhere, but not needed here? Not until there's a lambda state that's
+       pressure controlled.*/
+    /*
+      pVTerm = 0;
+      where does this PV term go?
+      for (i=0;i<nlim;i++)
+      {
+      fep_lamee[i] += pVTerm;
+      }
+    */
+
+       /* determine the minimum value to avoid overflow.  Probably a better way to do this */
+       /* we don't need to include the pressure term, since the volume is the same between the two.
+          is there some term we are neglecting, however? */
+
+    if (ir->efep != efepNO)
+    {
+        for (i=0;i<nlim;i++)
+        {
+            if (ir->bSimTemp)
+            {
+                /* Note -- this assumes no mass changes, since kinetic energy is not added  . . . */
+                scaled_lamee[i] = (enerd->enerpart_lambda[i+1]-enerd->enerpart_lambda[0])/(simtemp->temperatures[i]*BOLTZ)
+                    + enerd->term[F_EPOT]*(1.0/(simtemp->temperatures[i])- 1.0/(simtemp->temperatures[nlam]))/BOLTZ;
+            }
+            else
+            {
+                scaled_lamee[i] = (enerd->enerpart_lambda[i+1]-enerd->enerpart_lambda[0])/(expand->mc_temp*BOLTZ);
+                /* mc_temp is currently set to the system reft unless otherwise defined */
+            }
+
+            /* save these energies for printing, so they don't get overwritten by the next step */
+            /* they aren't overwritten in the non-free energy case, but we always print with these
+               for simplicity */
+        }
+    } else {
+        if (ir->bSimTemp) {
+            for (i=0;i<nlim;i++) {
+                scaled_lamee[i] = enerd->term[F_EPOT]*(1.0/simtemp->temperatures[i] - 1.0/simtemp->temperatures[nlam])/BOLTZ;
+            }
+        }
+    }
+
+       for (i=0;i<nlim;i++) {
+        pfep_lamee[i] = scaled_lamee[i];
+
+        weighted_lamee[i] = dfhist->sum_weights[i] - scaled_lamee[i];
+        if (i==0)
+        {
+            maxscaled = scaled_lamee[i];
+            maxweighted = weighted_lamee[i];
+        }
+        else
+        {
+            if (scaled_lamee[i] > maxscaled)
+            {
+                maxscaled = scaled_lamee[i];
+            }
+            if (weighted_lamee[i] > maxweighted)
+            {
+                maxweighted = weighted_lamee[i];
+            }
+        }
+       }
+
+       for (i=0;i<nlim;i++)
+    {
+        scaled_lamee[i] -= maxscaled;
+        weighted_lamee[i] -= maxweighted;
+       }
+
+       /* update weights - we decide whether or not to actually do this inside */
+
+       bDoneEquilibrating = UpdateWeights(nlim,expand,dfhist,nlam,scaled_lamee,weighted_lamee,step);
+    if (bDoneEquilibrating)
+    {
+        if (log) {
+            fprintf(log,"\nStep %d: Weights have equilibrated, using criteria: %s\n",(int)step,elmceq_names[expand->elmceq]);
+        }
+    }
+
+    lamnew = ChooseNewLambda(log,nlim,expand,dfhist,nlam,weighted_lamee,p_k,mcrng);
+    /* if using simulated tempering, we need to adjust the temperatures */
+    if (ir->bSimTemp && (lamnew != nlam)) /* only need to change the temperatures if we change the state */
+    {
+        int i, j, n, d;
+        real *buf_ngtc;
+        real told;
+        int nstart, nend, gt;
+
+        snew(buf_ngtc,ir->opts.ngtc);
+
+        for (i=0;i<ir->opts.ngtc;i++) {
+            if (ir->opts.ref_t[i] > 0) {
+                told = ir->opts.ref_t[i];
+                ir->opts.ref_t[i] =  simtemp->temperatures[lamnew];
+                buf_ngtc[i] = sqrt(ir->opts.ref_t[i]/told); /* using the buffer as temperature scaling */
+            }
+        }
+
+        /* we don't need to manipulate the ekind information, as it isn't due to be reset until the next step anyway */
+
+        nstart = mdatoms->start;
+        nend   = nstart + mdatoms->homenr;
+        for (n=nstart; n<nend; n++)
+        {
+            gt = 0;
+            if (mdatoms->cTC)
+            {
+                gt = mdatoms->cTC[n];
+            }
+            for(d=0; d<DIM; d++)
+            {
+                 v[n][d] *= buf_ngtc[gt];
+            }
+        }
+
+        if (IR_NPT_TROTTER(ir) || IR_NPH_TROTTER(ir) || IR_NVT_TROTTER(ir)) {
+            /* we need to recalculate the masses if the temperature has changed */
+            init_npt_masses(ir,state,MassQ,FALSE);
+            for (i=0;i<state->nnhpres;i++)
+            {
+                for (j=0;j<ir->opts.nhchainlength;j++)
+                {
+                    state->nhpres_vxi[i+j] *= buf_ngtc[i];
+                }
+            }
+            for (i=0;i<ir->opts.ngtc;i++)
+            {
+                for (j=0;j<ir->opts.nhchainlength;j++)
+                {
+                    state->nosehoover_vxi[i+j] *= buf_ngtc[i];
+                }
+            }
+        }
+        sfree(buf_ngtc);
+    }
+
+       /* now check on the Wang-Landau updating critera */
+
+       if (EWL(expand->elamstats))
+    {
+        bSwitchtoOneOverT = FALSE;
+        if (expand->bWLoneovert) {
+            totalsamples = 0;
+            for (i=0;i<nlim;i++)
+            {
+                totalsamples += dfhist->n_at_lam[i];
+            }
+            oneovert = (1.0*nlim)/totalsamples;
+            /* oneovert has decreasd by a bit since last time, so we actually make sure its within one of this number */
+            /* switch to 1/t incrementing when wl_delta has decreased at least once, and wl_delta is now less than 1/t */
+            if ((dfhist->wl_delta <= ((totalsamples)/(totalsamples-1.00001))*oneovert) &&
+                (dfhist->wl_delta < expand->init_wl_delta))
+            {
+                bSwitchtoOneOverT = TRUE;
+            }
+        }
+        if (bSwitchtoOneOverT) {
+            dfhist->wl_delta = oneovert; /* now we reduce by this each time, instead of only at flatness */
+        } else {
+            bIfReset = CheckHistogramRatios(nlim,dfhist->wl_histo,expand->wl_ratio);
+            if (bIfReset)
+            {
+                for (i=0;i<nlim;i++)
+                {
+                    dfhist->wl_histo[i] = 0;
+                }
+                dfhist->wl_delta *= expand->wl_scale;
+                if (log) {
+                    fprintf(log,"\nStep %d: weights are now:",(int)step);
+                    for (i=0;i<nlim;i++)
+                    {
+                        fprintf(log," %.5f",dfhist->sum_weights[i]);
+                    }
+                    fprintf(log,"\n");
+                }
+            }
+        }
+    }
+    sfree(scaled_lamee);
+    sfree(weighted_lamee);
+    sfree(p_k);
+
+    return lamnew;
+}
+
+
index 60988b7d8c5e40f47361ee6ca2bb9fae4cd8f85e..19be8f6fe6129d7ed7db4887a12b885091ceb0cd 100644 (file)
@@ -1,12 +1,12 @@
 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
  *
- * 
+ *
  *                This source code is part of
- * 
+ *
  *                 G   R   O   M   A   C   S
- * 
+ *
  *          GROningen MAchine for Chemical Simulations
- * 
+ *
  *                        VERSION 3.2.0
  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * If you want to redistribute modifications, please consider that
  * scientific software is very special. Version control is crucial -
  * bugs must be traceable. We will be happy to consider code for
  * inclusion in the official distribution, but derived work must not
  * be called official GROMACS. Details are found in the README & COPYING
  * files - if they are missing, get the official version at www.gromacs.org.
- * 
+ *
  * To help us fund GROMACS development, we humbly ask that you cite
  * the papers on the package - you can find them in the top README file.
- * 
+ *
  * For more info, check our website at http://www.gromacs.org
- * 
+ *
  * And Hey:
  * GROwing Monsters And Cloning Shrimps
  */
@@ -75,7 +75,7 @@ void ns(FILE *fp,
         t_mdatoms  *md,
         t_commrec  *cr,
         t_nrnb     *nrnb,
-        real       lambda,
+        real       *lambda,
         real       *dvdlambda,
         gmx_grppairener_t *grppener,
         gmx_bool       bFillGrid,
@@ -91,8 +91,8 @@ void ns(FILE *fp,
   {
       init_neighbor_list(fp, fr, md->homenr);
   }
-    
-  if (fr->bTwinRange) 
+
+  if (fr->bTwinRange)
     fr->nlr=0;
 
     nsearch = search_neighbours(fp,fr,x,box,top,groups,cr,nrnb,md,
@@ -101,7 +101,7 @@ void ns(FILE *fp,
                                 bDoForces,f);
   if (debug)
     fprintf(debug,"nsearch = %d\n",nsearch);
-    
+
   /* Check whether we have to do dynamic load balancing */
   /*if ((nsb->nstDlb > 0) && (mod(step,nsb->nstDlb) == 0))
     count_nb(cr,nsb,&(top->blocks[ebCGS]),nns,fr->nlr,
@@ -129,62 +129,69 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                        t_atomtypes *atype,
                        gmx_bool       bBornRadii,
                        matrix     box,
-                       real       lambda,  
+                       t_lambda   *fepvals,
+                       real       *lambda,
                        t_graph    *graph,
-                       t_blocka   *excl,    
+                       t_blocka   *excl,
                        rvec       mu_tot[],
                        int        flags,
                        float      *cycles_pme)
 {
-    int     i,status;
+    int     i,j,status;
     int     donb_flags;
     gmx_bool    bDoEpot,bSepDVDL,bSB;
     int     pme_flags;
     matrix  boxs;
     rvec    box_size;
-    real    dvdlambda,Vsr,Vlr,Vcorr=0,vdip,vcharge;
+    real    Vsr,Vlr,Vcorr=0,vdip,vcharge;
     t_pbc   pbc;
     real    dvdgb;
     char    buf[22];
     gmx_enerdata_t ed_lam;
-    double  lam_i;
-    real    dvdl_dum;
+    double  clam_i,vlam_i;
+    real    dvdl_dum[efptNR], dvdlambda[efptNR], lam_i[efptNR];
+    real    dvdlsum,dvdl_walls;
 
 #ifdef GMX_MPI
     double  t0=0.0,t1,t2,t3; /* time measurement for coarse load balancing */
 #endif
-    
-#define PRINT_SEPDVDL(s,v,dvdl) if (bSepDVDL) fprintf(fplog,sepdvdlformat,s,v,dvdl);
-    
+
+#define PRINT_SEPDVDL(s,v,dvdlambda) if (bSepDVDL) fprintf(fplog,sepdvdlformat,s,v,dvdlambda);
+
     GMX_MPE_LOG(ev_force_start);
     set_pbc(&pbc,fr->ePBC,box);
-    
+
+    /* reset free energy components */
+    for (i=0;i<efptNR;i++)
+    {
+        dvdlambda[i] = 0;
+        dvdl_dum[i] = 0;
+    }
+
     /* Reset box */
     for(i=0; (i<DIM); i++)
     {
         box_size[i]=box[i][i];
     }
-    
+
     bSepDVDL=(fr->bSepDVDL && do_per_step(step,ir->nstlog));
     debug_gmx();
-    
+
     /* do QMMM first if requested */
     if(fr->bQMMM)
     {
         enerd->term[F_EQM] = calculate_QMMM(cr,x,f,fr,md);
     }
-    
+
     if (bSepDVDL)
     {
         fprintf(fplog,"Step %s: non-bonded V and dVdl for node %d:\n",
                 gmx_step_str(step,buf),cr->nodeid);
     }
-    
+
     /* Call the short range functions all in one go. */
     GMX_MPE_LOG(ev_do_fnbf_start);
-    
-    dvdlambda = 0;
-    
+
 #ifdef GMX_MPI
     /*#define TAKETIME ((cr->npmenodes) && (fr->timesteps < 12))*/
 #define TAKETIME FALSE
@@ -194,57 +201,62 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
         t0=MPI_Wtime();
     }
 #endif
-    
+
     if (ir->nwall)
     {
-        dvdlambda = do_walls(ir,fr,box,md,x,f,lambda,
-                             enerd->grpp.ener[egLJSR],nrnb);
-        PRINT_SEPDVDL("Walls",0.0,dvdlambda);
-        enerd->dvdl_lin += dvdlambda;
+        /* foreign lambda component for walls */
+        dvdl_walls = do_walls(ir,fr,box,md,x,f,lambda[efptVDW],
+                 enerd->grpp.ener[egLJSR],nrnb);
+        PRINT_SEPDVDL("Walls",0.0,dvdl_walls);
+        dvdlambda[efptVDW] += dvdl_walls;
+        enerd->dvdl_lin[efptVDW] += dvdl_walls;
     }
-               
+
        /* If doing GB, reset dvda and calculate the Born radii */
        if (ir->implicit_solvent)
        {
                /* wallcycle_start(wcycle,ewcGB); */
-               
+
                for(i=0;i<born->nr;i++)
                {
                        fr->dvda[i]=0;
                }
-               
+
                if(bBornRadii)
                {
                        calc_gb_rad(cr,fr,ir,top,atype,x,&(fr->gblist),born,md,nrnb);
                }
-               
+
                /* wallcycle_stop(wcycle, ewcGB); */
        }
-       
+
     where();
     donb_flags = 0;
     if (flags & GMX_FORCE_FORCES)
     {
         donb_flags |= GMX_DONB_FORCES;
     }
+
     do_nonbonded(cr,fr,x,f,md,excl,
                  fr->bBHAM ?
                  enerd->grpp.ener[egBHAMSR] :
                  enerd->grpp.ener[egLJSR],
                  enerd->grpp.ener[egCOULSR],
                                 enerd->grpp.ener[egGB],box_size,nrnb,
-                 lambda,&dvdlambda,-1,-1,donb_flags);
+                 lambda,dvdlambda,-1,-1,donb_flags);
     /* If we do foreign lambda and we have soft-core interactions
      * we have to recalculate the (non-linear) energies contributions.
      */
-    if (ir->n_flambda > 0 && (flags & GMX_FORCE_DHDL) && ir->sc_alpha != 0)
+    if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL) && fepvals->sc_alpha != 0)
     {
-        init_enerdata(mtop->groups.grps[egcENER].nr,ir->n_flambda,&ed_lam);
-        
+        init_enerdata(mtop->groups.grps[egcENER].nr,fepvals->n_lambda,&ed_lam);
+
         for(i=0; i<enerd->n_lambda; i++)
         {
-            lam_i = (i==0 ? lambda : ir->flambda[i-1]);
-            dvdl_dum = 0;
+            for (j=0;j<efptNR;j++)
+            {
+                lam_i[j] = (i==0 ? lambda[j] : fepvals->all_lambda[j][i-1]);
+            }
             reset_enerdata(&ir->opts,fr,TRUE,&ed_lam,FALSE);
             do_nonbonded(cr,fr,x,f,md,excl,
                          fr->bBHAM ?
@@ -252,7 +264,7 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                          ed_lam.grpp.ener[egLJSR],
                          ed_lam.grpp.ener[egCOULSR],
                          enerd->grpp.ener[egGB], box_size,nrnb,
-                         lam_i,&dvdl_dum,-1,-1,
+                         lam_i,dvdl_dum,-1,-1,
                          GMX_DONB_FOREIGNLAMBDA);
             sum_epot(&ir->opts,&ed_lam);
             enerd->enerpart_lambda[i] += ed_lam.term[F_EPOT];
@@ -260,9 +272,10 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
         destroy_enerdata(&ed_lam);
     }
     where();
-       
-       /* If we are doing GB, calculate bonded forces and apply corrections 
+
+       /* If we are doing GB, calculate bonded forces and apply corrections
         * to the solvation forces */
+    /* MRS: Eventually, many need to include free energy contribution here! */
        if (ir->implicit_solvent)  {
                calc_gb_forces(cr,md,born,top,atype,x,f,fr,idef,
                        ir->gb_algorithm,ir->sa_algorithm,nrnb,bBornRadii,&pbc,graph,enerd);
@@ -275,15 +288,28 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
         fr->t_fnbf += t1-t0;
     }
 #endif
-    
-    if (ir->sc_alpha != 0)
+
+    if (fepvals->sc_alpha!=0)
     {
-        enerd->dvdl_nonlin += dvdlambda;
+        enerd->dvdl_nonlin[efptVDW] += dvdlambda[efptVDW];
     }
     else
     {
-        enerd->dvdl_lin    += dvdlambda;
+        enerd->dvdl_lin[efptVDW] += dvdlambda[efptVDW];
+    }
+
+    if (fepvals->sc_alpha!=0)
+
+        /* even though coulomb part is linear, we already added it, beacuse we
+           need to go through the vdw calculation anyway */
+    {
+        enerd->dvdl_nonlin[efptCOUL] += dvdlambda[efptCOUL];
     }
+    else
+    {
+        enerd->dvdl_lin[efptCOUL] += dvdlambda[efptCOUL];
+    }
+
     Vsr = 0;
     if (bSepDVDL)
     {
@@ -295,22 +321,23 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                  enerd->grpp.ener[egLJSR][i])
                 + enerd->grpp.ener[egCOULSR][i] + enerd->grpp.ener[egGB][i];
         }
+        dvdlsum = dvdlambda[efptVDW]+dvdlambda[efptCOUL];
+        PRINT_SEPDVDL("VdW and Coulomb SR particle-p.",Vsr,dvdlsum);
     }
-    PRINT_SEPDVDL("VdW and Coulomb SR particle-p.",Vsr,dvdlambda);
     debug_gmx();
-    
+
     GMX_MPE_LOG(ev_do_fnbf_finish);
-    
+
     if (debug)
     {
         pr_rvecs(debug,0,"fshift after SR",fr->fshift,SHIFTS);
     }
-    
-    /* Shift the coordinates. Must be done before bonded forces and PPPM, 
-     * but is also necessary for SHAKE and update, therefore it can NOT 
+
+    /* Shift the coordinates. Must be done before bonded forces and PPPM,
+     * but is also necessary for SHAKE and update, therefore it can NOT
      * go when no bonded forces have to be evaluated.
      */
-    
+
     /* Here sometimes we would not need to shift with NBFonly,
      * but we do so anyhow for consistency of the returned coordinates.
      */
@@ -337,7 +364,7 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
         set_pbc_dd(&pbc,fr->ePBC,cr->dd,TRUE,box);
     }
     debug_gmx();
-    
+
     if (flags & GMX_FORCE_BONDED)
     {
         GMX_MPE_LOG(ev_calc_bonds_start);
@@ -345,28 +372,28 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                    idef,x,hist,f,fr,&pbc,graph,enerd,nrnb,lambda,md,fcd,
                    DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL, atype, born,
                    fr->bSepDVDL && do_per_step(step,ir->nstlog),step);
-        
+
         /* Check if we have to determine energy differences
          * at foreign lambda's.
          */
-        if (ir->n_flambda > 0 && (flags & GMX_FORCE_DHDL) &&
+        if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL) &&
             idef->ilsort != ilsortNO_FE)
         {
             if (idef->ilsort != ilsortFE_SORTED)
             {
                 gmx_incons("The bonded interactions are not sorted for free energy");
             }
-            init_enerdata(mtop->groups.grps[egcENER].nr,ir->n_flambda,&ed_lam);
-            
+            init_enerdata(mtop->groups.grps[egcENER].nr,fepvals->n_lambda,&ed_lam);
+
             for(i=0; i<enerd->n_lambda; i++)
             {
-                lam_i = (i==0 ? lambda : ir->flambda[i-1]);
-                dvdl_dum = 0;
                 reset_enerdata(&ir->opts,fr,TRUE,&ed_lam,FALSE);
-                calc_bonds_lambda(fplog,
-                                  idef,x,fr,&pbc,graph,&ed_lam,nrnb,lam_i,md,
-                                  fcd,
-                                  DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL);
+                for (j=0;j<efptNR;j++)
+                {
+                    lam_i[j] = (i==0 ? lambda[j] : fepvals->all_lambda[j][i-1]);
+                }
+                calc_bonds_lambda(fplog,idef,x,fr,&pbc,graph,&ed_lam,nrnb,lam_i,md,
+                                  fcd,DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL);
                 sum_epot(&ir->opts,&ed_lam);
                 enerd->enerpart_lambda[i] += ed_lam.term[F_EPOT];
             }
@@ -388,14 +415,14 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
             svmul(ir->wall_ewald_zfac,boxs[ZZ],boxs[ZZ]);
             box_size[ZZ] *= ir->wall_ewald_zfac;
         }
-        
-        clear_mat(fr->vir_el_recip);   
-        
+
+        clear_mat(fr->vir_el_recip);
+
         if (fr->bEwald)
         {
             if (fr->n_tpi == 0)
             {
-                dvdlambda = 0;
+                dvdlambda[efptCOUL] = 0;
                 Vcorr = ewald_LRcorrection(fplog,md->start,md->start+md->homenr,
                                            cr,fr,
                                            md->chargeA,
@@ -403,9 +430,9 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                                            excl,x,bSB ? boxs : box,mu_tot,
                                            ir->ewald_geometry,
                                            ir->epsilon_surface,
-                                           lambda,&dvdlambda,&vdip,&vcharge);
+                                           lambda[efptCOUL],&dvdlambda[efptCOUL],&vdip,&vcharge);
                 PRINT_SEPDVDL("Ewald excl./charge/dip. corr.",Vcorr,dvdlambda);
-                enerd->dvdl_lin += dvdlambda;
+                enerd->dvdl_lin[efptCOUL] += dvdlambda[efptCOUL];
             }
             else
             {
@@ -420,8 +447,8 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                 Vcorr = 0;
             }
         }
-        
-        dvdlambda = 0;
+
+        dvdlambda[efptCOUL] = 0;
         status = 0;
         switch (fr->eeltype)
         {
@@ -459,7 +486,7 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                                         DOMAINDECOMP(cr) ? dd_pme_maxshift_y(cr->dd) : 0,
                                         nrnb,wcycle,
                                         fr->vir_el_recip,fr->ewaldcoeff,
-                                        &Vlr,lambda,&dvdlambda,
+                                        &Vlr,lambda[efptCOUL],&dvdlambda[efptCOUL],
                                         pme_flags);
                     *cycles_pme = wallcycle_stop(wcycle,ewcPMEMESH);
 
@@ -481,8 +508,8 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                                         md->chargeA + md->homenr - fr->n_tpi,
                                         &Vlr);
                 }
-                PRINT_SEPDVDL("PME mesh",Vlr,dvdlambda);
-            } 
+                PRINT_SEPDVDL("PME mesh",Vlr,dvdlambda[efptCOUL]);
+            }
             else
             {
                 /* Energies and virial are obtained later from the PME nodes */
@@ -495,8 +522,8 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                            md->chargeA,md->chargeB,
                            box_size,cr,md->homenr,
                            fr->vir_el_recip,fr->ewaldcoeff,
-                           lambda,&dvdlambda,fr->ewald_table);
-            PRINT_SEPDVDL("Ewald long-range",Vlr,dvdlambda);
+                           lambda[efptCOUL],&dvdlambda[efptCOUL],fr->ewald_table);
+            PRINT_SEPDVDL("Ewald long-range",Vlr,dvdlambda[efptCOUL]);
             break;
         default:
             Vlr = 0;
@@ -508,7 +535,7 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
             gmx_fatal(FARGS,"Error %d in long range electrostatics routine %s",
                       status,EELTYPE(fr->eeltype));
                }
-        enerd->dvdl_lin += dvdlambda;
+        enerd->dvdl_lin[efptCOUL] += dvdlambda[efptCOUL];
         enerd->term[F_COUL_RECIP] = Vlr + Vcorr;
         if (debug)
         {
@@ -522,29 +549,29 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
     {
         if (EEL_RF(fr->eeltype))
         {
-            dvdlambda = 0;
-            
+            dvdlambda[efptCOUL] = 0;
+
             if (fr->eeltype != eelRF_NEC)
             {
                 enerd->term[F_RF_EXCL] =
                     RF_excl_correction(fplog,fr,graph,md,excl,x,f,
-                                       fr->fshift,&pbc,lambda,&dvdlambda);
+                                       fr->fshift,&pbc,lambda[efptCOUL],&dvdlambda[efptCOUL]);
             }
-            
-            enerd->dvdl_lin += dvdlambda;
+
+            enerd->dvdl_lin[efptCOUL] += dvdlambda[efptCOUL];
             PRINT_SEPDVDL("RF exclusion correction",
-                          enerd->term[F_RF_EXCL],dvdlambda);
+                          enerd->term[F_RF_EXCL],dvdlambda[efptCOUL]);
         }
     }
     where();
     debug_gmx();
-       
+
     if (debug)
     {
-        print_nrnb(debug,nrnb); 
+        print_nrnb(debug,nrnb);
     }
     debug_gmx();
-    
+
 #ifdef GMX_MPI
     if (TAKETIME)
     {
@@ -554,33 +581,39 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
         fr->t_wait += t3-t2;
         if (fr->timesteps == 11)
         {
-            fprintf(stderr,"* PP load balancing info: node %d, step %s, rel wait time=%3.0f%% , load string value: %7.2f\n", 
-                    cr->nodeid, gmx_step_str(fr->timesteps,buf), 
-                    100*fr->t_wait/(fr->t_wait+fr->t_fnbf), 
+            fprintf(stderr,"* PP load balancing info: node %d, step %s, rel wait time=%3.0f%% , load string value: %7.2f\n",
+                    cr->nodeid, gmx_step_str(fr->timesteps,buf),
+                    100*fr->t_wait/(fr->t_wait+fr->t_fnbf),
                     (fr->t_fnbf+fr->t_wait)/fr->t_fnbf);
-        }        
+        }
         fr->timesteps++;
     }
 #endif
-    
+
     if (debug)
     {
         pr_rvecs(debug,0,"fshift after bondeds",fr->fshift,SHIFTS);
     }
-    
+
     GMX_MPE_LOG(ev_force_finish);
 
 }
 
-void init_enerdata(int ngener,int n_flambda,gmx_enerdata_t *enerd)
+void init_enerdata(int ngener,int n_lambda,gmx_enerdata_t *enerd)
 {
     int i,n2;
-    
+
     for(i=0; i<F_NRE; i++)
     {
         enerd->term[i] = 0;
     }
-    
+
+
+    for(i=0; i<efptNR; i++) {
+        enerd->dvdl_lin[i]  = 0;
+        enerd->dvdl_nonlin[i]  = 0;
+    }
+
     n2=ngener*ngener;
     if (debug)
     {
@@ -592,9 +625,9 @@ void init_enerdata(int ngener,int n_flambda,gmx_enerdata_t *enerd)
         snew(enerd->grpp.ener[i],n2);
     }
 
-    if (n_flambda)
+    if (n_lambda)
     {
-        enerd->n_lambda = 1 + n_flambda;
+        enerd->n_lambda = 1 + n_lambda;
         snew(enerd->enerpart_lambda,enerd->n_lambda);
     }
     else
@@ -622,11 +655,11 @@ static real sum_v(int n,real v[])
 {
   real t;
   int  i;
-  
+
   t = 0.0;
   for(i=0; (i<n); i++)
     t = t + v[i];
-    
+
   return t;
 }
 
@@ -635,7 +668,7 @@ void sum_epot(t_grpopts *opts,gmx_enerdata_t *enerd)
   gmx_grppairener_t *grpp;
   real *epot;
   int i;
-  
+
   grpp = &enerd->grpp;
   epot = enerd->term;
 
@@ -648,7 +681,7 @@ void sum_epot(t_grpopts *opts,gmx_enerdata_t *enerd)
   epot[F_LJ_LR]    = sum_v(grpp->nener,grpp->ener[egLJLR]);
   /* We have already added 1-2,1-3, and 1-4 terms to F_GBPOL */
   epot[F_GBPOL]   += sum_v(grpp->nener,grpp->ener[egGB]);
-    
+
 /* lattice part of LR doesnt belong to any group
  * and has been added earlier
  */
@@ -657,45 +690,104 @@ void sum_epot(t_grpopts *opts,gmx_enerdata_t *enerd)
 
   epot[F_EPOT] = 0;
   for(i=0; (i<F_EPOT); i++)
-    if (i != F_DISRESVIOL && i != F_ORIRESDEV && i != F_DIHRESVIOL)
-      epot[F_EPOT] += epot[i];
+  {
+      if (i != F_DISRESVIOL && i != F_ORIRESDEV)
+      {
+          epot[F_EPOT] += epot[i];
+      }
+  }
 }
 
-void sum_dhdl(gmx_enerdata_t *enerd,double lambda,t_inputrec *ir)
+void sum_dhdl(gmx_enerdata_t *enerd, real *lambda, t_lambda *fepvals)
 {
-    int i;
-    double dlam,dhdl_lin;
+    int i,j,index;
+    double dlam;
 
-    enerd->term[F_DVDL] = enerd->dvdl_lin + enerd->dvdl_nonlin;
-
-    if (debug)
+    enerd->dvdl_lin[efptVDW] += enerd->term[F_DVDL_VDW];  /* include dispersion correction */
+    enerd->term[F_DVDL] = 0.0;
+    for (i=0;i<efptNR;i++)
     {
-        fprintf(debug,"dvdl: %f, non-linear %f + linear %f\n",
-                enerd->term[F_DVDL],enerd->dvdl_nonlin,enerd->dvdl_lin);
+        if (fepvals->separate_dvdl[i])
+        {
+            /* could this be done more readably/compactly? */
+            switch (i) {
+            case (efptCOUL):
+                index = F_DVDL_COUL;
+                break;
+            case (efptVDW):
+                index = F_DVDL_VDW;
+                break;
+            case (efptBONDED):
+                index = F_DVDL_BONDED;
+                break;
+            case (efptRESTRAINT):
+                index = F_DVDL_RESTRAINT;
+                break;
+            case (efptMASS):
+                index = F_DKDL;
+                break;
+            default:
+                index = F_DVDL;
+                break;
+            }
+            enerd->term[index] = enerd->dvdl_lin[i] + enerd->dvdl_nonlin[i];
+            if (debug)
+            {
+                fprintf(debug,"dvdl-%s[%2d]: %f: non-linear %f + linear %f\n",
+                        efpt_names[i],i,enerd->term[index],enerd->dvdl_nonlin[i],enerd->dvdl_lin[i]);
+            }
+        }
+        else
+        {
+            enerd->term[F_DVDL] += enerd->dvdl_lin[i] + enerd->dvdl_nonlin[i];
+            if (debug)
+            {
+                fprintf(debug,"dvd-%sl[%2d]: %f: non-linear %f + linear %f\n",
+                        efpt_names[0],i,enerd->term[F_DVDL],enerd->dvdl_nonlin[i],enerd->dvdl_lin[i]);
+            }
+        }
     }
 
     /* Notes on the foreign lambda free energy difference evaluation:
      * Adding the potential and ekin terms that depend linearly on lambda
      * as delta lam * dvdl to the energy differences is exact.
-     * For the constraint dvdl this is not exact, but we have no other option.
+     * For the constraints this is not exact, but we have no other option
+     * without literally changing the lengths and reevaluating the energies at each step.
+     * (try to remedy this post 4.6 - MRS)
      * For the non-bonded LR term we assume that the soft-core (if present)
      * no longer affects the energy beyond the short-range cut-off,
      * which is a very good approximation (except for exotic settings).
+     * (investigate how to overcome this post 4.6 - MRS)
      */
-    for(i=1; i<enerd->n_lambda; i++)
-    {
-        dlam = (ir->flambda[i-1] - lambda);
-        dhdl_lin =
-            enerd->dvdl_lin + enerd->term[F_DKDL] + enerd->term[F_DHDL_CON];
-        if (debug)
+
+    for(i=0; i<fepvals->n_lambda; i++)
+    {                                         /* note we are iterating over fepvals here!
+                                                 For the current lam, dlam = 0 automatically,
+                                                 so we don't need to add anything to the
+                                                 enerd->enerpart_lambda[0] */
+
+        /* we don't need to worry about dvdl contributions to the current lambda, because
+           it's automatically zero */
+
+        /* first kinetic energy term */
+        dlam = (fepvals->all_lambda[efptMASS][i] - lambda[efptMASS]);
+
+        enerd->enerpart_lambda[i+1] += enerd->term[F_DKDL]*dlam;
+
+        for (j=0;j<efptNR;j++)
         {
-            fprintf(debug,"enerdiff lam %g: non-linear %f linear %f*%f\n",
-                    ir->flambda[i-1],
-                    enerd->enerpart_lambda[i] - enerd->enerpart_lambda[0],
-                    dlam,dhdl_lin);
-        }
-        enerd->enerpart_lambda[i] += dlam*dhdl_lin;
+            if (j==efptMASS) {continue;} /* no other mass term to worry about */
 
+            dlam = (fepvals->all_lambda[j][i]-lambda[j]);
+            enerd->enerpart_lambda[i+1] += dlam*enerd->dvdl_lin[j];
+            if (debug)
+            {
+                fprintf(debug,"enerdiff lam %g: (%15s), non-linear %f linear %f*%f\n",
+                        fepvals->all_lambda[j][i],efpt_names[j],
+                        (enerd->enerpart_lambda[i+1] - enerd->enerpart_lambda[0]),
+                        dlam,enerd->dvdl_lin[j]);
+            }
+        }
     }
 }
 
@@ -704,36 +796,43 @@ void reset_enerdata(t_grpopts *opts,
                     gmx_enerdata_t *enerd,
                     gmx_bool bMaster)
 {
-  gmx_bool bKeepLR;
-  int  i,j;
-  
-  /* First reset all energy components, except for the long range terms
-   * on the master at non neighbor search steps, since the long range
-   * terms have already been summed at the last neighbor search step.
-   */
-  bKeepLR = (fr->bTwinRange && !bNS);
-  for(i=0; (i<egNR); i++) {
-    if (!(bKeepLR && bMaster && (i == egCOULLR || i == egLJLR))) {
-      for(j=0; (j<enerd->grpp.nener); j++)
-       enerd->grpp.ener[i][j] = 0.0;
+    gmx_bool bKeepLR;
+    int  i,j;
+
+    /* First reset all energy components, except for the long range terms
+     * on the master at non neighbor search steps, since the long range
+     * terms have already been summed at the last neighbor search step.
+     */
+    bKeepLR = (fr->bTwinRange && !bNS);
+    for(i=0; (i<egNR); i++) {
+        if (!(bKeepLR && bMaster && (i == egCOULLR || i == egLJLR))) {
+            for(j=0; (j<enerd->grpp.nener); j++)
+                enerd->grpp.ener[i][j] = 0.0;
+        }
+    }
+    for (i=0;i<efptNR;i++)
+    {
+        enerd->dvdl_lin[i]    = 0.0;
+        enerd->dvdl_nonlin[i] = 0.0;
     }
-  }
-  enerd->dvdl_lin    = 0.0;
-  enerd->dvdl_nonlin = 0.0;
 
-  /* Normal potential energy components */
-  for(i=0; (i<=F_EPOT); i++) {
-    enerd->term[i] = 0.0;
-  }
-  /* Initialize the dVdlambda term with the long range contribution */
-  enerd->term[F_DVDL]     = 0.0;
-  enerd->term[F_DKDL]     = 0.0;
-  enerd->term[F_DHDL_CON] = 0.0;
-  if (enerd->n_lambda > 0)
-  {
-      for(i=0; i<enerd->n_lambda; i++)
-      {
-          enerd->enerpart_lambda[i] = 0.0;
-      }
-  }
+    /* Normal potential energy components */
+    for(i=0; (i<=F_EPOT); i++) {
+        enerd->term[i] = 0.0;
+    }
+    /* Initialize the dVdlambda term with the long range contribution */
+    /* Initialize the dvdl term with the long range contribution */
+    enerd->term[F_DVDL]            = 0.0;
+    enerd->term[F_DVDL_COUL]       = 0.0;
+    enerd->term[F_DVDL_VDW]        = 0.0;
+    enerd->term[F_DVDL_BONDED]     = 0.0;
+    enerd->term[F_DVDL_RESTRAINT]  = 0.0;
+    enerd->term[F_DKDL]            = 0.0;
+    if (enerd->n_lambda > 0)
+    {
+        for(i=0; i<enerd->n_lambda; i++)
+        {
+            enerd->enerpart_lambda[i] = 0.0;
+        }
+    }
 }
index 975c0547918b9db7e25c2de3f243655efdebe7e6..bf53578cc6f77fdb8edb36fa5844d9df95b17a6a 100644 (file)
@@ -860,7 +860,7 @@ void set_avcsixtwelve(FILE *fplog,t_forcerec *fr,const gmx_mtop_t *mtop)
                                 tpj = atoms->atom[k].typeB;
                             }
                             if (bBHAM) {
-                                csix -= nmol*BHAMC(nbfp,ntp,tpi,tpj);
+                               csix -= nmol*BHAMC(nbfp,ntp,tpi,tpj);
                             } else {
                                 csix    -= nmol*C6 (nbfp,ntp,tpi,tpj);
                                 ctwelve -= nmol*C12(nbfp,ntp,tpi,tpj);
@@ -1384,11 +1384,22 @@ void init_forcerec(FILE *fp,
     fr->fc_stepsize = ir->fc_stepsize;
     
     /* Free energy */
-    fr->efep          = ir->efep;
-    fr->sc_alpha      = ir->sc_alpha;
-    fr->sc_power      = ir->sc_power;
-    fr->sc_sigma6_def = pow(ir->sc_sigma,6);
-    fr->sc_sigma6_min = pow(ir->sc_sigma_min,6);
+    fr->efep       = ir->efep;
+    fr->sc_alphavdw = ir->fepvals->sc_alpha;
+    if (ir->fepvals->bScCoul)
+    {
+        fr->sc_alphacoul = ir->fepvals->sc_alpha;
+        fr->sc_sigma6_min = pow(ir->fepvals->sc_sigma_min,6);
+    }
+    else
+    {
+        fr->sc_alphacoul = 0;
+        fr->sc_sigma6_min = 0; /* only needed when bScCoul is on */
+    }
+    fr->sc_power   = ir->fepvals->sc_power;
+    fr->sc_r_power   = ir->fepvals->sc_r_power;
+    fr->sc_sigma6_def = pow(ir->fepvals->sc_sigma,6);
+
     env = getenv("GMX_SCSIGMA_MIN");
     if (env != NULL)
     {
index 4f19556b8b6f4661d0495cc2da9673e05469d9be..2219580e0e055b48f42b0fc0b2ab177d0996768f 100644 (file)
@@ -1,12 +1,12 @@
 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
  *
- * 
+ *
  *                This source code is part of
- * 
+ *
  *                 G   R   O   M   A   C   S
- * 
+ *
  *          GROningen MAchine for Chemical Simulations
- * 
+ *
  *                        VERSION 3.2.0
  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * If you want to redistribute modifications, please consider that
  * scientific software is very special. Version control is crucial -
  * bugs must be traceable. We will be happy to consider code for
  * inclusion in the official distribution, but derived work must not
  * be called official GROMACS. Details are found in the README & COPYING
  * files - if they are missing, get the official version at www.gromacs.org.
- * 
+ *
  * To help us fund GROMACS development, we humbly ask that you cite
  * the papers on the package - you can find them in the top README file.
- * 
+ *
  * For more info, check our website at http://www.gromacs.org
- * 
+ *
  * And Hey:
  * GROwing Monsters And Cloning Shrimps
  */
 #define NOT_FINISHED(l1,l2) \
   printf("not finished yet: lines %d .. %d in %s\n",l1,l2,__FILE__)
 
+static char *int_title(const char *title,int nodeid,char buf[], int size)
+{
+  sprintf(buf,"%s (%d)",title,nodeid);
+
+  return buf;
+}
+
 void set_state_entries(t_state *state,const t_inputrec *ir,int nnodes)
 {
   int nnhpres;
@@ -69,9 +76,16 @@ void set_state_entries(t_state *state,const t_inputrec *ir,int nnodes)
    * with what is needed, so we correct this here.
    */
   state->flags = 0;
-  if (ir->efep != efepNO)
-    state->flags |= (1<<estLAMBDA);
+  if (ir->efep != efepNO || ir->bExpanded)
+  {
+      state->flags |= (1<<estLAMBDA);
+      state->flags |= (1<<estFEPSTATE);
+  }
   state->flags |= (1<<estX);
+  if (state->lambda==NULL)
+    {
+      snew(state->lambda,efptNR);
+    }
   if (state->x == NULL)
     snew(state->x,state->nalloc);
   if (EI_DYNAMICS(ir->eI)) {
@@ -109,56 +123,69 @@ void set_state_entries(t_state *state,const t_inputrec *ir,int nnodes)
   } else {
     state->nrng = 0;
   }
+
+  if (ir->bExpanded)
+  {
+      state->nmcrng  = gmx_rng_n();
+      snew(state->mc_rng,state->nmcrng);
+      snew(state->mc_rngi,1);
+  }
+
   state->nnhpres = 0;
   if (ir->ePBC != epbcNONE) {
-    state->flags |= (1<<estBOX);
-    if (PRESERVE_SHAPE(*ir)) {
-      state->flags |= (1<<estBOX_REL);
-    }
-    if ((ir->epc == epcPARRINELLORAHMAN) || (ir->epc == epcMTTK)) {
-      state->flags |= (1<<estBOXV);
-    }
-    if (ir->epc != epcNO) {
-      if (IR_NPT_TROTTER(ir)) {
-       state->nnhpres = 1;
-       state->flags |= (1<<estNHPRES_XI);
-       state->flags |= (1<<estNHPRES_VXI);
-       state->flags |= (1<<estSVIR_PREV);
-       state->flags |= (1<<estFVIR_PREV);
-       state->flags |= (1<<estVETA);
-       state->flags |= (1<<estVOL0);
-      } else {
-       state->flags |= (1<<estPRES_PREV);
+      state->flags |= (1<<estBOX);
+      if (PRESERVE_SHAPE(*ir)) {
+          state->flags |= (1<<estBOX_REL);
+      }
+      if ((ir->epc == epcPARRINELLORAHMAN) || (ir->epc == epcMTTK))
+      {
+          state->flags |= (1<<estBOXV);
+      }
+      if (ir->epc != epcNO)
+      {
+          if (IR_NPT_TROTTER(ir) || (IR_NPH_TROTTER(ir)))
+          {
+              state->nnhpres = 1;
+              state->flags |= (1<<estNHPRES_XI);
+              state->flags |= (1<<estNHPRES_VXI);
+              state->flags |= (1<<estSVIR_PREV);
+              state->flags |= (1<<estFVIR_PREV);
+              state->flags |= (1<<estVETA);
+              state->flags |= (1<<estVOL0);
+          }
+          else
+          {
+              state->flags |= (1<<estPRES_PREV);
+          }
       }
-    }
   }
 
   if (ir->etc == etcNOSEHOOVER) {
     state->flags |= (1<<estNH_XI);
     state->flags |= (1<<estNH_VXI);
   }
-  
+
   if (ir->etc == etcVRESCALE) {
     state->flags |= (1<<estTC_INT);
   }
-  
+
   init_gtc_state(state,state->ngtc,state->nnhpres,ir->opts.nhchainlength); /* allocate the space for nose-hoover chains */
   init_ekinstate(&state->ekinstate,ir);
 
   init_energyhistory(&state->enerhist);
+  init_df_history(&state->dfhist,ir->fepvals->n_lambda,ir->expandedvals->init_wl_delta);
 }
 
 
 void init_parallel(FILE *log, t_commrec *cr, t_inputrec *inputrec,
                    gmx_mtop_t *mtop)
 {
-  bcast_ir_mtop(cr,inputrec,mtop);
+    bcast_ir_mtop(cr,inputrec,mtop);
 
-
-  if (inputrec->eI == eiBD || EI_SD(inputrec->eI)) {
-    /* Make sure the random seeds are different on each node */
-    inputrec->ld_seed += cr->nodeid;
-  }
+    if (inputrec->eI == eiBD || EI_SD(inputrec->eI)) {
+        /* Make sure the random seeds are different on each node */
+        inputrec->ld_seed += cr->nodeid;
+    }
 }
 
 
index c50f1036d2b34cd715b3123afa97b2e8d4f7f7d2..4901aaf68c7cb08fca2fb44f0ba41fe5ebcdc20e 100644 (file)
@@ -456,7 +456,7 @@ void compute_globals(FILE *fplog, gmx_global_stat_t gstat, t_commrec *cr, t_inpu
     
     if (bEner || bPres || bConstrain) 
     {
-        calc_dispcorr(fplog,ir,fr,0,top_global->natoms,box,state->lambda,
+        calc_dispcorr(fplog,ir,fr,0,top_global->natoms,box,state->lambda[efptVDW],
                       corr_pres,corr_vir,&prescorr,&enercorr,&dvdlcorr);
     }
     
@@ -464,10 +464,7 @@ void compute_globals(FILE *fplog, gmx_global_stat_t gstat, t_commrec *cr, t_inpu
     {
         enerd->term[F_DISPCORR] = enercorr;
         enerd->term[F_EPOT] += enercorr;
-        enerd->term[F_DVDL] += dvdlcorr;
-        if (fr->efep != efepNO) {
-            enerd->dvdl_lin += dvdlcorr;
-        }
+        enerd->term[F_DVDL_VDW] += dvdlcorr;
     }
     
     /* ########## Now pressure ############## */
@@ -494,7 +491,7 @@ void compute_globals(FILE *fplog, gmx_global_stat_t gstat, t_commrec *cr, t_inpu
         *pcurr = enerd->term[F_PRES];
         /* calculate temperature using virial */
         enerd->term[F_VTEMP] = calc_temp(trace(total_vir),ir->opts.nrdf[0]);
-        
+
     }    
 }
 
@@ -513,6 +510,85 @@ void check_nst_param(FILE *fplog,t_commrec *cr,
     }
 }
 
+void set_current_lambdas(gmx_large_int_t step, t_lambda *fepvals, gmx_bool bRerunMD,
+                         t_trxframe *rerun_fr,t_state *state_global, t_state *state, double lam0[])
+/* find the current lambdas.  If rerunning, we either read in a state, or a lambda value,
+   requiring different logic. */
+{
+    real frac;
+    int i,fep_state=0;
+    if (bRerunMD)
+    {
+        if (rerun_fr->bLambda)
+        {
+            if (fepvals->delta_lambda!=0)
+            {
+                state_global->lambda[efptFEP] = rerun_fr->lambda;
+                for (i=0;i<efptNR;i++)
+                {
+                    if (i!= efptFEP)
+                    {
+                        state->lambda[i] = state_global->lambda[i];
+                    }
+                }
+            }
+            else
+            {
+                /* find out between which two value of lambda we should be */
+                frac = (step*fepvals->delta_lambda);
+                fep_state = floor(frac*fepvals->n_lambda);
+                /* interpolate between this state and the next */
+                /* this assumes that the initial lambda corresponds to lambda==0, which is verified in grompp */
+                frac = (frac*fepvals->n_lambda)-fep_state;
+                for (i=0;i<efptNR;i++)
+                {
+                    state_global->lambda[i] = lam0[i] + (fepvals->all_lambda[i][fep_state]) +
+                        frac*(fepvals->all_lambda[i][fep_state+1]-fepvals->all_lambda[i][fep_state]);
+                }
+            }
+        }
+        else if (rerun_fr->bFepState)
+        {
+            state_global->fep_state = rerun_fr->fep_state;
+            for (i=0;i<efptNR;i++)
+            {
+                state_global->lambda[i] = fepvals->all_lambda[i][fep_state];
+            }
+        }
+    }
+    else
+    {
+        if (fepvals->delta_lambda!=0)
+        {
+            /* find out between which two value of lambda we should be */
+            frac = (step*fepvals->delta_lambda);
+            if (fepvals->n_lambda > 0)
+            {
+                fep_state = floor(frac*fepvals->n_lambda);
+                /* interpolate between this state and the next */
+                /* this assumes that the initial lambda corresponds to lambda==0, which is verified in grompp */
+                frac = (frac*fepvals->n_lambda)-fep_state;
+                for (i=0;i<efptNR;i++)
+                {
+                    state_global->lambda[i] = lam0[i] + (fepvals->all_lambda[i][fep_state]) +
+                        frac*(fepvals->all_lambda[i][fep_state+1]-fepvals->all_lambda[i][fep_state]);
+                }
+            }
+            else
+            {
+                for (i=0;i<efptNR;i++)
+                {
+                    state_global->lambda[i] = lam0[i] + frac;
+                }
+            }
+        }
+    }
+    for (i=0;i<efptNR;i++)
+    {
+        state->lambda[i] = state_global->lambda[i];
+    }
+}
+
 void reset_all_counters(FILE *fplog,t_commrec *cr,
                         gmx_large_int_t step,
                         gmx_large_int_t *step_rel,t_inputrec *ir,
@@ -684,7 +760,7 @@ void check_ir_old_tpx_versions(t_commrec *cr,FILE *fplog,
         if (ir->efep != efepNO)
         {
             check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
-                            "nstdhdl",&ir->nstdhdl);
+                            "nstdhdl",&ir->fepvals->nstdhdl);
         }
     }
 }
index 003dd922dbf0a97445b18a8b25f52877951eace3..bf2a9a37a28176e4f2559bdd47fc159c2f071d01 100644 (file)
@@ -1,12 +1,12 @@
 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
  *
- * 
+ *
  *                This source code is part of
- * 
+ *
  *                 G   R   O   M   A   C   S
- * 
+ *
  *          GROningen MAchine for Chemical Simulations
- * 
+ *
  *                        VERSION 3.2.0
  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * If you want to redistribute modifications, please consider that
  * scientific software is very special. Version control is crucial -
  * bugs must be traceable. We will be happy to consider code for
  * inclusion in the official distribution, but derived work must not
  * be called official GROMACS. Details are found in the README & COPYING
  * files - if they are missing, get the official version at www.gromacs.org.
- * 
+ *
  * To help us fund GROMACS development, we humbly ask that you cite
  * the papers on the package - you can find them in the top README file.
- * 
+ *
  * For more info, check our website at http://www.gromacs.org
- * 
+ *
  * And Hey:
  * GROwing Monsters And Cloning Shrimps
  */
@@ -55,7 +55,7 @@
 #include "mtop_util.h"
 #include "xvgr.h"
 #include "gmxfio.h"
-
+#include "mdrun.h"
 #include "mdebin_bar.h"
 
 
@@ -63,9 +63,9 @@ static const char *conrmsd_nm[] = { "Constr. rmsd", "Constr.2 rmsd" };
 
 static const char *boxs_nm[] = { "Box-X", "Box-Y", "Box-Z" };
 
-static const char *tricl_boxs_nm[] = { 
+static const char *tricl_boxs_nm[] = {
     "Box-XX", "Box-YY", "Box-ZZ",
-    "Box-YX", "Box-ZX", "Box-ZY" 
+    "Box-YX", "Box-ZX", "Box-ZY"
 };
 
 static const char *vol_nm[] = { "Volume" };
@@ -84,7 +84,6 @@ static const char *boxvel_nm[] = {
 #define NBOXS asize(boxs_nm)
 #define NTRICLBOXS asize(tricl_boxs_nm)
 
-
 t_mdebin *init_mdebin(ener_file_t fp_ene,
                       const gmx_mtop_t *mtop,
                       const t_inputrec *ir,
@@ -206,10 +205,13 @@ t_mdebin *init_mdebin(ener_file_t fp_ene,
             md->bEner[i] = b14;
         else if (i == F_LJC14_Q || i == F_LJC_PAIRS_NB)
             md->bEner[i] = FALSE;
-        else if ((i == F_DVDL) || (i == F_DKDL))
+        else if ((i == F_DVDL_COUL && ir->fepvals->separate_dvdl[efptCOUL]) ||
+                 (i == F_DVDL_VDW  && ir->fepvals->separate_dvdl[efptVDW]) ||
+                 (i == F_DVDL_BONDED && ir->fepvals->separate_dvdl[efptBONDED]) ||
+                 (i == F_DVDL_RESTRAINT && ir->fepvals->separate_dvdl[efptRESTRAINT]) ||
+                 (i == F_DKDL && ir->fepvals->separate_dvdl[efptMASS]) ||
+                 (i == F_DVDL && ir->fepvals->separate_dvdl[efptFEP]))
             md->bEner[i] = (ir->efep != efepNO);
-        else if (i == F_DHDL_CON)
-            md->bEner[i] = (ir->efep != efepNO && md->bConstr);
         else if ((interaction_function[i].flags & IF_VSITE) ||
                  (i == F_CONSTR) || (i == F_CONSTRNC) || (i == F_SETTLE))
             md->bEner[i] = FALSE;
@@ -223,7 +225,7 @@ t_mdebin *init_mdebin(ener_file_t fp_ene,
             md->bEner[i] = FALSE;
         else if ((i == F_ETOT) || (i == F_EKIN) || (i == F_TEMP))
             md->bEner[i] = EI_DYNAMICS(ir->eI);
-        else if (i==F_VTEMP) 
+        else if (i==F_VTEMP)
             md->bEner[i] =  (EI_DYNAMICS(ir->eI) && getenv("GMX_VIRIAL_TEMPERATURE"));
         else if (i == F_DISPCORR || i == F_PDISPCORR)
             md->bEner[i] = (ir->eDispCorr != edispcNO);
@@ -281,7 +283,8 @@ t_mdebin *init_mdebin(ener_file_t fp_ene,
     md->bDynBox = DYNAMIC_BOX(*ir);
     md->etc = ir->etc;
     md->bNHC_trotter = IR_NVT_TROTTER(ir);
-    md->bMTTK = IR_NPT_TROTTER(ir);
+    md->bPrintNHChains = ir-> bPrintNHChains;
+    md->bMTTK = (IR_NPT_TROTTER(ir) || IR_NPH_TROTTER(ir));
 
     md->ebin  = mk_ebin();
     /* Pass NULL for unit to let get_ebin_space determine the units
@@ -297,8 +300,8 @@ t_mdebin *init_mdebin(ener_file_t fp_ene,
     }
     if (md->bDynBox)
     {
-        md->ib    = get_ebin_space(md->ebin, 
-                                   md->bTricl ? NTRICLBOXS : NBOXS, 
+        md->ib    = get_ebin_space(md->ebin,
+                                   md->bTricl ? NTRICLBOXS : NBOXS,
                                    md->bTricl ? tricl_boxs_nm : boxs_nm,
                                    unit_length);
         md->ivol  = get_ebin_space(md->ebin, 1, vol_nm,  unit_volume);
@@ -434,22 +437,23 @@ t_mdebin *init_mdebin(ener_file_t fp_ene,
     }
 
     md->nTC=groups->grps[egcTC].nr;
-    md->nNHC = ir->opts.nhchainlength; /* shorthand for number of NH chains */ 
+    md->nNHC = ir->opts.nhchainlength; /* shorthand for number of NH chains */
     if (md->bMTTK)
     {
-        md->nTCP = 1;  /* assume only one possible coupling system for barostat 
+        md->nTCP = 1;  /* assume only one possible coupling system for barostat
                           for now */
-    } 
-    else 
+    }
+    else
     {
         md->nTCP = 0;
     }
-
-    if (md->etc == etcNOSEHOOVER) {
-        if (md->bNHC_trotter) { 
+    if (md->etc == etcNOSEHOOVER)
+    {
+        if (md->bNHC_trotter)
+        {
             md->mde_n = 2*md->nNHC*md->nTC;
         }
-        else 
+        else
         {
             md->mde_n = 2*md->nTC;
         }
@@ -457,7 +461,7 @@ t_mdebin *init_mdebin(ener_file_t fp_ene,
         {
             md->mdeb_n = 2*md->nNHC*md->nTCP;
         }
-    } else { 
+    } else {
         md->mde_n = md->nTC;
         md->mdeb_n = 0;
     }
@@ -476,19 +480,17 @@ t_mdebin *init_mdebin(ener_file_t fp_ene,
     md->itemp=get_ebin_space(md->ebin,md->nTC,(const char **)grpnms,
                              unit_temp_K);
 
-    bNoseHoover = (getenv("GMX_NOSEHOOVER_CHAINS") != NULL); /* whether to print Nose-Hoover chains */
-
     if (md->etc == etcNOSEHOOVER)
     {
-        if (bNoseHoover) 
+        if (md->bPrintNHChains)
         {
-            if (md->bNHC_trotter) 
+            if (md->bNHC_trotter)
             {
-                for(i=0; (i<md->nTC); i++) 
+                for(i=0; (i<md->nTC); i++)
                 {
                     ni=groups->grps[egcTC].nm_ind[i];
                     bufi = *(groups->grpname[ni]);
-                    for(j=0; (j<md->nNHC); j++) 
+                    for(j=0; (j<md->nNHC); j++)
                     {
                         sprintf(buf,"Xi-%d-%s",j,bufi);
                         grpnms[2*(i*md->nNHC+j)]=strdup(buf);
@@ -498,12 +500,12 @@ t_mdebin *init_mdebin(ener_file_t fp_ene,
                 }
                 md->itc=get_ebin_space(md->ebin,md->mde_n,
                                        (const char **)grpnms,unit_invtime);
-                if (md->bMTTK) 
+                if (md->bMTTK)
                 {
-                    for(i=0; (i<md->nTCP); i++) 
+                    for(i=0; (i<md->nTCP); i++)
                     {
                         bufi = baro_nm[0];  /* All barostat DOF's together for now. */
-                        for(j=0; (j<md->nNHC); j++) 
+                        for(j=0; (j<md->nNHC); j++)
                         {
                             sprintf(buf,"Xi-%d-%s",j,bufi);
                             grpnms[2*(i*md->nNHC+j)]=strdup(buf);
@@ -514,10 +516,10 @@ t_mdebin *init_mdebin(ener_file_t fp_ene,
                     md->itcb=get_ebin_space(md->ebin,md->mdeb_n,
                                             (const char **)grpnms,unit_invtime);
                 }
-            } 
+            }
             else
             {
-                for(i=0; (i<md->nTC); i++) 
+                for(i=0; (i<md->nTC); i++)
                 {
                     ni=groups->grps[egcTC].nm_ind[i];
                     bufi = *(groups->grpname[ni]);
@@ -531,7 +533,7 @@ t_mdebin *init_mdebin(ener_file_t fp_ene,
             }
         }
     }
-    else if (md->etc == etcBERENDSEN || md->etc == etcYES || 
+    else if (md->etc == etcBERENDSEN || md->etc == etcYES ||
              md->etc == etcVRESCALE)
     {
         for(i=0; (i<md->nTC); i++)
@@ -572,10 +574,9 @@ t_mdebin *init_mdebin(ener_file_t fp_ene,
     md->print_grpnms=NULL;
 
     /* check whether we're going to write dh histograms */
-    md->dhc=NULL; 
-    if (ir->separate_dhdl_file == sepdhdlfileNO )
+    md->dhc=NULL;
+    if (ir->fepvals->separate_dhdl_file == esepdhdlfileNO )
     {
-        int i;
         snew(md->dhc, 1);
 
         mde_delta_h_coll_init(md->dhc, ir);
@@ -585,67 +586,173 @@ t_mdebin *init_mdebin(ener_file_t fp_ene,
     {
         md->fp_dhdl = fp_dhdl;
     }
-    md->dhdl_derivatives = (ir->dhdl_derivatives==dhdlderivativesYES);
+    if (ir->bSimTemp) {
+        int i;
+        snew(md->temperatures,ir->fepvals->n_lambda);
+        for (i=0;i<ir->fepvals->n_lambda;i++)
+        {
+            md->temperatures[i] = ir->simtempvals->temperatures[i];
+        }
+    }
     return md;
 }
 
-FILE *open_dhdl(const char *filename,const t_inputrec *ir,
-                const output_env_t oenv)
+extern FILE *open_dhdl(const char *filename,const t_inputrec *ir,
+                       const output_env_t oenv)
 {
     FILE *fp;
-    const char *dhdl="dH/d\\lambda",*deltag="\\DeltaH",*lambda="\\lambda";
+    const char *dhdl="dH/d\\lambda",*deltag="\\DeltaH",*lambda="\\lambda",
+        *lambdastate="\\lambda state",*remain="remaining";
     char title[STRLEN],label_x[STRLEN],label_y[STRLEN];
+    int  i,np,nps,nsets,nsets_de,nsetsbegin;
+    t_lambda *fep;
     char **setname;
     char buf[STRLEN];
+    int bufplace=0;
+
+    int nsets_dhdl = 0;
+    int s = 0;
+    int nsetsextend;
+
+    /* for simplicity */
+    fep = ir->fepvals;
 
-    sprintf(label_x,"%s (%s)","Time",unit_time);
-    if (ir->n_flambda == 0)
+    if (fep->n_lambda == 0)
     {
         sprintf(title,"%s",dhdl);
+        sprintf(label_x,"Time (ps)");
         sprintf(label_y,"%s (%s %s)",
                 dhdl,unit_energy,"[\\lambda]\\S-1\\N");
     }
     else
     {
-        sprintf(title,"%s, %s",dhdl,deltag);
-        sprintf(label_y,"(%s)",unit_energy);
+        sprintf(title,"%s and %s",dhdl,deltag);
+        sprintf(label_x,"Time (ps)");
+        sprintf(label_y,"%s and %s (%s %s)",
+                dhdl,deltag,unit_energy,"[\\8l\\4]\\S-1\\N");
     }
     fp = gmx_fio_fopen(filename,"w+");
     xvgr_header(fp,title,label_x,label_y,exvggtXNY,oenv);
 
-    if (ir->delta_lambda == 0)
+    if (!(ir->bSimTemp))
     {
-        sprintf(buf,"T = %g (K), %s = %g",
-                ir->opts.ref_t[0],lambda,ir->init_lambda);
+        bufplace = sprintf(buf,"T = %g (K) ",
+                ir->opts.ref_t[0]);
     }
-    else
+    if (ir->efep != efepSLOWGROWTH)
     {
-        sprintf(buf,"T = %g (K)",
-                ir->opts.ref_t[0]);
+        if (fep->n_lambda == 0)
+        {
+            sprintf(&(buf[bufplace]),"%s = %g",
+                    lambda,fep->init_lambda);
+        }
+        else
+        {
+            sprintf(&(buf[bufplace]),"%s = %d",
+                    lambdastate,fep->init_fep_state);
+        }
     }
     xvgr_subtitle(fp,buf,oenv);
 
-    if (ir->n_flambda > 0)
+    for (i=0;i<efptNR;i++)
+    {
+        if (fep->separate_dvdl[i]) {nsets_dhdl++;}
+    }
+
+    /* count the number of delta_g states */
+    nsets_de = fep->n_lambda;
+
+    nsets = nsets_dhdl + nsets_de; /* dhdl + fep differences */
+
+    if (fep->n_lambda>0 && ir->bExpanded)
+    {
+        nsets += 1;   /*add fep state for expanded ensemble */
+    }
+
+    if (fep->bPrintEnergy)
+    {
+        nsets += 1;  /* add energy to the dhdl as well */
+    }
+
+    nsetsextend = nsets;
+    if ((ir->epc!=epcNO) && (fep->n_lambda>0))
+    {
+        nsetsextend += 1; /* for PV term, other terms possible if required for the reduced potential (only needed with foreign lambda) */
+    }
+    snew(setname,nsetsextend);
+
+    if (ir->bExpanded)
+    {
+        /* state for the fep_vals, if we have alchemical sampling */
+        sprintf(buf,"%s","Thermodynamic state");
+        setname[s] = strdup(buf);
+        s+=1;
+    }
+
+    if (fep->bPrintEnergy)
+    {
+        sprintf(buf,"%s (%s)","Energy",unit_energy);
+        setname[s] = strdup(buf);
+        s+=1;
+    }
+
+    for (i=0;i<efptNR;i++)
+    {
+        if (fep->separate_dvdl[i]) {
+            sprintf(buf,"%s (%s)",dhdl,efpt_names[i]);
+            setname[s] = strdup(buf);
+            s+=1;
+        }
+    }
+
+    if (fep->n_lambda > 0)
     {
-        int nsets,s,nsi=0;
         /* g_bar has to determine the lambda values used in this simulation
-         * from this xvg legend.  */
-        nsets = ( (ir->dhdl_derivatives==dhdlderivativesYES) ? 1 : 0) + 
-                  ir->n_flambda;
-        snew(setname,nsets);
-        if (ir->dhdl_derivatives == dhdlderivativesYES)
+         * from this xvg legend.
+         */
+
+        if (ir->bExpanded) {
+            nsetsbegin = 1;  /* for including the expanded ensemble */
+        } else {
+            nsetsbegin = 0;
+        }
+
+        if (fep->bPrintEnergy)
         {
-            sprintf(buf,"%s %s %g",dhdl,lambda,ir->init_lambda);
-            setname[nsi++] = gmx_strdup(buf);
+            nsetsbegin += 1;
         }
-        for(s=0; s<ir->n_flambda; s++)
+        nsetsbegin += nsets_dhdl;
+
+        for(s=nsetsbegin; s<nsets; s++)
         {
-            sprintf(buf,"%s %s %g",deltag,lambda,ir->flambda[s]);
-            setname[nsi++] = gmx_strdup(buf);
+            nps = sprintf(buf,"%s %s (",deltag,lambda);
+            for (i=0;i<efptNR;i++)
+            {
+                if (fep->separate_dvdl[i])
+                {
+                    np = sprintf(&buf[nps],"%g,",fep->all_lambda[i][s-(nsetsbegin)]);
+                    nps += np;
+                }
+            }
+            if (ir->bSimTemp)
+            {
+                /* print the temperature for this state if doing simulated annealing */
+                sprintf(&buf[nps],"T = %g (%s))",ir->simtempvals->temperatures[s-(nsetsbegin)],unit_temp_K);
+            }
+            else
+            {
+                sprintf(&buf[nps-1],")");  /* -1 to overwrite the last comma */
+            }
+            setname[s] = strdup(buf);
+        }
+        if (ir->epc!=epcNO) {
+            np = sprintf(buf,"pV (%s)",unit_energy);
+            setname[nsetsextend-1] = strdup(buf);  /* the first entry after nsets */
         }
-        xvgr_legend(fp,nsets,(const char**)setname,oenv);
 
-        for(s=0; s<nsets; s++)
+        xvgr_legend(fp,nsetsextend,(const char **)setname,oenv);
+
+        for(s=0; s<nsetsextend; s++)
         {
             sfree(setname[s]);
         }
@@ -662,16 +769,19 @@ static void copy_energy(t_mdebin *md, real e[],real ecpy[])
     for(i=j=0; (i<F_NRE); i++)
         if (md->bEner[i])
             ecpy[j++] = e[i];
-    if (j != md->f_nre) 
+    if (j != md->f_nre)
         gmx_incons("Number of energy terms wrong");
 }
 
-void upd_mdebin(t_mdebin *md, gmx_bool write_dhdl,
+void upd_mdebin(t_mdebin *md,
+                gmx_bool bDoDHDL,
                 gmx_bool bSum,
                 double time,
                 real tmass,
                 gmx_enerdata_t *enerd,
                 t_state *state,
+                t_lambda *fep,
+                t_expanded *expand,
                 matrix  box,
                 tensor svir,
                 tensor fvir,
@@ -686,8 +796,10 @@ void upd_mdebin(t_mdebin *md, gmx_bool write_dhdl,
     real   bs[NTRICLBOXS],vol,dens,pv,enthalpy;
     real   eee[egNR];
     real   ecopy[F_NRE];
+    double store_dhdl[efptNR];
+    double *dE=NULL;
+    real   store_energy=0;
     real   tmp;
-    gmx_bool   bNoseHoover;
 
     /* Do NOT use the box in the state variable, but the separate box provided
      * as an argument. This is because we sometimes need to write the box from
@@ -726,7 +838,6 @@ void upd_mdebin(t_mdebin *md, gmx_bool write_dhdl,
         }
         vol  = box[XX][XX]*box[YY][YY]*box[ZZ][ZZ];
         dens = (tmass*AMU)/(vol*NANO*NANO*NANO);
-
         add_ebin(md->ebin,md->ib   ,nboxs,bs   ,bSum);
         add_ebin(md->ebin,md->ivol ,1    ,&vol ,bSum);
         add_ebin(md->ebin,md->idens,1    ,&dens,bSum);
@@ -734,7 +845,7 @@ void upd_mdebin(t_mdebin *md, gmx_bool write_dhdl,
         if (md->bDiagPres)
         {
             /* This is pV (in kJ/mol).  The pressure is the reference pressure,
-               not the instantaneous pressure */  
+               not the instantaneous pressure */
             pv = vol*md->ref_p/PRESFAC;
 
             add_ebin(md->ebin,md->ipv  ,1    ,&pv  ,bSum);
@@ -775,7 +886,7 @@ void upd_mdebin(t_mdebin *md, gmx_bool write_dhdl,
         /* 1/viscosity, unit 1/(kg m^-1 s^-1) */
         tmp = 1/(ekind->cosacc.cos_accel/(ekind->cosacc.vcos*PICO)
                  *dens*vol*sqr(box[ZZ][ZZ]*NANO/(2*M_PI)));
-        add_ebin(md->ebin,md->ivisc,1,&tmp,bSum);    
+        add_ebin(md->ebin,md->ivisc,1,&tmp,bSum);
     }
     if (md->nE > 1)
     {
@@ -806,41 +917,38 @@ void upd_mdebin(t_mdebin *md, gmx_bool write_dhdl,
         }
         add_ebin(md->ebin,md->itemp,md->nTC,md->tmp_r,bSum);
 
-        /* whether to print Nose-Hoover chains: */
-        bNoseHoover = (getenv("GMX_NOSEHOOVER_CHAINS") != NULL); 
-
         if (md->etc == etcNOSEHOOVER)
         {
-            if (bNoseHoover) 
+            /* whether to print Nose-Hoover chains: */
+            if (md->bPrintNHChains)
             {
                 if (md->bNHC_trotter)
                 {
-                    for(i=0; (i<md->nTC); i++) 
+                    for(i=0; (i<md->nTC); i++)
                     {
-                        for (j=0;j<md->nNHC;j++) 
+                        for (j=0;j<md->nNHC;j++)
                         {
                             k = i*md->nNHC+j;
                             md->tmp_r[2*k] = state->nosehoover_xi[k];
                             md->tmp_r[2*k+1] = state->nosehoover_vxi[k];
                         }
                     }
-                    add_ebin(md->ebin,md->itc,md->mde_n,md->tmp_r,bSum);      
+                    add_ebin(md->ebin,md->itc,md->mde_n,md->tmp_r,bSum);
 
                     if (md->bMTTK) {
-                        for(i=0; (i<md->nTCP); i++) 
+                        for(i=0; (i<md->nTCP); i++)
                         {
-                            for (j=0;j<md->nNHC;j++) 
+                            for (j=0;j<md->nNHC;j++)
                             {
                                 k = i*md->nNHC+j;
                                 md->tmp_r[2*k] = state->nhpres_xi[k];
                                 md->tmp_r[2*k+1] = state->nhpres_vxi[k];
                             }
                         }
-                        add_ebin(md->ebin,md->itcb,md->mdeb_n,md->tmp_r,bSum);      
+                        add_ebin(md->ebin,md->itcb,md->mdeb_n,md->tmp_r,bSum);
                     }
-
-                } 
-                else 
+                }
+                else
                 {
                     for(i=0; (i<md->nTC); i++)
                     {
@@ -851,7 +959,7 @@ void upd_mdebin(t_mdebin *md, gmx_bool write_dhdl,
                 }
             }
         }
-        else if (md->etc == etcBERENDSEN || md->etc == etcYES || 
+        else if (md->etc == etcBERENDSEN || md->etc == etcYES ||
                  md->etc == etcVRESCALE)
         {
             for(i=0; (i<md->nTC); i++)
@@ -874,40 +982,90 @@ void upd_mdebin(t_mdebin *md, gmx_bool write_dhdl,
     ebin_increase_count(md->ebin,bSum);
 
     /* BAR + thermodynamic integration values */
-    if (write_dhdl)
+    if ((md->fp_dhdl || md->dhc) && bDoDHDL && (enerd->n_lambda > 0))
     {
-        if (md->fp_dhdl)
-        {
-            fprintf(md->fp_dhdl,"%.4f", time);
-
-            if (md->dhdl_derivatives)
+        snew(dE,enerd->n_lambda-1);
+        for(i=0; i<enerd->n_lambda-1; i++) {
+            dE[i] = enerd->enerpart_lambda[i+1]-enerd->enerpart_lambda[0];  /* zero for simulated tempering */
+            if (md->temperatures!=NULL)
             {
-                fprintf(md->fp_dhdl," %g", enerd->term[F_DVDL]+ 
-                                           enerd->term[F_DKDL]+
-                                           enerd->term[F_DHDL_CON]);
+                /* MRS: is this right, given the way we have defined the exchange probabilities? */
+                /* is this even useful to have at all? */
+                dE[i] += (md->temperatures[i]/md->temperatures[state->fep_state]-1.0)*enerd->term[F_EKIN];
             }
-            for(i=1; i<enerd->n_lambda; i++)
+        }
+    }
+
+    if (md->fp_dhdl && bDoDHDL)
+    {
+        fprintf(md->fp_dhdl,"%.4f",time);
+        /* the current free energy state */
+
+        /* print the current state if we are doing expanded ensemble */
+        if (expand->elmcmove > elmcmoveNO) {
+            fprintf(md->fp_dhdl," %4d",state->fep_state);
+        }
+        /* total energy (for if the temperature changes */
+        if (fep->bPrintEnergy)
+        {
+            store_energy = enerd->term[F_ETOT];
+            fprintf(md->fp_dhdl," %#.8g",store_energy);
+        }
+
+        for (i=0;i<efptNR;i++)
+        {
+            if (fep->separate_dvdl[i])
             {
-                fprintf(md->fp_dhdl," %g",
-                        enerd->enerpart_lambda[i]-enerd->enerpart_lambda[0]);
+                fprintf(md->fp_dhdl," %#.8g",enerd->term[F_DVDL+i]); /* assumes F_DVDL is first */
             }
-            fprintf(md->fp_dhdl,"\n");
         }
-        /* and the binary BAR output */
-        if (md->dhc)
+        for(i=1; i<enerd->n_lambda; i++)
+        {
+            fprintf(md->fp_dhdl," %#.8g",dE[i-1]);
+
+        }
+        if ((md->epc!=epcNO)  && (enerd->n_lambda > 0))
         {
-            mde_delta_h_coll_add_dh(md->dhc, 
-                                    enerd->term[F_DVDL]+ enerd->term[F_DKDL]+
-                                    enerd->term[F_DHDL_CON],
-                                    enerd->enerpart_lambda, time, 
-                                    state->lambda);
+            fprintf(md->fp_dhdl," %#.8g",pv);   /* PV term only needed when there are alternate state lambda */
         }
+        fprintf(md->fp_dhdl,"\n");
+        /* and the binary free energy output */
+    }
+    if (md->dhc && bDoDHDL)
+    {
+        int idhdl = 0;
+        for (i=0;i<efptNR;i++)
+        {
+            if (fep->separate_dvdl[i])
+            {
+                store_dhdl[idhdl] = enerd->term[F_DVDL+i]; /* assumes F_DVDL is first */
+                idhdl+=1;
+            }
+        }
+        /* store_dh is dE */
+        mde_delta_h_coll_add_dh(md->dhc,
+                                (double)state->fep_state,
+                                store_energy,
+                                pv,
+                                (expand->elamstats>elamstatsNO),
+                                (fep->bPrintEnergy),
+                                (md->epc!=epcNO),
+                                idhdl,
+                                fep->n_lambda,
+                                store_dhdl,
+                                dE,
+                                time);
+    }
+    if ((md->fp_dhdl || md->dhc) && bDoDHDL && (enerd->n_lambda >0))
+    {
+        sfree(dE);
     }
 }
 
+
 void upd_mdebin_step(t_mdebin *md)
 {
-    ebin_increase_count(md->ebin,FALSE); 
+    ebin_increase_count(md->ebin,FALSE);
 }
 
 static void npr(FILE *log,int n,char c)
@@ -936,13 +1094,13 @@ static void pprint(FILE *log,const char *s,t_mdebin *md)
     fprintf(log,"\n");
 }
 
-void print_ebin_header(FILE *log,gmx_large_int_t steps,double time,real lamb)
+void print_ebin_header(FILE *log,gmx_large_int_t steps,double time,real lambda)
 {
     char buf[22];
 
     fprintf(log,"   %12s   %12s   %12s\n"
             "   %12s   %12.5f   %12.5f\n\n",
-            "Step","Time","Lambda",gmx_step_str(steps,buf),time,lamb);
+            "Step","Time","Lambda",gmx_step_str(steps,buf),time,lambda);
 }
 
 void print_ebin(ener_file_t fp_ene,gmx_bool bEne,gmx_bool bDR,gmx_bool bOR,
@@ -965,7 +1123,7 @@ void print_ebin(ener_file_t fp_ene,gmx_bool bEne,gmx_bool bDR,gmx_bool bOR,
     real        *block[enxNR];
 
     /* temporary arrays for the lambda values to write out */
-    double      enxlambda_data[2]; 
+    double      enxlambda_data[2];
 
     t_enxframe  fr;
 
@@ -994,14 +1152,14 @@ void print_ebin(ener_file_t fp_ene,gmx_bool bEne,gmx_bool bDR,gmx_bool bOR,
                 nr[enxOR]     = fcd->orires.nr;
                 block[enxOR]  = fcd->orires.otav;
                 id[enxOR]     = enxOR;
-                nr[enxORI]    = (fcd->orires.oinsl != fcd->orires.otav) ? 
+                nr[enxORI]    = (fcd->orires.oinsl != fcd->orires.otav) ?
                           fcd->orires.nr : 0;
                 block[enxORI] = fcd->orires.oinsl;
                 id[enxORI]    = enxORI;
                 nr[enxORT]    = fcd->orires.nex*12;
                 block[enxORT] = fcd->orires.eig;
                 id[enxORT]    = enxORT;
-            }        
+            }
 
             /* whether we are going to wrte anything out: */
             if (fr.nre || ndisre || nr[enxOR] || nr[enxORI])
@@ -1020,7 +1178,7 @@ void print_ebin(ener_file_t fp_ene,gmx_bool bEne,gmx_bool bDR,gmx_bool bOR,
                 for(b=0;b<fr.nblock;b++)
                 {
                     add_subblocks_enxblock(&(fr.block[b]), 1);
-                    fr.block[b].id=id[b]; 
+                    fr.block[b].id=id[b];
                     fr.block[b].sub[0].nr = nr[b];
 #ifndef GMX_DOUBLE
                     fr.block[b].sub[0].type = xdr_datatype_float;
@@ -1062,6 +1220,12 @@ void print_ebin(ener_file_t fp_ene,gmx_bool bEne,gmx_bool bDR,gmx_bool bOR,
                     mde_delta_h_coll_handle_block(md->dhc, &fr, fr.nblock);
                 }
 
+                /* we can now free & reset the data in the blocks */
+                if (md->dhc)
+                {
+                    mde_delta_h_coll_reset(md->dhc);
+                }
+
                 /* do the actual I/O */
                 do_enx(fp_ene,&fr);
                 gmx_fio_check_file_position(enx_file_pointer(fp_ene));
@@ -1070,10 +1234,6 @@ void print_ebin(ener_file_t fp_ene,gmx_bool bEne,gmx_bool bDR,gmx_bool bOR,
                     /* We have stored the sums, so reset the sum history */
                     reset_ebin_sums(md->ebin);
                 }
-
-                /* we can now free & reset the data in the blocks */
-                if (md->dhc)
-                    mde_delta_h_coll_reset(md->dhc);
             }
             free_enxframe(&fr);
             break;
@@ -1109,7 +1269,7 @@ void print_ebin(ener_file_t fp_ene,gmx_bool bEne,gmx_bool bDR,gmx_bool bOR,
             print_orires_log(log,&(fcd->orires));
         }
         fprintf(log,"   Energies (%s)\n",unit_energy);
-        pr_ebin(log,md->ebin,md->ie,md->f_nre+md->nCrmsd,5,mode,TRUE);  
+        pr_ebin(log,md->ebin,md->ie,md->f_nre+md->nCrmsd,5,mode,TRUE);
         fprintf(log,"\n");
 
         if (!bCompact)
@@ -1117,26 +1277,26 @@ void print_ebin(ener_file_t fp_ene,gmx_bool bEne,gmx_bool bDR,gmx_bool bOR,
             if (md->bDynBox)
             {
                 pr_ebin(log,md->ebin,md->ib, md->bTricl ? NTRICLBOXS : NBOXS,5,
-                        mode,TRUE);      
+                        mode,TRUE);
                 fprintf(log,"\n");
             }
             if (md->bConstrVir)
             {
                 fprintf(log,"   Constraint Virial (%s)\n",unit_energy);
-                pr_ebin(log,md->ebin,md->isvir,9,3,mode,FALSE);  
+                pr_ebin(log,md->ebin,md->isvir,9,3,mode,FALSE);
                 fprintf(log,"\n");
                 fprintf(log,"   Force Virial (%s)\n",unit_energy);
-                pr_ebin(log,md->ebin,md->ifvir,9,3,mode,FALSE);  
+                pr_ebin(log,md->ebin,md->ifvir,9,3,mode,FALSE);
                 fprintf(log,"\n");
             }
             fprintf(log,"   Total Virial (%s)\n",unit_energy);
-            pr_ebin(log,md->ebin,md->ivir,9,3,mode,FALSE);   
+            pr_ebin(log,md->ebin,md->ivir,9,3,mode,FALSE);
             fprintf(log,"\n");
             fprintf(log,"   Pressure (%s)\n",unit_pres_bar);
-            pr_ebin(log,md->ebin,md->ipres,9,3,mode,FALSE);  
+            pr_ebin(log,md->ebin,md->ipres,9,3,mode,FALSE);
             fprintf(log,"\n");
             fprintf(log,"   Total Dipole (%s)\n",unit_dipole_D);
-            pr_ebin(log,md->ebin,md->imu,3,3,mode,FALSE);    
+            pr_ebin(log,md->ebin,md->imu,3,3,mode,FALSE);
             fprintf(log,"\n");
 
             if (md->nE > 1)
@@ -1269,7 +1429,7 @@ void restore_energyhistory_from_state(t_mdebin * mdebin,
                   (enerhist->nsum_sim > 0 ? enerhist->ener_sum_sim[i] : 0);
     }
     if (mdebin->dhc)
-    {         
+    {
         mde_delta_h_coll_restore_energyhistory(mdebin->dhc, enerhist);
     }
 }
index 4c44d80571c8fcc9957efcb74af352ad11b7b3bb..f496f68b30e41d9d32a645beb5fed8c286ac4051 100644 (file)
@@ -1,12 +1,12 @@
 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
  *
- * 
+ *
  *                This source code is part of
- * 
+ *
  *                 G   R   O   M   A   C   S
- * 
+ *
  *          GROningen MAchine for Chemical Simulations
- * 
+ *
  *                        VERSION 3.2.0
  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * If you want to redistribute modifications, please consider that
  * scientific software is very special. Version control is crucial -
  * bugs must be traceable. We will be happy to consider code for
  * inclusion in the official distribution, but derived work must not
  * be called official GROMACS. Details are found in the README & COPYING
  * files - if they are missing, get the official version at www.gromacs.org.
- * 
+ *
  * To help us fund GROMACS development, we humbly ask that you cite
  * the papers on the package - you can find them in the top README file.
- * 
+ *
  * For more info, check our website at http://www.gromacs.org
- * 
+ *
  * And Hey:
  * GROwing Monsters And Cloning Shrimps
  */
@@ -57,15 +57,11 @@ static void mde_delta_h_reset(t_mde_delta_h *dh)
 }
 
 /* initialize the delta_h list */
-static void mde_delta_h_init(t_mde_delta_h *dh, int nbins, 
-                             double dx, unsigned int  ndhmax, 
-                             gmx_bool derivative, double foreign_lambda)
+static void mde_delta_h_init(t_mde_delta_h *dh, int nbins,
+                             double dx, unsigned int  ndhmax)
 {
     int i;
 
-    dh->derivative=derivative;
-    dh->lambda=foreign_lambda;
-
     dh->ndhmax=ndhmax+2;
     for(i=0;i<2;i++)
     {
@@ -73,6 +69,8 @@ static void mde_delta_h_init(t_mde_delta_h *dh, int nbins,
     }
 
     snew(dh->dh, dh->ndhmax);
+    snew(dh->dhf,dh->ndhmax);
+
     if ( nbins <= 0 || dx<GMX_REAL_EPS*10 )
     {
         dh->nhist=0;
@@ -81,10 +79,7 @@ static void mde_delta_h_init(t_mde_delta_h *dh, int nbins,
     {
         int i;
         /* pre-allocate the histogram */
-        if (derivative)
-            dh->nhist=2;
-        else
-            dh->nhist=1;
+        dh->nhist=2; /* energies and derivatives histogram */
         dh->dx=dx;
         dh->nbins=nbins;
         for(i=0;i<dh->nhist;i++)
@@ -108,7 +103,7 @@ static void mde_delta_h_add_dh(t_mde_delta_h *dh, double delta_h, double time)
 
 /* construct histogram with index hi */
 static void mde_delta_h_make_hist(t_mde_delta_h *dh, int hi, gmx_bool invert)
-{ 
+{
     double min_dh = FLT_MAX;
     double max_dh = -FLT_MAX;
     unsigned int i;
@@ -117,7 +112,7 @@ static void mde_delta_h_make_hist(t_mde_delta_h *dh, int hi, gmx_bool invert)
     double dx=dh->dx;
     double f; /* energy mult. factor */
 
-    /* by applying a -1 scaling factor on the energies we get the same as 
+    /* by applying a -1 scaling factor on the energies we get the same as
        having a negative dx, but we don't need to fix the min/max values
        beyond inverting x0 */
     f=invert ? -1 : 1;
@@ -130,7 +125,7 @@ static void mde_delta_h_make_hist(t_mde_delta_h *dh, int hi, gmx_bool invert)
         if (f*dh->dh[i] > max_dh)
             max_dh=f*dh->dh[i];
     }
-    
+
     /* reset the histogram */
     for(i=0;i<dh->nbins;i++)
     {
@@ -138,11 +133,12 @@ static void mde_delta_h_make_hist(t_mde_delta_h *dh, int hi, gmx_bool invert)
     }
     dh->maxbin[hi]=0;
 
-    /* The starting point of the histogram is the lowest value found: 
-       that value has the highest contribution to the free energy. 
+    /* The starting point of the histogram is the lowest value found:
+       that value has the highest contribution to the free energy.
 
-       Get this start value in number of histogram dxs from zero, 
+       Get this start value in number of histogram dxs from zero,
        as an integer.*/
+
     dh->x0[hi] = (gmx_large_int_t)floor(min_dh/dx);
 
     min_dh_hist=(dh->x0[hi])*dx;
@@ -153,9 +149,9 @@ static void mde_delta_h_make_hist(t_mde_delta_h *dh, int hi, gmx_bool invert)
     {
         unsigned int bin;
 
-        /* Determine the bin number. If it doesn't fit into the histogram, 
-           add it to the last bin. 
-           We check the max_dh_int range because converting to integers 
+        /* Determine the bin number. If it doesn't fit into the histogram,
+           add it to the last bin.
+           We check the max_dh_int range because converting to integers
            might lead to overflow with unpredictable results.*/
         if ( (f*dh->dh[i] >= min_dh_hist) && (f*dh->dh[i] <= max_dh_hist ) )
         {
@@ -163,10 +159,10 @@ static void mde_delta_h_make_hist(t_mde_delta_h *dh, int hi, gmx_bool invert)
         }
         else
         {
-            bin = dh->nbins-1; 
+            bin = dh->nbins-1;
         }
         /* double-check here because of possible round-off errors*/
-        if (bin >= dh->nbins) 
+        if (bin >= dh->nbins)
         {
             bin = dh->nbins-1;
         }
@@ -178,7 +174,7 @@ static void mde_delta_h_make_hist(t_mde_delta_h *dh, int hi, gmx_bool invert)
         dh->bin[hi][bin]++;
     }
 
-    /* make sure we include a bin with 0 if we didn't use the full 
+    /* make sure we include a bin with 0 if we didn't use the full
        histogram width. This can then be used as an indication that
        all the data was binned. */
     if (dh->maxbin[hi] < dh->nbins-1)
@@ -191,8 +187,10 @@ void mde_delta_h_handle_block(t_mde_delta_h *dh, t_enxblock *blk)
     /* first check which type we should use: histogram or raw data */
     if (dh->nhist == 0)
     {
+        unsigned int i;
+
         /* We write raw data.
-           Raw data consists of 3 subblocks: a block with the 
+           Raw data consists of 3 subblocks: a block with the
            the foreign lambda, and the data itself */
         add_subblocks_enxblock(blk, 3);
 
@@ -212,12 +210,19 @@ void mde_delta_h_handle_block(t_mde_delta_h *dh, t_enxblock *blk)
 
         /* subblock 3 */
         /* check if there's actual data to be written. */
-        if (dh->ndh > 1)
+        /*if (dh->ndh > 1)*/
+        if (dh->ndh > 0)
         {
             blk->sub[2].nr=dh->ndh;
+/* For F@H for now. */
+#undef GMX_DOUBLE
 #ifndef GMX_DOUBLE
             blk->sub[2].type=xdr_datatype_float;
-            blk->sub[2].fval=dh->dh;
+            for(i=0;i<dh->ndh;i++)
+            {
+                dh->dhf[i] = (float)dh->dh[i];
+            }
+            blk->sub[2].fval=dh->dhf;
 #else
             blk->sub[2].type=xdr_datatype_double;
             blk->sub[2].dval=dh->dh;
@@ -229,6 +234,7 @@ void mde_delta_h_handle_block(t_mde_delta_h *dh, t_enxblock *blk)
             blk->sub[2].nr=0;
 #ifndef GMX_DOUBLE
             blk->sub[2].type=xdr_datatype_float;
+            blk->sub[2].fval=NULL;
 #else
             blk->sub[2].type=xdr_datatype_double;
 #endif
@@ -249,7 +255,7 @@ void mde_delta_h_handle_block(t_mde_delta_h *dh, t_enxblock *blk)
             {
                 if (!prev_complete)
                 {
-                    /* the first histogram is always normal, and the 
+                    /* the first histogram is always normal, and the
                        second one is always reverse */
                     mde_delta_h_make_hist(dh, i, i==1);
                     nhist_written++;
@@ -264,8 +270,8 @@ void mde_delta_h_handle_block(t_mde_delta_h *dh, t_enxblock *blk)
             dh->written=TRUE;
         }
 
-        /* A histogram consists of 2, 3 or 4 subblocks: 
-           the foreign lambda value + histogram spacing, the starting point, 
+        /* A histogram consists of 2, 3 or 4 subblocks:
+           the foreign lambda value + histogram spacing, the starting point,
            and the histogram data (0, 1 or 2 blocks). */
         add_subblocks_enxblock(blk, nhist_written+2);
         blk->id=enxDHHIST;
@@ -290,7 +296,7 @@ void mde_delta_h_handle_block(t_mde_delta_h *dh, t_enxblock *blk)
         /* subblock 3 + 4 : the histogram data */
         for(i=0;i<nhist_written;i++)
         {
-            blk->sub[i+2].nr=dh->maxbin[i]+1; /* it's +1 because size=index+1 
+            blk->sub[i+2].nr=dh->maxbin[i]+1; /* it's +1 because size=index+1
                                                  in C */
             blk->sub[i+2].type=xdr_datatype_int;
             blk->sub[i+2].ival=dh->bin[i];
@@ -301,76 +307,109 @@ void mde_delta_h_handle_block(t_mde_delta_h *dh, t_enxblock *blk)
 /* initialize the collection*/
 void mde_delta_h_coll_init(t_mde_delta_h_coll *dhc, const t_inputrec *ir)
 {
-    int i; 
+    int i;
+    double lambda;
     int ndhmax=ir->nstenergy/ir->nstcalcenergy;
 
-    dhc->temp=ir->opts.ref_t[0]; 
+    dhc->temperature=ir->opts.ref_t[0];  /* only store system temperature */
     dhc->start_time=0.;
-    dhc->start_lambda=ir->init_lambda; 
-   
-    dhc->delta_time=ir->delta_t*ir->nstdhdl;
-    dhc->delta_lambda=ir->delta_lambda*ir->nstdhdl;
-
+    dhc->delta_time=ir->delta_t*ir->fepvals->nstdhdl;
     dhc->start_time_set=FALSE;
 
-    if (ir->dhdl_derivatives == dhdlderivativesYES)
-    {
-        dhc->ndhdl=1;
+    /* for continuous change of lambda values */
+    dhc->start_lambda=ir->fepvals->init_lambda;
+    dhc->delta_lambda=ir->fepvals->delta_lambda*ir->fepvals->nstdhdl;
+
+    /* total number of raw data points in the sample */
+    dhc->ndh = 0;
+
+    /* include one more for the specification of the state, by lambda or fep_state, store as double for now*/
+    if (ir->expandedvals->elamstats > elamstatsNO) {
+        dhc->ndh +=1;
     }
-    else
+
+    /* whether to print energies */
+    if (ir->fepvals->bPrintEnergy) {
+        dhc->ndh += 1;
+    }
+
+    /* add the dhdl's */
+    for (i=0;i<efptNR;i++)
     {
-        dhc->ndhdl=0;
+        if (ir->fepvals->separate_dvdl[i])
+        {
+            dhc->ndh+=1;
+        }
+    }
+
+    /* add the lambdas */
+    dhc->ndh += ir->fepvals->n_lambda;
+
+    if (ir->epc > epcNO) {
+        dhc->ndh += 1;  /* include pressure-volume work */
     }
 
-    dhc->ndh=ir->n_flambda+dhc->ndhdl;
     snew(dhc->dh, dhc->ndh);
     for(i=0;i<dhc->ndh;i++)
     {
-        if (i<dhc->ndhdl)
-        {
-            mde_delta_h_init(dhc->dh + i, ir->dh_hist_size, 
-                             ir->dh_hist_spacing, ndhmax, 
-                             TRUE, dhc->start_lambda);
-        }
-        else
-        {
-            mde_delta_h_init(dhc->dh + i, ir->dh_hist_size, 
-                             ir->dh_hist_spacing, ndhmax, 
-                             FALSE, 
-                             ir->flambda[i-dhc->ndhdl] );
-        }
+        mde_delta_h_init(dhc->dh+i, ir->fepvals->dh_hist_size,
+                         ir->fepvals->dh_hist_spacing, ndhmax);
     }
 }
 
-/* add a bunch of samples */
-void mde_delta_h_coll_add_dh(t_mde_delta_h_coll *dhc, 
-                             double dhdl,
-                             double *U, double time,
-                             double native_lambda)
+/* add a bunch of samples - note fep_state is double to allow for better data storage */
+void mde_delta_h_coll_add_dh(t_mde_delta_h_coll *dhc,
+                             double fep_state,
+                             double energy,
+                             double pV,
+                             int bExpanded,
+                             int bPrintEnergy,
+                             int bPressure,
+                             int ndhdl,
+                             int nlambda,
+                             double *dhdl,
+                             double *foreign_dU,
+                             double time)
 {
-    int i;
+    int i,n;
 
     if (!dhc->start_time_set)
     {
         dhc->start_time_set=TRUE;
         dhc->start_time=time;
-        dhc->start_lambda=native_lambda;
     }
-    for(i=0;i<dhc->ndh;i++)
+
+    n = 0;
+    if (bExpanded)
     {
-        if (i<dhc->ndhdl)
-        {
-            mde_delta_h_add_dh(dhc->dh + i, dhdl, time);
-        }
-        else
-        {
-            mde_delta_h_add_dh(dhc->dh + i, U[i+1-dhc->ndhdl] - U[0], time);
-        }
+        mde_delta_h_add_dh(dhc->dh+n,fep_state,time);
+        n++;
+    }
+    if (bPrintEnergy)
+    {
+        mde_delta_h_add_dh(dhc->dh+n,energy,time);
+        n++;
+    }
+    for (i=0;i<ndhdl;i++)
+    {
+        mde_delta_h_add_dh(dhc->dh+n, dhdl[i], time);
+        n++;
+    }
+    for (i=0;i<nlambda;i++)
+    {
+        mde_delta_h_add_dh(dhc->dh+n, foreign_dU[i], time);
+        n++;
+    }
+    if (bPressure)
+    {
+        mde_delta_h_add_dh(dhc->dh+n, pV, time);
+        n++;
     }
 }
 
-/* write the data associated with all the du blocks, but not the blocks 
-   themselves. */
+/* write the data associated with all the du blocks, but not the blocks
+   themselves. Essentially, the metadata.  Or -- is this generated every time?*/
+
 void mde_delta_h_coll_handle_block(t_mde_delta_h_coll *dhc,
                                    t_enxframe *fr, int nblock)
 {
@@ -384,12 +423,11 @@ void mde_delta_h_coll_handle_block(t_mde_delta_h_coll *dhc,
 
     add_subblocks_enxblock(blk, 1);
 
-    dhc->subblock_d[0] = dhc->temp; /* temperature */
+    dhc->subblock_d[0] = dhc->temperature; /* temperature */
     dhc->subblock_d[1] = dhc->start_time; /* time of first sample */
     dhc->subblock_d[2] = dhc->delta_time; /* time difference between samples */
     dhc->subblock_d[3] = dhc->start_lambda; /* lambda at starttime */
     dhc->subblock_d[4] = dhc->delta_lambda; /* lambda diff. between samples */
-
     blk->id=enxDHCOLL;
     blk->sub[0].nr=5;
     blk->sub[0].type=xdr_datatype_double;
index 3bf9d269d1a5fd6a821698319b4f3698d3a2a4cd..bb4ffd21ed607e4fac913ce3cd36d513a371ba97 100644 (file)
@@ -1,11 +1,11 @@
-/*
- * 
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
  *                This source code is part of
- * 
+ *
  *                 G   R   O   M   A   C   S
- * 
+ *
  *          GROningen MAchine for Chemical Simulations
- * 
+ *
  *                        VERSION 3.2.0
  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * If you want to redistribute modifications, please consider that
  * scientific software is very special. Version control is crucial -
  * bugs must be traceable. We will be happy to consider code for
  * inclusion in the official distribution, but derived work must not
  * be called official GROMACS. Details are found in the README & COPYING
  * files - if they are missing, get the official version at www.gromacs.org.
- * 
+ *
  * To help us fund GROMACS development, we humbly ask that you cite
  * the papers on the package - you can find them in the top README file.
- * 
+ *
  * For more info, check our website at http://www.gromacs.org
- * 
+ *
  * And Hey:
  * Gromacs Runs On Most of All Computer Systems
  */
 extern "C" {
 #endif
 
-/* The functions & data structures here describe writing 
+/* The functions & data structures here describe writing
    energy differences (or their histogram )for use with g_bar */
 
 /* Data for one foreign lambda, or derivative. */
-typedef struct 
+typedef struct
 {
-    real *dh; /* the raw energy differences */
+    real *dh; /* the raw energy difference data -- actually, store more in here. */
+    float *dhf; /* raw difference data -- in floats, for storage. */
     unsigned int ndh; /* number of data points */
     unsigned int ndhmax; /* the maximum number of points */
 
@@ -59,78 +60,87 @@ typedef struct
                      values, respectively). */
     int *bin[2]; /* the histogram(s) */
     double dx; /* the histogram spacing in kJ/mol. This is the
-                  same for the two histograms */
-    unsigned int nbins; /* the number of bins */
-    gmx_large_int_t x0[2]; /* the starting point in units of spacing 
+                  same for the two histograms? */
+    unsigned int nbins; /* the number of bins in the histograms*/
+    gmx_large_int_t x0[2]; /* the starting point in units of spacing
                               of the histogram */
     unsigned int maxbin[2]; /* highest bin number with data */
 
     gmx_bool derivative; /* whether this delta_h contains derivatives */
-    double lambda; /* the 'foreign' lambda value associated with this delta H */
-    gmx_bool written; /* whether this data has already been written out */
+    double lambda; /* current lambda */
+    gmx_bool written;    /* whether this data has already been written out */
 
     double subblock_d[4]; /* data for an mdebin subblock for I/O. */
     gmx_large_int_t subblock_l[4]; /* data for an mdebin subblock for I/O.  */
     int subblock_i[4]; /* data for an mdebin subblock for I/O.  */
 } t_mde_delta_h;
 
-/* the type definition is in mdebin.h */
+/* the type definition is in mdebin_bar.h */
 struct t_mde_delta_h_coll
 {
-    t_mde_delta_h *dh; /* the delta hs */
+    t_mde_delta_h *dh; /* the delta h data */
     int ndh; /* the number of delta_h structures */
-    int ndhdl; /* number of derivative delta_hs */
-
     double start_time; /* start time of the current dh collection */
     double delta_time; /* time difference between samples */
     gmx_bool start_time_set; /* whether the start time has been set */
-
-    double start_lambda; /* the native lambda associated with the free energy 
-                           calculations (at the time of the first sample) */
-    double delta_lambda; /* lambda difference between samples */
-
-    double temp; /* the temperature */
+    double start_lambda; /* starting lambda for continuous motion of state*/
+    double delta_lambda; /* delta lambda, for continuous motion of state */
+    double temperature; /* the temperature of the samples*/
     double subblock_d[5]; /* data for writing an mdebin subblock for I/O */
 };
 
 
 
-/* initialize a collection of delta h histograms/sets 
+/* initialize a collection of delta h histograms/sets
     dhc = the collection
     ir = the input record */
+
 void mde_delta_h_coll_init(t_mde_delta_h_coll *dhc,
                            const t_inputrec *ir);
 
 /* add a bunch of samples to the delta_h collection
     dhc = the collection
-    dhdl = the hamiltonian derivative
+    dhdl = the hamiltonian derivatives
     U = the array with energies: from enerd->enerpart_lambda.
-    time = the current simulation time. */
-void mde_delta_h_coll_add_dh(t_mde_delta_h_coll *dhc, 
-                             double dhdl,
-                             double *U, double time,
-                             double native_lambda);
+    time = the current simulation time.
+    current_lambda = current lambda values : primarily useful for continuous processes
+    fep_state = current fep_state
+ */
+
+/* add a bunch of samples - note fep_state is double to allow for better data storage */
+void mde_delta_h_coll_add_dh(t_mde_delta_h_coll *dhc,
+                             double fep_state,
+                             double energy,
+                             double pV,
+                             int bExpanded,
+                             int bPrintEnergy,
+                             int bPressure,
+                             int ndhdl,
+                             int nlambda,
+                             double *dhdl,
+                             double *foreign_dU,
+                             double time);
 
 /* write the data associated with the du blocks collection as a collection
     of mdebin blocks.
     dhc = the collection
     fr = the enxio frame
     nblock = the current number of blocks */
-void mde_delta_h_coll_handle_block(t_mde_delta_h_coll *dhc,   
+void mde_delta_h_coll_handle_block(t_mde_delta_h_coll *dhc,
                                    t_enxframe *fr, int nblock);
 
 
-/* reset the collection of delta_h buffers for a new round of 
+/* reset the collection of delta_h buffers for a new round of
    data gathering */
 void mde_delta_h_coll_reset(t_mde_delta_h_coll *dhc);
 
 
 /* set the energyhistory variables to save state */
-void mde_delta_h_coll_update_energyhistory(t_mde_delta_h_coll *dhc, 
+void mde_delta_h_coll_update_energyhistory(t_mde_delta_h_coll *dhc,
                                            energyhistory_t *enerhist);
 
 /* restore the variables from an energyhistory */
-void mde_delta_h_coll_restore_energyhistory(t_mde_delta_h_coll *dhc, 
+void mde_delta_h_coll_restore_energyhistory(t_mde_delta_h_coll *dhc,
                                             energyhistory_t *enerhist);
 
 
index c360264bc1188be56acb59a7a53951fd9b7e62b9..927141031215b8370a8980483c8b70d0e0fffc0a 100644 (file)
@@ -1,12 +1,12 @@
 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
  *
- * 
+ *
  *                This source code is part of
- * 
+ *
  *                 G   R   O   M   A   C   S
- * 
+ *
  *          GROningen MAchine for Chemical Simulations
- * 
+ *
  *                        VERSION 3.2.0
  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * If you want to redistribute modifications, please consider that
  * scientific software is very special. Version control is crucial -
  * bugs must be traceable. We will be happy to consider code for
  * inclusion in the official distribution, but derived work must not
  * be called official GROMACS. Details are found in the README & COPYING
  * files - if they are missing, get the official version at www.gromacs.org.
- * 
+ *
  * To help us fund GROMACS development, we humbly ask that you cite
  * the papers on the package - you can find them in the top README file.
- * 
+ *
  * For more info, check our website at http://www.gromacs.org
- * 
+ *
  * And Hey:
  * GROwing Monsters And Cloning Shrimps
  */
@@ -88,9 +88,12 @@ typedef struct {
 static em_state_t *init_em_state()
 {
   em_state_t *ems;
-  
+
   snew(ems,1);
 
+  /* does this need to be here?  Should the array be declared differently (staticaly)in the state definition? */
+  snew(ems->s.lambda,efptNR);
+
   return ems;
 }
 
@@ -157,23 +160,23 @@ static void print_converged(FILE *fp,const char *alg,real ftol,
 
   if (bDone)
     fprintf(fp,"\n%s converged to Fmax < %g in %s steps\n",
-           alg,ftol,gmx_step_str(count,buf)); 
+           alg,ftol,gmx_step_str(count,buf));
   else if(count<nsteps)
     fprintf(fp,"\n%s converged to machine precision in %s steps,\n"
                "but did not reach the requested Fmax < %g.\n",
            alg,gmx_step_str(count,buf),ftol);
-  else 
+  else
     fprintf(fp,"\n%s did not converge to Fmax < %g in %s steps.\n",
            alg,ftol,gmx_step_str(count,buf));
 
 #ifdef GMX_DOUBLE
-  fprintf(fp,"Potential Energy  = %21.14e\n",epot); 
-  fprintf(fp,"Maximum force     = %21.14e on atom %d\n",fmax,nfmax+1); 
-  fprintf(fp,"Norm of force     = %21.14e\n",fnorm); 
+  fprintf(fp,"Potential Energy  = %21.14e\n",epot);
+  fprintf(fp,"Maximum force     = %21.14e on atom %d\n",fmax,nfmax+1);
+  fprintf(fp,"Norm of force     = %21.14e\n",fnorm);
 #else
-  fprintf(fp,"Potential Energy  = %14.7e\n",epot); 
-  fprintf(fp,"Maximum force     = %14.7e on atom %d\n",fmax,nfmax+1); 
-  fprintf(fp,"Norm of force     = %14.7e\n",fnorm); 
+  fprintf(fp,"Potential Energy  = %14.7e\n",epot);
+  fprintf(fp,"Maximum force     = %14.7e on atom %d\n",fmax,nfmax+1);
+  fprintf(fp,"Norm of force     = %14.7e\n",fnorm);
 #endif
 }
 
@@ -269,34 +272,27 @@ void init_em(FILE *fplog,const char *title,
 {
     int  start,homenr,i;
     real dvdlambda;
-    
+
     if (fplog)
     {
         fprintf(fplog,"Initiating %s\n",title);
     }
-    
+
     state_global->ngtc = 0;
-    
-    /* Initiate some variables */
-    if (ir->efep != efepNO)
-    {
-        state_global->lambda = ir->init_lambda;
-    }
-    else 
-    {
-        state_global->lambda = 0.0;
-    }
-    
+
+    /* Initialize lambda variables */
+    initialize_lambdas(fplog,ir,&(state_global->fep_state),state_global->lambda,NULL);
+
     init_nrnb(nrnb);
-    
+
     if (DOMAINDECOMP(cr))
     {
         *top = dd_init_local_top(top_global);
-        
+
         dd_init_local_state(cr->dd,state_global,&ems->s);
 
         *f = NULL;
-        
+
         /* Distribute the charge groups over the nodes from the master node */
         dd_partition_system(fplog,ir->init_step,cr,TRUE,1,
                             state_global,top_global,ir,
@@ -304,7 +300,7 @@ void init_em(FILE *fplog,const char *title,
                             fr,vsite,NULL,constr,
                             nrnb,NULL,FALSE);
         dd_store_state(cr->dd,&ems->s);
-        
+
         if (ir->nstfout)
         {
             snew(*f_global,top_global->natoms);
@@ -328,12 +324,12 @@ void init_em(FILE *fplog,const char *title,
             copy_rvec(state_global->x[i],ems->s.x[i]);
         }
         copy_mat(state_global->box,ems->s.box);
-        
+
         if (PAR(cr) && ir->eI != eiNM)
         {
             /* Initialize the particle decomposition and split the topology */
             *top = split_system(fplog,top_global,ir,cr);
-            
+
             pd_cg_range(cr,&fr->cg0,&fr->hcg);
         }
         else
@@ -341,7 +337,7 @@ void init_em(FILE *fplog,const char *title,
             *top = gmx_mtop_generate_local_top(top_global,ir);
         }
         *f_global = *f;
-        
+
         if (ir->ePBC != epbcNONE && !ir->bPeriodicMols)
         {
             *graph = mk_graph(fplog,&((*top)->idef),0,top_global->natoms,FALSE,FALSE);
@@ -362,14 +358,14 @@ void init_em(FILE *fplog,const char *title,
             homenr = top_global->natoms;
         }
         atoms2md(top_global,ir,0,NULL,start,homenr,mdatoms);
-        update_mdatoms(mdatoms,state_global->lambda);
-    
+        update_mdatoms(mdatoms,state_global->lambda[efptFEP]);
+
         if (vsite)
         {
             set_vsite_top(vsite,*top,mdatoms,cr);
         }
     }
-    
+
     if (constr)
     {
         if (ir->eConstrAlg == econtSHAKE &&
@@ -378,7 +374,7 @@ void init_em(FILE *fplog,const char *title,
             gmx_fatal(FARGS,"Can not do energy minimization with %s, use %s\n",
                       econstr_names[econtSHAKE],econstr_names[econtLINCS]);
         }
-        
+
         if (!DOMAINDECOMP(cr))
         {
             set_constraints(constr,*top,ir,mdatoms,cr);
@@ -391,25 +387,26 @@ void init_em(FILE *fplog,const char *title,
             constrain(PAR(cr) ? NULL : fplog,TRUE,TRUE,constr,&(*top)->idef,
                       ir,NULL,cr,-1,0,mdatoms,
                       ems->s.x,ems->s.x,NULL,ems->s.box,
-                      ems->s.lambda,&dvdlambda,
+                      ems->s.lambda[efptFEP],&dvdlambda,
                       NULL,NULL,nrnb,econqCoord,FALSE,0,0);
         }
     }
-    
+
     if (PAR(cr))
     {
         *gstat = global_stat_init(ir);
     }
-    
+
     *outf = init_mdoutf(nfile,fnm,0,cr,ir,NULL);
 
     snew(*enerd,1);
-    init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,*enerd);
+    init_enerdata(top_global->groups.grps[egcENER].nr,ir->fepvals->n_lambda,
+                  *enerd);
 
     if (mdebin != NULL)
     {
         /* Init bin for energy stuff */
-        *mdebin = init_mdebin((*outf)->fp_ene,top_global,ir,NULL); 
+        *mdebin = init_mdebin((*outf)->fp_ene,top_global,ir,NULL);
     }
 
     clear_rvec(mu_tot);
@@ -463,14 +460,14 @@ static void write_em_traj(FILE *fplog,t_commrec *cr,
         copy_em_coords(state,state_global);
         f_global = state->f;
     }
-    
+
     mdof_flags = 0;
     if (bX) { mdof_flags |= MDOF_X; }
     if (bF) { mdof_flags |= MDOF_F; }
     write_traj(fplog,cr,outf,mdof_flags,
                top_global,step,(double)step,
                &state->s,state_global,state->f,f_global,NULL,NULL);
-    
+
     if (confout != NULL && MASTER(cr))
     {
         if (ir->ePBC != epbcNONE && !ir->bPeriodicMols && DOMAINDECOMP(cr))
@@ -513,9 +510,13 @@ static void do_em_step(t_commrec *cr,t_inputrec *ir,t_mdatoms *md,
     if (s2->flags & (1<<estCGP))
       srenew(s2->cg_p,  s1->nalloc);
   }
-  
+
   s2->natoms = s1->natoms;
-  s2->lambda = s1->lambda;
+  /* Copy free energy state -> is this necessary? */
+  for (i=0;i<efptNR;i++)
+  {
+      s2->lambda[i] = s1->lambda[i];
+  }
   copy_mat(s1->box,s2->box);
 
   start = md->start;
@@ -558,9 +559,9 @@ static void do_em_step(t_commrec *cr,t_inputrec *ir,t_mdatoms *md,
   if (constr) {
     wallcycle_start(wcycle,ewcCONSTR);
     dvdlambda = 0;
-    constrain(NULL,TRUE,TRUE,constr,&top->idef,        
+    constrain(NULL,TRUE,TRUE,constr,&top->idef,
               ir,NULL,cr,count,0,md,
-              s1->x,s2->x,NULL,s2->box,s2->lambda,
+              s1->x,s2->x,NULL,s2->box,s2->lambda[efptBONDED],
               &dvdlambda,NULL,NULL,nrnb,econqCoord,FALSE,0,0);
     wallcycle_stop(wcycle,ewcCONSTR);
   }
@@ -583,7 +584,7 @@ static void em_dd_partition_system(FILE *fplog,int step,t_commrec *cr,
     dd_store_state(cr->dd,&ems->s);
     wallcycle_stop(wcycle,ewcDOMDEC);
 }
-    
+
 static void evaluate_energy(FILE *fplog,gmx_bool bVerbose,t_commrec *cr,
                             t_state *state_global,gmx_mtop_t *top_global,
                             em_state_t *ems,gmx_localtop_t *top,
@@ -601,9 +602,9 @@ static void evaluate_energy(FILE *fplog,gmx_bool bVerbose,t_commrec *cr,
   gmx_bool bNS;
   int  nabnsb;
   tensor force_vir,shake_vir,ekin;
-  real dvdl,prescorr,enercorr,dvdlcorr;
+  real dvdlambda,prescorr,enercorr,dvdlcorr;
   real terminate=0;
-  
+
   /* Set the time to the initial time, the time does not change during EM */
   t = inputrec->init_t;
 
@@ -636,7 +637,7 @@ static void evaluate_energy(FILE *fplog,gmx_bool bVerbose,t_commrec *cr,
                             nrnb,wcycle);
     }
   }
-      
+
     /* Calc force & energy on new trial position  */
     /* do_force always puts the charge groups in the box and shifts again
      * We do not unshift, so molecules are always whole in congrad.c
@@ -648,10 +649,10 @@ static void evaluate_energy(FILE *fplog,gmx_bool bVerbose,t_commrec *cr,
              ems->s.lambda,graph,fr,vsite,mu_tot,t,NULL,NULL,TRUE,
              GMX_FORCE_STATECHANGED | GMX_FORCE_ALLFORCES | GMX_FORCE_VIRIAL |
              (bNS ? GMX_FORCE_NS | GMX_FORCE_DOLR : 0));
-       
-  /* Clear the unused shake virial and pressure */
-  clear_mat(shake_vir);
-  clear_mat(pres);
+
+    /* Clear the unused shake virial and pressure */
+    clear_mat(shake_vir);
+    clear_mat(pres);
 
     /* Communicate stuff when parallel */
     if (PAR(cr) && inputrec->eI != eiNM)
@@ -661,16 +662,16 @@ static void evaluate_energy(FILE *fplog,gmx_bool bVerbose,t_commrec *cr,
         global_stat(fplog,gstat,cr,enerd,force_vir,shake_vir,mu_tot,
                     inputrec,NULL,NULL,NULL,1,&terminate,
                     top_global,&ems->s,FALSE,
-                    CGLO_ENERGY | 
-                    CGLO_PRESSURE | 
-                    CGLO_CONSTRAINT | 
+                    CGLO_ENERGY |
+                    CGLO_PRESSURE |
+                    CGLO_CONSTRAINT |
                     CGLO_FIRSTITERATE);
 
         wallcycle_stop(wcycle,ewcMoveE);
     }
 
     /* Calculate long range corrections to pressure and energy */
-    calc_dispcorr(fplog,inputrec,fr,count,top_global->natoms,ems->s.box,ems->s.lambda,
+    calc_dispcorr(fplog,inputrec,fr,count,top_global->natoms,ems->s.box,ems->s.lambda[efptVDW],
                   pres,force_vir,&prescorr,&enercorr,&dvdlcorr);
     enerd->term[F_DISPCORR] = enercorr;
     enerd->term[F_EPOT] += enercorr;
@@ -678,18 +679,18 @@ static void evaluate_energy(FILE *fplog,gmx_bool bVerbose,t_commrec *cr,
     enerd->term[F_DVDL] += dvdlcorr;
 
   ems->epot = enerd->term[F_EPOT];
-  
+
   if (constr) {
     /* Project out the constraint components of the force */
     wallcycle_start(wcycle,ewcCONSTR);
-    dvdl = 0;
+    dvdlambda = 0;
     constrain(NULL,FALSE,FALSE,constr,&top->idef,
               inputrec,NULL,cr,count,0,mdatoms,
-              ems->s.x,ems->f,ems->f,ems->s.box,ems->s.lambda,&dvdl,
+              ems->s.x,ems->f,ems->f,ems->s.box,ems->s.lambda[efptBONDED],&dvdlambda,
               NULL,&shake_vir,nrnb,econqForceDispl,FALSE,0,0);
     if (fr->bSepDVDL && fplog)
-      fprintf(fplog,sepdvdlformat,"Constraints",t,dvdl);
-    enerd->term[F_DHDL_CON] += dvdl;
+      fprintf(fplog,sepdvdlformat,"Constraints",t,dvdlambda);
+    enerd->term[F_DVDL_BONDED] += dvdlambda;
     m_add(force_vir,shake_vir,vir);
     wallcycle_stop(wcycle,ewcCONSTR);
   } else {
@@ -700,7 +701,7 @@ static void evaluate_energy(FILE *fplog,gmx_bool bVerbose,t_commrec *cr,
   enerd->term[F_PRES] =
     calc_pres(fr->ePBC,inputrec->nwall,ems->s.box,ekin,vir,pres);
 
-  sum_dhdl(enerd,ems->s.lambda,inputrec);
+  sum_dhdl(enerd,ems->s.lambda,inputrec->fepvals);
 
     if (EI_ENERGY_MINIMIZATION(inputrec->eI))
     {
@@ -732,7 +733,7 @@ static double reorder_partsum(t_commrec *cr,t_grpopts *opts,t_mdatoms *mdatoms,
    * but to fully optimize this a much more complicated algorithm is required.
    */
   snew(fmg,mtop->natoms);
-  
+
   ncg   = s_min->s.ncg_gl;
   cg_gl = s_min->s.cg_gl;
   i = 0;
@@ -770,7 +771,7 @@ static double reorder_partsum(t_commrec *cr,t_grpopts *opts,t_mdatoms *mdatoms,
       i++;
     }
   }
-  
+
   sfree(fmg);
 
   return partsum;
@@ -788,7 +789,7 @@ static real pr_beta(t_commrec *cr,t_grpopts *opts,t_mdatoms *mdatoms,
    * it looks a bit complicated since we take freeze groups into account,
    * and might have to sum it in parallel runs.
    */
-  
+
   if (!DOMAINDECOMP(cr) ||
       (s_min->s.ddp_count == cr->dd->ddp_count &&
        s_b->s.ddp_count   == cr->dd->ddp_count)) {
@@ -805,7 +806,7 @@ static real pr_beta(t_commrec *cr,t_grpopts *opts,t_mdatoms *mdatoms,
       for(m=0; m<DIM; m++)
        if (!opts->nFreeze[gf][m]) {
          sum += (fb[i][m] - fm[i][m])*fb[i][m];
-       } 
+       }
     }
   } else {
     /* We need to reorder cgs while summing */
@@ -830,7 +831,7 @@ double do_cg(FILE *fplog,t_commrec *cr,
              t_nrnb *nrnb,gmx_wallcycle_t wcycle,
              gmx_edsam_t ed,
              t_forcerec *fr,
-             int repl_ex_nst,int repl_ex_seed,
+             int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
              gmx_membed_t membed,
              real cpt_period,real max_hours,
              const char *deviceOptions,
@@ -848,7 +849,7 @@ double do_cg(FILE *fplog,t_commrec *cr,
   rvec   *f_global,*p,*sf,*sfm;
   double gpa,gpb,gpc,tmp,sum[2],minstep;
   real   fnormn;
-  real   stepsize;     
+  real   stepsize;
   real   a,b,c,beta=0.0;
   real   epot_repl=0;
   real   pnorm;
@@ -860,7 +861,7 @@ double do_cg(FILE *fplog,t_commrec *cr,
   int    number_steps,neval=0,nstcg=inputrec->nstcgsteep;
   gmx_mdoutf_t *outf;
   int    i,m,gf,step,nminstep;
-  real   terminate=0;  
+  real   terminate=0;
 
   step=0;
 
@@ -874,10 +875,10 @@ double do_cg(FILE *fplog,t_commrec *cr,
           state_global,top_global,s_min,&top,&f,&f_global,
           nrnb,mu_tot,fr,&enerd,&graph,mdatoms,&gstat,vsite,constr,
           nfile,fnm,&outf,&mdebin);
-  
+
   /* Print to log file */
   print_em_start(fplog,cr,runtime,wcycle,CG);
-  
+
   /* Max number of steps */
   number_steps=inputrec->nsteps;
 
@@ -900,10 +901,10 @@ double do_cg(FILE *fplog,t_commrec *cr,
   if (MASTER(cr)) {
     /* Copy stuff to the energy bin for easy printing etc. */
     upd_mdebin(mdebin,FALSE,FALSE,(double)step,
-              mdatoms->tmass,enerd,&s_min->s,s_min->s.box,
-              NULL,NULL,vir,pres,NULL,mu_tot,constr);
-    
-    print_ebin_header(fplog,step,step,s_min->s.lambda);
+               mdatoms->tmass,enerd,&s_min->s,inputrec->fepvals,inputrec->expandedvals,s_min->s.box,
+               NULL,NULL,vir,pres,NULL,mu_tot,constr);
+
+    print_ebin_header(fplog,step,step,s_min->s.lambda[efptFEP]);
     print_ebin(outf->fp_ene,TRUE,FALSE,FALSE,fplog,step,step,eprNORMAL,
                TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
   }
@@ -911,7 +912,7 @@ double do_cg(FILE *fplog,t_commrec *cr,
 
   /* Estimate/guess the initial stepsize */
   stepsize = inputrec->em_stepsize/s_min->fnorm;
+
   if (MASTER(cr)) {
     fprintf(stderr,"   F-max             = %12.5e on atom %d\n",
            s_min->fmax,s_min->a_fmax+1);
@@ -924,16 +925,16 @@ double do_cg(FILE *fplog,t_commrec *cr,
     fprintf(fplog,"   F-Norm            = %12.5e\n",
            s_min->fnorm/sqrt(state_global->natoms));
     fprintf(fplog,"\n");
-  }  
-  /* Start the loop over CG steps.             
+  }
+  /* Start the loop over CG steps.
    * Each successful step is counted, and we continue until
    * we either converge or reach the max number of steps.
    */
   converged = FALSE;
   for(step=0; (number_steps<0 || (number_steps>=0 && step<=number_steps)) && !converged;step++) {
-    
-    /* start taking steps in a new direction 
-     * First time we enter the routine, beta=0, and the direction is 
+
+    /* start taking steps in a new direction
+     * First time we enter the routine, beta=0, and the direction is
      * simply the negative gradient.
      */
 
@@ -943,7 +944,7 @@ double do_cg(FILE *fplog,t_commrec *cr,
     gpa = 0;
     gf = 0;
     for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++) {
-      if (mdatoms->cFREEZE) 
+      if (mdatoms->cFREEZE)
        gf = mdatoms->cFREEZE[i];
       for(m=0; m<DIM; m++) {
        if (!inputrec->opts.nFreeze[gf][m]) {
@@ -955,19 +956,19 @@ double do_cg(FILE *fplog,t_commrec *cr,
        }
       }
     }
-    
+
     /* Sum the gradient along the line across CPUs */
     if (PAR(cr))
       gmx_sumd(1,&gpa,cr);
 
     /* Calculate the norm of the search vector */
     get_f_norm_max(cr,&(inputrec->opts),mdatoms,p,&pnorm,NULL,NULL);
-    
+
     /* Just in case stepsize reaches zero due to numerical precision... */
-    if(stepsize<=0)      
+    if(stepsize<=0)
       stepsize = inputrec->em_stepsize/pnorm;
-    
-    /* 
+
+    /*
      * Double check the value of the derivative in the search direction.
      * If it is positive it must be due to the old information in the
      * CG formula, so just remove that and start over with beta=0.
@@ -1002,15 +1003,15 @@ double do_cg(FILE *fplog,t_commrec *cr,
       converged=TRUE;
       break;
     }
-    
+
     /* Write coordinates if necessary */
     do_x = do_per_step(step,inputrec->nstxout);
     do_f = do_per_step(step,inputrec->nstfout);
-    
+
     write_em_traj(fplog,cr,outf,do_x,do_f,NULL,
                   top_global,inputrec,step,
                   s_min,state_global,f_global);
-    
+
     /* Take a step downhill.
      * In theory, we should minimize the function along this direction.
      * That is quite possible, but it turns out to take 5-10 function evaluations
@@ -1023,15 +1024,15 @@ double do_cg(FILE *fplog,t_commrec *cr,
      * the continue straight to the next CG step without trying to find any minimum.
      * If it didn't work (higher energy), there must be a minimum somewhere between
      * the old position and the new one.
-     * 
+     *
      * Due to the finite numerical accuracy, it turns out that it is a good idea
      * to even accept a SMALL increase in energy, if the derivative is still downhill.
-     * This leads to lower final energies in the tests I've done. / Erik 
+     * This leads to lower final energies in the tests I've done. / Erik
      */
     s_a->epot = s_min->epot;
     a = 0.0;
     c = a + stepsize; /* reference position along line is zero */
-    
+
     if (DOMAINDECOMP(cr) && s_min->s.ddp_count < cr->dd->ddp_count) {
       em_dd_partition_system(fplog,step,cr,top_global,inputrec,
                             s_min,top,mdatoms,fr,vsite,constr,
@@ -1041,7 +1042,7 @@ double do_cg(FILE *fplog,t_commrec *cr,
     /* Take a trial step (new coords in s_c) */
     do_em_step(cr,inputrec,mdatoms,s_min,c,s_min->s.cg_p,s_c,
               constr,top,nrnb,wcycle,-1);
-    
+
     neval++;
     /* Calculate energy for the trial step */
     evaluate_energy(fplog,bVerbose,cr,
@@ -1049,13 +1050,13 @@ double do_cg(FILE *fplog,t_commrec *cr,
                    inputrec,nrnb,wcycle,gstat,
                    vsite,constr,fcd,graph,mdatoms,fr,
                    mu_tot,enerd,vir,pres,-1,FALSE);
-    
+
     /* Calc derivative along line */
     p  = s_c->s.cg_p;
     sf = s_c->f;
     gpc=0;
     for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++) {
-      for(m=0; m<DIM; m++) 
+      for(m=0; m<DIM; m++)
          gpc -= p[i][m]*sf[i][m];  /* f is negative gradient, thus the sign */
     }
     /* Sum the gradient along the line across CPUs */
@@ -1083,11 +1084,11 @@ double do_cg(FILE *fplog,t_commrec *cr,
        */
       foundlower = FALSE;
       stepsize *= 0.618034;
-    }    
+    }
+
 
 
 
-    
     /* OK, if we didn't find a lower value we will have to locate one now - there must
      * be one in the interval [a=0,c].
      * The same thing is valid here, though: Don't spend dozens of iterations to find
@@ -1110,14 +1111,14 @@ double do_cg(FILE *fplog,t_commrec *cr,
        if(gpa<0 && gpc>0)
          b = a + gpa*(a-c)/(gpc-gpa);
        else
-         b = 0.5*(a+c);                
-       
+         b = 0.5*(a+c);
+
        /* safeguard if interpolation close to machine accuracy causes errors:
         * never go outside the interval
         */
        if(b<=a || b>=c)
          b = 0.5*(a+c);
-       
+
        if (DOMAINDECOMP(cr) && s_min->s.ddp_count != cr->dd->ddp_count) {
          /* Reload the old state */
          em_dd_partition_system(fplog,-1,cr,top_global,inputrec,
@@ -1128,7 +1129,7 @@ double do_cg(FILE *fplog,t_commrec *cr,
        /* Take a trial step to this new point - new coords in s_b */
        do_em_step(cr,inputrec,mdatoms,s_min,b,s_min->s.cg_p,s_b,
                   constr,top,nrnb,wcycle,-1);
-       
+
        neval++;
        /* Calculate energy for the trial step */
        evaluate_energy(fplog,bVerbose,cr,
@@ -1136,7 +1137,7 @@ double do_cg(FILE *fplog,t_commrec *cr,
                        inputrec,nrnb,wcycle,gstat,
                        vsite,constr,fcd,graph,mdatoms,fr,
                        mu_tot,enerd,vir,pres,-1,FALSE);
-       
+
        /* p does not change within a step, but since the domain decomposition
         * might change, we have to use cg_p of s_b here.
         */
@@ -1150,13 +1151,13 @@ double do_cg(FILE *fplog,t_commrec *cr,
        /* Sum the gradient along the line across CPUs */
        if (PAR(cr))
          gmx_sumd(1,&gpb,cr);
-       
+
        if (debug)
          fprintf(debug,"CGE: EpotA %f EpotB %f EpotC %f gpb %f\n",
                  s_a->epot,s_b->epot,s_c->epot,gpb);
 
        epot_repl = s_b->epot;
-       
+
        /* Keep one of the intervals based on the value of the derivative at the new point */
        if (gpb > 0) {
          /* Replace c endpoint with b */
@@ -1169,15 +1170,15 @@ double do_cg(FILE *fplog,t_commrec *cr,
          a = b;
          gpa = gpb;
        }
-       
-       /* 
+
+       /*
         * Stop search as soon as we find a value smaller than the endpoints.
         * Never run more than 20 steps, no matter what.
         */
        nminstep++;
       } while ((epot_repl > s_a->epot || epot_repl > s_c->epot) &&
-              (nminstep < 20));     
-      
+              (nminstep < 20));
+
       if (fabs(epot_repl - s_min->epot) < fabs(s_min->epot)*GMX_REAL_EPS ||
          nminstep >= 20) {
        /* OK. We couldn't find a significantly lower energy.
@@ -1194,7 +1195,7 @@ double do_cg(FILE *fplog,t_commrec *cr,
          continue;
        }
       }
-      
+
       /* Select min energy state of A & C, put the best in B.
        */
       if (s_c->epot < s_a->epot) {
@@ -1212,7 +1213,7 @@ double do_cg(FILE *fplog,t_commrec *cr,
        gpb = gpa;
        b = a;
       }
-      
+
     } else {
       if (debug)
        fprintf(debug,"CGE: Found a lower energy %f, moving C to B\n",
@@ -1221,10 +1222,10 @@ double do_cg(FILE *fplog,t_commrec *cr,
       gpb = gpc;
       b = c;
     }
-    
+
     /* new search direction */
     /* beta = 0 means forget all memory and restart with steepest descents. */
-    if (nstcg && ((step % nstcg)==0)) 
+    if (nstcg && ((step % nstcg)==0))
       beta = 0.0;
     else {
       /* s_min->fnorm cannot be zero, because then we would have converged
@@ -1239,12 +1240,12 @@ double do_cg(FILE *fplog,t_commrec *cr,
     /* Limit beta to prevent oscillations */
     if (fabs(beta) > 5.0)
       beta = 0.0;
-    
-    
+
+
     /* update positions */
     swap_em_state(s_min,s_b);
     gpa = gpb;
-    
+
     /* Print it if necessary */
     if (MASTER(cr)) {
       if(bVerbose)
@@ -1253,27 +1254,28 @@ double do_cg(FILE *fplog,t_commrec *cr,
                s_min->fmax,s_min->a_fmax+1);
       /* Store the new (lower) energies */
       upd_mdebin(mdebin,FALSE,FALSE,(double)step,
-                mdatoms->tmass,enerd,&s_min->s,s_min->s.box,
-                NULL,NULL,vir,pres,NULL,mu_tot,constr);
+                 mdatoms->tmass,enerd,&s_min->s,inputrec->fepvals,inputrec->expandedvals,s_min->s.box,
+                 NULL,NULL,vir,pres,NULL,mu_tot,constr);
+
       do_log = do_per_step(step,inputrec->nstlog);
       do_ene = do_per_step(step,inputrec->nstenergy);
       if(do_log)
-       print_ebin_header(fplog,step,step,s_min->s.lambda);
+          print_ebin_header(fplog,step,step,s_min->s.lambda[efptFEP]);
       print_ebin(outf->fp_ene,do_ene,FALSE,FALSE,
                 do_log ? fplog : NULL,step,step,eprNORMAL,
                 TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
     }
-    
+
     /* Stop when the maximum force lies below tolerance.
      * If we have reached machine precision, converged is already set to true.
-     */        
+     */
     converged = converged || (s_min->fmax < inputrec->em_tol);
-    
+
   } /* End of the loop */
-  
-  if (converged)       
+
+  if (converged)
     step--; /* we never took that last step in this case */
-  
+
     if (s_min->fmax > inputrec->em_tol)
     {
         if (MASTER(cr))
@@ -1281,16 +1283,16 @@ double do_cg(FILE *fplog,t_commrec *cr,
             warn_step(stderr,inputrec->em_tol,step-1==number_steps,FALSE);
             warn_step(fplog ,inputrec->em_tol,step-1==number_steps,FALSE);
         }
-        converged = FALSE; 
+        converged = FALSE;
     }
-  
+
   if (MASTER(cr)) {
     /* If we printed energy and/or logfile last step (which was the last step)
      * we don't have to do it again, but otherwise print the final values.
      */
     if(!do_log) {
       /* Write final value to log since we didn't do anything the last step */
-      print_ebin_header(fplog,step,step,s_min->s.lambda);
+      print_ebin_header(fplog,step,step,s_min->s.lambda[efptFEP]);
     }
     if (!do_ene || !do_log) {
       /* Write final energy file entries */
@@ -1303,34 +1305,34 @@ double do_cg(FILE *fplog,t_commrec *cr,
   /* Print some stuff... */
   if (MASTER(cr))
     fprintf(stderr,"\nwriting lowest energy coordinates.\n");
-  
+
   /* IMPORTANT!
    * For accurate normal mode calculation it is imperative that we
    * store the last conformation into the full precision binary trajectory.
    *
    * However, we should only do it if we did NOT already write this step
    * above (which we did if do_x or do_f was true).
-   */  
+   */
   do_x = !do_per_step(step,inputrec->nstxout);
   do_f = (inputrec->nstfout > 0 && !do_per_step(step,inputrec->nstfout));
-  
+
   write_em_traj(fplog,cr,outf,do_x,do_f,ftp2fn(efSTO,nfile,fnm),
                 top_global,inputrec,step,
                 s_min,state_global,f_global);
-  
+
   fnormn = s_min->fnorm/sqrt(state_global->natoms);
-  
+
   if (MASTER(cr)) {
     print_converged(stderr,CG,inputrec->em_tol,step,converged,number_steps,
                    s_min->epot,s_min->fmax,s_min->a_fmax,fnormn);
     print_converged(fplog,CG,inputrec->em_tol,step,converged,number_steps,
                    s_min->epot,s_min->fmax,s_min->a_fmax,fnormn);
-    
+
     fprintf(fplog,"\nPerformed %d energy evaluations in total.\n",neval);
   }
-  
+
   finish_em(fplog,cr,outf,runtime,wcycle);
-  
+
   /* To print the actual number of steps we needed somewhere */
   runtime->nsteps_done = step;
 
@@ -1351,7 +1353,7 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
                 t_nrnb *nrnb,gmx_wallcycle_t wcycle,
                 gmx_edsam_t ed,
                 t_forcerec *fr,
-                int repl_ex_nst,int repl_ex_seed,
+                int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
                 gmx_membed_t membed,
                 real cpt_period,real max_hours,
                 const char *deviceOptions,
@@ -1368,7 +1370,7 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
   rvec   *f_global;
   int    ncorr,nmaxcorr,point,cp,neval,nminstep;
   double stepsize,gpa,gpb,gpc,tmp,minstep;
-  real   *rho,*alpha,*ff,*xx,*p,*s,*lastx,*lastf,**dx,**dg;    
+  real   *rho,*alpha,*ff,*xx,*p,*s,*lastx,*lastf,**dx,**dg;
   real   *xa,*xb,*xc,*fa,*fb,*fc,*xtmp,*ftmp;
   real   a,b,c,maxdelta,delta;
   real   diag,Epot0,Epot,EpotA,EpotB,EpotC;
@@ -1387,10 +1389,10 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
 
   if (PAR(cr))
     gmx_fatal(FARGS,"Cannot do parallel L-BFGS Minimization - yet.\n");
-  
+
   n = 3*state->natoms;
   nmaxcorr = inputrec->nbfgscorr;
-  
+
   /* Allocate memory */
   /* Use pointers to real so we dont have to loop over both atoms and
    * dimensions all the time...
@@ -1405,22 +1407,22 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
   snew(fc,n);
   snew(frozen,n);
 
-  snew(p,n); 
-  snew(lastx,n); 
-  snew(lastf,n); 
+  snew(p,n);
+  snew(lastx,n);
+  snew(lastf,n);
   snew(rho,nmaxcorr);
   snew(alpha,nmaxcorr);
-  
+
   snew(dx,nmaxcorr);
   for(i=0;i<nmaxcorr;i++)
     snew(dx[i],n);
-  
+
   snew(dg,nmaxcorr);
   for(i=0;i<nmaxcorr;i++)
     snew(dg[i],n);
 
   step = 0;
-  neval = 0; 
+  neval = 0;
 
   /* Init em */
   init_em(fplog,LBFGS,cr,inputrec,
@@ -1438,12 +1440,12 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
 
   start = mdatoms->start;
   end   = mdatoms->homenr + start;
-    
+
   /* Print to log file */
   print_em_start(fplog,cr,runtime,wcycle,LBFGS);
-  
+
   do_log = do_ene = do_x = do_f = TRUE;
-  
+
   /* Max number of steps */
   number_steps=inputrec->nsteps;
 
@@ -1452,19 +1454,19 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
   for(i=start; i<end; i++) {
     if (mdatoms->cFREEZE)
       gf = mdatoms->cFREEZE[i];
-     for(m=0; m<DIM; m++) 
-       frozen[3*i+m]=inputrec->opts.nFreeze[gf][m];  
+     for(m=0; m<DIM; m++)
+       frozen[3*i+m]=inputrec->opts.nFreeze[gf][m];
   }
   if (MASTER(cr))
     sp_header(stderr,LBFGS,inputrec->em_tol,number_steps);
   if (fplog)
     sp_header(fplog,LBFGS,inputrec->em_tol,number_steps);
-  
+
   if (vsite)
     construct_vsites(fplog,vsite,state->x,nrnb,1,NULL,
                     top->idef.iparams,top->idef.il,
                     fr->ePBC,fr->bMolPBC,graph,cr,state->box);
-  
+
   /* Call the force routine and some auxiliary (neighboursearching etc.) */
   /* do_force always puts the charge groups in the box and shifts again
    * We do not unshift, so molecules are always whole
@@ -1478,32 +1480,32 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
                  vsite,constr,fcd,graph,mdatoms,fr,
                  mu_tot,enerd,vir,pres,-1,TRUE);
   where();
-       
+
   if (MASTER(cr)) {
     /* Copy stuff to the energy bin for easy printing etc. */
     upd_mdebin(mdebin,FALSE,FALSE,(double)step,
-              mdatoms->tmass,enerd,state,state->box,
-              NULL,NULL,vir,pres,NULL,mu_tot,constr);
-    
-    print_ebin_header(fplog,step,step,state->lambda);
+               mdatoms->tmass,enerd,state,inputrec->fepvals,inputrec->expandedvals,state->box,
+               NULL,NULL,vir,pres,NULL,mu_tot,constr);
+
+    print_ebin_header(fplog,step,step,state->lambda[efptFEP]);
     print_ebin(outf->fp_ene,TRUE,FALSE,FALSE,fplog,step,step,eprNORMAL,
                TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
   }
   where();
-  
+
   /* This is the starting energy */
   Epot = enerd->term[F_EPOT];
-  
+
   fnorm = ems.fnorm;
   fmax  = ems.fmax;
   nfmax = ems.a_fmax;
-  
+
   /* Set the initial step.
-   * since it will be multiplied by the non-normalized search direction 
+   * since it will be multiplied by the non-normalized search direction
    * vector (force vector the first time), we scale it by the
    * norm of the force.
    */
-  
+
   if (MASTER(cr)) {
     fprintf(stderr,"Using %d BFGS correction steps.\n\n",nmaxcorr);
     fprintf(stderr,"   F-max             = %12.5e on atom %d\n",fmax,nfmax+1);
@@ -1514,8 +1516,8 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
     fprintf(fplog,"   F-max             = %12.5e on atom %d\n",fmax,nfmax+1);
     fprintf(fplog,"   F-Norm            = %12.5e\n",fnorm/sqrt(state->natoms));
     fprintf(fplog,"\n");
-  }   
-  
+  }
+
   point=0;
   for(i=0;i<n;i++)
     if(!frozen[i])
@@ -1525,36 +1527,36 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
 
   stepsize = 1.0/fnorm;
   converged = FALSE;
-  
-  /* Start the loop over BFGS steps.           
+
+  /* Start the loop over BFGS steps.
    * Each successful step is counted, and we continue until
    * we either converge or reach the max number of steps.
    */
-  
+
   ncorr=0;
 
   /* Set the gradient from the force */
   converged = FALSE;
   for(step=0; (number_steps<0 || (number_steps>=0 && step<=number_steps)) && !converged; step++) {
-    
+
     /* Write coordinates if necessary */
     do_x = do_per_step(step,inputrec->nstxout);
     do_f = do_per_step(step,inputrec->nstfout);
-    
+
     write_traj(fplog,cr,outf,MDOF_X | MDOF_F,
                top_global,step,(real)step,state,state,f,f,NULL,NULL);
 
     /* Do the linesearching in the direction dx[point][0..(n-1)] */
-    
+
     /* pointer to current direction - point=0 first time here */
     s=dx[point];
-    
+
     /* calculate line gradient */
-    for(gpa=0,i=0;i<n;i++) 
+    for(gpa=0,i=0;i<n;i++)
        gpa-=s[i]*ff[i];
 
-    /* Calculate minimum allowed stepsize, before the average (norm) 
-     * relative change in coordinate is smaller than precision 
+    /* Calculate minimum allowed stepsize, before the average (norm)
+     * relative change in coordinate is smaller than precision
      */
     for(minstep=0,i=0;i<n;i++) {
       tmp=fabs(xx[i]);
@@ -1564,24 +1566,24 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
       minstep += tmp*tmp;
     }
     minstep = GMX_REAL_EPS/sqrt(minstep/n);
-    
+
     if(stepsize<minstep) {
       converged=TRUE;
       break;
     }
-    
+
     /* Store old forces and coordinates */
     for(i=0;i<n;i++) {
       lastx[i]=xx[i];
       lastf[i]=ff[i];
     }
     Epot0=Epot;
-    
+
     first=TRUE;
-    
+
     for(i=0;i<n;i++)
       xa[i]=xx[i];
-    
+
     /* Take a step downhill.
      * In theory, we should minimize the function along this direction.
      * That is quite possible, but it turns out to take 5-10 function evaluations
@@ -1594,17 +1596,17 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
      * the continue straight to the next BFGS step without trying to find any minimum.
      * If it didn't work (higher energy), there must be a minimum somewhere between
      * the old position and the new one.
-     * 
+     *
      * Due to the finite numerical accuracy, it turns out that it is a good idea
      * to even accept a SMALL increase in energy, if the derivative is still downhill.
-     * This leads to lower final energies in the tests I've done. / Erik 
+     * This leads to lower final energies in the tests I've done. / Erik
      */
     foundlower=FALSE;
     EpotA = Epot0;
     a = 0.0;
     c = a + stepsize; /* reference position along line is zero */
 
-    /* Check stepsize first. We do not allow displacements 
+    /* Check stepsize first. We do not allow displacements
      * larger than emstep.
      */
     do {
@@ -1622,7 +1624,7 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
     /* Take a trial step */
     for (i=0; i<n; i++)
       xc[i] = lastx[i] + c*s[i];
-    
+
     neval++;
     /* Calculate energy for the trial step */
     ems.s.x = (rvec *)xc;
@@ -1633,7 +1635,7 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
                    vsite,constr,fcd,graph,mdatoms,fr,
                    mu_tot,enerd,vir,pres,step,FALSE);
     EpotC = ems.epot;
-    
+
     /* Calc derivative along line */
     for(gpc=0,i=0; i<n; i++) {
        gpc -= s[i]*fc[i];   /* f is negative gradient, thus the sign */
@@ -1641,10 +1643,10 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
     /* Sum the gradient along the line across CPUs */
     if (PAR(cr))
       gmx_sumd(1,&gpc,cr);
-    
+
      /* This is the max amount of increase in energy we tolerate */
    tmp=sqrt(GMX_REAL_EPS)*fabs(EpotA);
-    
+
     /* Accept the step if the energy is lower, or if it is not significantly higher
      * and the line derivative is still negative.
      */
@@ -1663,8 +1665,8 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
        */
       foundlower = FALSE;
       stepsize *= 0.618034;
-    }    
-    
+    }
+
     /* OK, if we didn't find a lower value we will have to locate one now - there must
      * be one in the interval [a=0,c].
      * The same thing is valid here, though: Don't spend dozens of iterations to find
@@ -1678,29 +1680,29 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
      */
 
     if(!foundlower) {
-     
+
       nminstep=0;
       do {
        /* Select a new trial point.
         * If the derivatives at points a & c have different sign we interpolate to zero,
         * otherwise just do a bisection.
         */
-       
+
        if(gpa<0 && gpc>0)
          b = a + gpa*(a-c)/(gpc-gpa);
        else
-         b = 0.5*(a+c);                
-       
+         b = 0.5*(a+c);
+
        /* safeguard if interpolation close to machine accuracy causes errors:
         * never go outside the interval
         */
        if(b<=a || b>=c)
          b = 0.5*(a+c);
-       
+
        /* Take a trial step */
-       for (i=0; i<n; i++) 
+       for (i=0; i<n; i++)
          xb[i] = lastx[i] + b*s[i];
-       
+
        neval++;
        /* Calculate energy for the trial step */
        ems.s.x = (rvec *)xb;
@@ -1711,16 +1713,16 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
                        vsite,constr,fcd,graph,mdatoms,fr,
                        mu_tot,enerd,vir,pres,step,FALSE);
        EpotB = ems.epot;
-       
+
        fnorm = ems.fnorm;
-       
-       for(gpb=0,i=0; i<n; i++) 
+
+       for(gpb=0,i=0; i<n; i++)
          gpb -= s[i]*fb[i];   /* f is negative gradient, thus the sign */
-       
+
        /* Sum the gradient along the line across CPUs */
        if (PAR(cr))
          gmx_sumd(1,&gpb,cr);
-       
+
        /* Keep one of the intervals based on the value of the derivative at the new point */
        if(gpb>0) {
          /* Replace c endpoint with b */
@@ -1728,9 +1730,9 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
          c = b;
          gpc = gpb;
          /* swap coord pointers b/c */
-         xtmp = xb; 
+         xtmp = xb;
          ftmp = fb;
-         xb = xc; 
+         xb = xc;
          fb = fc;
          xc = xtmp;
          fc = ftmp;
@@ -1740,20 +1742,20 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
          a = b;
          gpa = gpb;
          /* swap coord pointers a/b */
-         xtmp = xb; 
+         xtmp = xb;
          ftmp = fb;
-         xb = xa; 
+         xb = xa;
          fb = fa;
-         xa = xtmp; 
+         xa = xtmp;
          fa = ftmp;
        }
-       
-       /* 
+
+       /*
         * Stop search as soon as we find a value smaller than the endpoints,
         * or if the tolerance is below machine precision.
         * Never run more than 20 steps, no matter what.
         */
-       nminstep++; 
+       nminstep++;
       } while((EpotB>EpotA || EpotB>EpotC) && (nminstep<20));
 
       if(fabs(EpotB-Epot0)<GMX_REAL_EPS || nminstep>=20) {
@@ -1776,7 +1778,7 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
          continue;
        }
       }
-      
+
       /* Select min energy state of A & C, put the best in xx/ff/Epot
        */
       if(EpotC<EpotA) {
@@ -1796,7 +1798,7 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
        }
        stepsize=a;
       }
-      
+
     } else {
       /* found lower */
       Epot = EpotC;
@@ -1808,11 +1810,11 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
       stepsize=c;
     }
 
-    /* Update the memory information, and calculate a new 
-     * approximation of the inverse hessian 
+    /* Update the memory information, and calculate a new
+     * approximation of the inverse hessian
      */
-    
-    /* Have new data in Epot, xx, ff */        
+
+    /* Have new data in Epot, xx, ff */
     if(ncorr<nmaxcorr)
       ncorr++;
 
@@ -1820,64 +1822,64 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
       dg[point][i]=lastf[i]-ff[i];
       dx[point][i]*=stepsize;
     }
-    
+
     dgdg=0;
-    dgdx=0;    
+    dgdx=0;
     for(i=0;i<n;i++) {
       dgdg+=dg[point][i]*dg[point][i];
       dgdx+=dg[point][i]*dx[point][i];
     }
-    
+
     diag=dgdx/dgdg;
-    
+
     rho[point]=1.0/dgdx;
     point++;
-    
+
     if(point>=nmaxcorr)
       point=0;
-    
+
     /* Update */
     for(i=0;i<n;i++)
       p[i]=ff[i];
-    
+
     cp=point;
-    
+
     /* Recursive update. First go back over the memory points */
     for(k=0;k<ncorr;k++) {
       cp--;
-      if(cp<0) 
+      if(cp<0)
        cp=ncorr-1;
-      
+
       sq=0;
       for(i=0;i<n;i++)
        sq+=dx[cp][i]*p[i];
-      
+
       alpha[cp]=rho[cp]*sq;
-      
+
       for(i=0;i<n;i++)
-       p[i] -= alpha[cp]*dg[cp][i];            
+       p[i] -= alpha[cp]*dg[cp][i];
     }
-    
+
     for(i=0;i<n;i++)
       p[i] *= diag;
-    
+
     /* And then go forward again */
     for(k=0;k<ncorr;k++) {
       yr = 0;
       for(i=0;i<n;i++)
        yr += p[i]*dg[cp][i];
-      
-      beta = rho[cp]*yr;           
+
+      beta = rho[cp]*yr;
       beta = alpha[cp]-beta;
-      
+
       for(i=0;i<n;i++)
        p[i] += beta*dx[cp][i];
-      
-      cp++;    
+
+      cp++;
       if(cp>=ncorr)
        cp=0;
     }
-    
+
     for(i=0;i<n;i++)
       if(!frozen[i])
        dx[point][i] = p[i];
@@ -1885,10 +1887,10 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
        dx[point][i] = 0;
 
     stepsize=1.0;
-    
+
     /* Test whether the convergence criterion is met */
     get_f_norm_max(cr,&(inputrec->opts),mdatoms,f,&fnorm,&fmax,&nfmax);
-    
+
     /* Print it if necessary */
     if (MASTER(cr)) {
       if(bVerbose)
@@ -1896,28 +1898,28 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
                step,Epot,fnorm/sqrt(state->natoms),fmax,nfmax+1);
       /* Store the new (lower) energies */
       upd_mdebin(mdebin,FALSE,FALSE,(double)step,
-                mdatoms->tmass,enerd,state,state->box,
-                NULL,NULL,vir,pres,NULL,mu_tot,constr);
+                 mdatoms->tmass,enerd,state,inputrec->fepvals,inputrec->expandedvals,state->box,
+                 NULL,NULL,vir,pres,NULL,mu_tot,constr);
       do_log = do_per_step(step,inputrec->nstlog);
       do_ene = do_per_step(step,inputrec->nstenergy);
       if(do_log)
-       print_ebin_header(fplog,step,step,state->lambda);
+          print_ebin_header(fplog,step,step,state->lambda[efptFEP]);
       print_ebin(outf->fp_ene,do_ene,FALSE,FALSE,
                 do_log ? fplog : NULL,step,step,eprNORMAL,
                 TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
     }
-    
+
     /* Stop when the maximum force lies below tolerance.
      * If we have reached machine precision, converged is already set to true.
      */
-    
+
     converged = converged || (fmax < inputrec->em_tol);
-    
+
   } /* End of the loop */
-  
-  if(converged)        
+
+  if(converged)
     step--; /* we never took that last step in this case */
-  
+
     if(fmax>inputrec->em_tol)
     {
         if (MASTER(cr))
@@ -1925,45 +1927,45 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
             warn_step(stderr,inputrec->em_tol,step-1==number_steps,FALSE);
             warn_step(fplog ,inputrec->em_tol,step-1==number_steps,FALSE);
         }
-        converged = FALSE; 
+        converged = FALSE;
     }
-  
+
   /* If we printed energy and/or logfile last step (which was the last step)
    * we don't have to do it again, but otherwise print the final values.
    */
   if(!do_log) /* Write final value to log since we didn't do anythin last step */
-    print_ebin_header(fplog,step,step,state->lambda);
+    print_ebin_header(fplog,step,step,state->lambda[efptFEP]);
   if(!do_ene || !do_log) /* Write final energy file entries */
     print_ebin(outf->fp_ene,!do_ene,FALSE,FALSE,
               !do_log ? fplog : NULL,step,step,eprNORMAL,
               TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
-  
+
   /* Print some stuff... */
   if (MASTER(cr))
     fprintf(stderr,"\nwriting lowest energy coordinates.\n");
-  
+
   /* IMPORTANT!
    * For accurate normal mode calculation it is imperative that we
    * store the last conformation into the full precision binary trajectory.
    *
    * However, we should only do it if we did NOT already write this step
    * above (which we did if do_x or do_f was true).
-   */  
+   */
   do_x = !do_per_step(step,inputrec->nstxout);
   do_f = !do_per_step(step,inputrec->nstfout);
   write_em_traj(fplog,cr,outf,do_x,do_f,ftp2fn(efSTO,nfile,fnm),
                 top_global,inputrec,step,
                 &ems,state,f);
-  
+
   if (MASTER(cr)) {
     print_converged(stderr,LBFGS,inputrec->em_tol,step,converged,
                    number_steps,Epot,fmax,nfmax,fnorm/sqrt(state->natoms));
     print_converged(fplog,LBFGS,inputrec->em_tol,step,converged,
                    number_steps,Epot,fmax,nfmax,fnorm/sqrt(state->natoms));
-    
+
     fprintf(fplog,"\nPerformed %d energy evaluations in total.\n",neval);
   }
-  
+
   finish_em(fplog,cr,outf,runtime,wcycle);
 
   /* To print the actual number of steps we needed somewhere */
@@ -1986,13 +1988,13 @@ double do_steep(FILE *fplog,t_commrec *cr,
                 t_nrnb *nrnb,gmx_wallcycle_t wcycle,
                 gmx_edsam_t ed,
                 t_forcerec *fr,
-                int repl_ex_nst,int repl_ex_seed,
+                int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
                 gmx_membed_t membed,
                 real cpt_period,real max_hours,
                 const char *deviceOptions,
                 unsigned long Flags,
                 gmx_runtime_t *runtime)
-{ 
+{
   const char *SD="Steepest Descents";
   em_state_t *s_min,*s_try;
   rvec       *f_global;
@@ -2004,13 +2006,13 @@ double do_steep(FILE *fplog,t_commrec *cr,
   real   stepsize,constepsize;
   real   ustep,dvdlambda,fnormn;
   gmx_mdoutf_t *outf;
-  t_mdebin   *mdebin; 
-  gmx_bool   bDone,bAbort,do_x,do_f; 
-  tensor vir,pres; 
+  t_mdebin   *mdebin;
+  gmx_bool   bDone,bAbort,do_x,do_f;
+  tensor vir,pres;
   rvec   mu_tot;
   int    nsteps;
-  int    count=0; 
-  int    steps_accepted=0; 
+  int    count=0;
+  int    steps_accepted=0;
   /* not used */
   real   terminate=0;
 
@@ -2022,27 +2024,27 @@ double do_steep(FILE *fplog,t_commrec *cr,
           state_global,top_global,s_try,&top,&f,&f_global,
           nrnb,mu_tot,fr,&enerd,&graph,mdatoms,&gstat,vsite,constr,
           nfile,fnm,&outf,&mdebin);
-       
+
   /* Print to log file  */
   print_em_start(fplog,cr,runtime,wcycle,SD);
-    
-  /* Set variables for stepsize (in nm). This is the largest  
-   * step that we are going to make in any direction. 
+
+  /* Set variables for stepsize (in nm). This is the largest
+   * step that we are going to make in any direction.
    */
-  ustep = inputrec->em_stepsize; 
+  ustep = inputrec->em_stepsize;
   stepsize = 0;
-  
+
   /* Max number of steps  */
-  nsteps = inputrec->nsteps; 
-  
-  if (MASTER(cr)) 
+  nsteps = inputrec->nsteps;
+
+  if (MASTER(cr))
     /* Print to the screen  */
     sp_header(stderr,SD,inputrec->em_tol,nsteps);
   if (fplog)
     sp_header(fplog,SD,inputrec->em_tol,nsteps);
-    
+
   /**** HERE STARTS THE LOOP ****
-   * count is the counter for the number of steps 
+   * count is the counter for the number of steps
    * bDone will be TRUE when the minimization has converged
    * bAbort will be TRUE when nsteps steps have been performed or when
    * the stepsize becomes smaller than is reasonable for machine precision
@@ -2052,25 +2054,25 @@ double do_steep(FILE *fplog,t_commrec *cr,
   bAbort = FALSE;
   while( !bDone && !bAbort ) {
     bAbort = (nsteps >= 0) && (count == nsteps);
-    
+
     /* set new coordinates, except for first step */
     if (count > 0) {
       do_em_step(cr,inputrec,mdatoms,s_min,stepsize,s_min->f,s_try,
                 constr,top,nrnb,wcycle,count);
     }
-    
+
     evaluate_energy(fplog,bVerbose,cr,
                    state_global,top_global,s_try,top,
                    inputrec,nrnb,wcycle,gstat,
                    vsite,constr,fcd,graph,mdatoms,fr,
                    mu_tot,enerd,vir,pres,count,count==0);
-        
+
     if (MASTER(cr))
-      print_ebin_header(fplog,count,count,s_try->s.lambda);
+      print_ebin_header(fplog,count,count,s_try->s.lambda[efptFEP]);
 
     if (count == 0)
       s_min->epot = s_try->epot + 1;
-    
+
     /* Print it if necessary  */
     if (MASTER(cr)) {
       if (bVerbose) {
@@ -2078,12 +2080,12 @@ double do_steep(FILE *fplog,t_commrec *cr,
                count,ustep,s_try->epot,s_try->fmax,s_try->a_fmax+1,
                (s_try->epot < s_min->epot) ? '\n' : '\r');
       }
-      
+
       if (s_try->epot < s_min->epot) {
        /* Store the new (lower) energies  */
        upd_mdebin(mdebin,FALSE,FALSE,(double)count,
-                  mdatoms->tmass,enerd,&s_try->s,s_try->s.box,
-                  NULL,NULL,vir,pres,NULL,mu_tot,constr);
+                  mdatoms->tmass,enerd,&s_try->s,inputrec->fepvals,inputrec->expandedvals,
+                   s_try->s.box, NULL,NULL,vir,pres,NULL,mu_tot,constr);
        print_ebin(outf->fp_ene,TRUE,
                   do_per_step(steps_accepted,inputrec->nstdisreout),
                   do_per_step(steps_accepted,inputrec->nstorireout),
@@ -2091,21 +2093,21 @@ double do_steep(FILE *fplog,t_commrec *cr,
                   mdebin,fcd,&(top_global->groups),&(inputrec->opts));
        fflush(fplog);
       }
-    } 
-    
-    /* Now if the new energy is smaller than the previous...  
+    }
+
+    /* Now if the new energy is smaller than the previous...
      * or if this is the first step!
-     * or if we did random steps! 
+     * or if we did random steps!
      */
-    
+
     if ( (count==0) || (s_try->epot < s_min->epot) ) {
-      steps_accepted++; 
+      steps_accepted++;
 
       /* Test whether the convergence criterion is met...  */
       bDone = (s_try->fmax < inputrec->em_tol);
-      
+
       /* Copy the arrays for force, positions and energy  */
-      /* The 'Min' array always holds the coords and forces of the minimal 
+      /* The 'Min' array always holds the coords and forces of the minimal
         sampled energy  */
       swap_em_state(s_min,s_try);
       if (count > 0)
@@ -2117,7 +2119,7 @@ double do_steep(FILE *fplog,t_commrec *cr,
       write_em_traj(fplog,cr,outf,do_x,do_f,NULL,
                     top_global,inputrec,count,
                     s_min,state_global,f_global);
-    } 
+    }
     else {
       /* If energy is not smaller make the step smaller...  */
       ustep *= 0.5;
@@ -2129,10 +2131,10 @@ double do_steep(FILE *fplog,t_commrec *cr,
                               nrnb,wcycle);
       }
     }
-    
+
     /* Determine new step  */
     stepsize = ustep/s_min->fmax;
-    
+
     /* Check if stepsize is too small, with 1 nm as a characteristic length */
 #ifdef GMX_DOUBLE
         if (count == nsteps || ustep < 1e-12)
@@ -2147,13 +2149,13 @@ double do_steep(FILE *fplog,t_commrec *cr,
             }
             bAbort=TRUE;
         }
-    
+
     count++;
   } /* End of the loop  */
-  
+
     /* Print some shit...  */
-  if (MASTER(cr)) 
-    fprintf(stderr,"\nwriting lowest energy coordinates.\n"); 
+  if (MASTER(cr))
+    fprintf(stderr,"\nwriting lowest energy coordinates.\n");
   write_em_traj(fplog,cr,outf,TRUE,inputrec->nstfout,ftp2fn(efSTO,nfile,fnm),
                top_global,inputrec,count,
                s_min,state_global,f_global);
@@ -2168,12 +2170,12 @@ double do_steep(FILE *fplog,t_commrec *cr,
   }
 
   finish_em(fplog,cr,outf,runtime,wcycle);
-  
+
   /* To print the actual number of steps we needed somewhere */
   inputrec->nsteps=count;
 
   runtime->nsteps_done = count;
-  
+
   return 0;
 } /* That's all folks */
 
@@ -2191,7 +2193,7 @@ double do_nm(FILE *fplog,t_commrec *cr,
              t_nrnb *nrnb,gmx_wallcycle_t wcycle,
              gmx_edsam_t ed,
              t_forcerec *fr,
-             int repl_ex_nst,int repl_ex_seed,
+             int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
              gmx_membed_t membed,
              real cpt_period,real max_hours,
              const char *deviceOptions,
@@ -2208,7 +2210,7 @@ double do_nm(FILE *fplog,t_commrec *cr,
     rvec       *f;
     gmx_global_stat_t gstat;
     t_graph    *graph;
-    real       t,lambda;
+    real       t,t0,lambda,lam0;
     gmx_bool       bNS;
     tensor     vir,pres;
     rvec       mu_tot;
@@ -2218,31 +2220,31 @@ double do_nm(FILE *fplog,t_commrec *cr,
     gmx_sparsematrix_t * sparse_matrix = NULL;
     real *     full_matrix             = NULL;
     em_state_t *   state_work;
-       
+
     /* added with respect to mdrun */
     int        i,j,k,row,col;
     real       der_range=10.0*sqrt(GMX_REAL_EPS);
     real       x_min;
     real       fnorm,fmax;
-    
+
     if (constr != NULL)
     {
         gmx_fatal(FARGS,"Constraints present with Normal Mode Analysis, this combination is not supported");
     }
 
     state_work = init_em_state();
-    
+
     /* Init em and store the local state in state_minimum */
     init_em(fplog,NM,cr,inputrec,
             state_global,top_global,state_work,&top,
             &f,&f_global,
             nrnb,mu_tot,fr,&enerd,&graph,mdatoms,&gstat,vsite,constr,
             nfile,fnm,&outf,NULL);
-    
+
     natoms = top_global->natoms;
     snew(fneg,natoms);
     snew(dfdx,natoms);
-    
+
 #ifndef GMX_DOUBLE
     if (MASTER(cr))
     {
@@ -2253,11 +2255,11 @@ double do_nm(FILE *fplog,t_commrec *cr,
                 "      are fairly modest even if you recompile in double precision.\n\n");
     }
 #endif
-    
+
     /* Check if we can/should use sparse storage format.
      *
      * Sparse format is only useful when the Hessian itself is sparse, which it
-      * will be when we use a cutoff.    
+      * will be when we use a cutoff.
       * For small systems (n<1000) it is easier to always use full matrix format, though.
       */
     if(EEL_FULL(fr->eeltype) || fr->rlist==0.0)
@@ -2275,9 +2277,9 @@ double do_nm(FILE *fplog,t_commrec *cr,
         fprintf(stderr,"Using compressed symmetric sparse Hessian format.\n");
         bSparse = TRUE;
     }
-    
+
     sz = DIM*top_global->natoms;
-    
+
     fprintf(stderr,"Allocating Hessian memory...\n\n");
 
     if(bSparse)
@@ -2289,29 +2291,31 @@ double do_nm(FILE *fplog,t_commrec *cr,
     {
         snew(full_matrix,sz*sz);
     }
-    
+
     /* Initial values */
-    t      = inputrec->init_t;
-    lambda = inputrec->init_lambda;
-    
+    t0           = inputrec->init_t;
+    lam0         = inputrec->fepvals->init_lambda;
+    t            = t0;
+    lambda       = lam0;
+
     init_nrnb(nrnb);
-    
+
     where();
-    
+
     /* Write start time and temperature */
     print_em_start(fplog,cr,runtime,wcycle,NM);
 
     /* fudge nr of steps to nr of atoms */
     inputrec->nsteps = natoms*2;
 
-    if (MASTER(cr)) 
+    if (MASTER(cr))
     {
         fprintf(stderr,"starting normal mode calculation '%s'\n%d steps.\n\n",
                 *(top_global->name),(int)inputrec->nsteps);
     }
 
     nnodes = cr->nnodes;
-   
+
     /* Make evaluate_energy do a single node force calculation */
     cr->nnodes = 1;
     evaluate_energy(fplog,bVerbose,cr,
@@ -2327,7 +2331,7 @@ double do_nm(FILE *fplog,t_commrec *cr,
     if (MASTER(cr))
     {
         fprintf(stderr,"Maximum force:%12.5e\n",state_work->fmax);
-        if (state_work->fmax > 1.0e-3) 
+        if (state_work->fmax > 1.0e-3)
         {
             fprintf(stderr,"Maximum force probably not small enough to");
             fprintf(stderr," ensure that you are in an \nenergy well. ");
@@ -2335,26 +2339,26 @@ double do_nm(FILE *fplog,t_commrec *cr,
             fprintf(stderr," when the\nresulting matrix is diagonalized.\n");
         }
     }
-    
+
     /***********************************************************
      *
-     *      Loop over all pairs in matrix 
-     * 
-     *      do_force called twice. Once with positive and 
-     *      once with negative displacement 
+     *      Loop over all pairs in matrix
+     *
+     *      do_force called twice. Once with positive and
+     *      once with negative displacement
      *
      ************************************************************/
 
     /* Steps are divided one by one over the nodes */
-    for(atom=cr->nodeid; atom<natoms; atom+=nnodes) 
+    for(atom=cr->nodeid; atom<natoms; atom+=nnodes)
     {
-        
-        for (d=0; d<DIM; d++) 
+
+        for (d=0; d<DIM; d++)
         {
             x_min = state_work->s.x[atom][d];
 
             state_work->s.x[atom][d] = x_min - der_range;
-          
+
             /* Make evaluate_energy do a single node force calculation */
             cr->nnodes = 1;
             evaluate_energy(fplog,bVerbose,cr,
@@ -2362,14 +2366,14 @@ double do_nm(FILE *fplog,t_commrec *cr,
                             inputrec,nrnb,wcycle,gstat,
                             vsite,constr,fcd,graph,mdatoms,fr,
                             mu_tot,enerd,vir,pres,atom*2,FALSE);
-                       
+
             for(i=0; i<natoms; i++)
             {
                 copy_rvec(state_work->f[i], fneg[i]);
             }
-            
+
             state_work->s.x[atom][d] = x_min + der_range;
-            
+
             evaluate_energy(fplog,bVerbose,cr,
                             state_global,top_global,state_work,top,
                             inputrec,nrnb,wcycle,gstat,
@@ -2380,9 +2384,9 @@ double do_nm(FILE *fplog,t_commrec *cr,
             /* x is restored to original */
             state_work->s.x[atom][d] = x_min;
 
-            for(j=0; j<natoms; j++) 
+            for(j=0; j<natoms; j++)
             {
-                for (k=0; (k<DIM); k++) 
+                for (k=0; (k<DIM); k++)
                 {
                     dfdx[j][k] =
                         -(state_work->f[j][k] - fneg[j][k])/(2*der_range);
@@ -2417,12 +2421,12 @@ double do_nm(FILE *fplog,t_commrec *cr,
 
                     row = (atom + node)*DIM + d;
 
-                    for(j=0; j<natoms; j++) 
+                    for(j=0; j<natoms; j++)
                     {
-                        for(k=0; k<DIM; k++) 
+                        for(k=0; k<DIM; k++)
                         {
                             col = j*DIM + k;
-                            
+
                             if (bSparse)
                             {
                                 if (col >= row && dfdx[j][k] != 0.0)
@@ -2439,22 +2443,22 @@ double do_nm(FILE *fplog,t_commrec *cr,
                     }
                 }
             }
-            
+
             if (bVerbose && fplog)
             {
-                fflush(fplog);            
+                fflush(fplog);
             }
         }
         /* write progress */
-        if (MASTER(cr) && bVerbose) 
+        if (MASTER(cr) && bVerbose)
         {
             fprintf(stderr,"\rFinished step %d out of %d",
-                    min(atom+nnodes,natoms),natoms); 
+                    min(atom+nnodes,natoms),natoms);
             fflush(stderr);
         }
     }
-    
-    if (MASTER(cr)) 
+
+    if (MASTER(cr))
     {
         fprintf(stderr,"\n\nWriting Hessian...\n");
         gmx_mtxio_write(ftp2fn(efMTX,nfile,fnm),sz,sz,full_matrix,sparse_matrix);
@@ -2463,6 +2467,7 @@ double do_nm(FILE *fplog,t_commrec *cr,
     finish_em(fplog,cr,outf,runtime,wcycle);
 
     runtime->nsteps_done = natoms*2;
-    
+
     return 0;
 }
+
index 6651f1ed80b7a54383d81caa303058f7ae3c4a8d..2757cbd2dde292bd7f83a2d209ff1c233ed49989 100644 (file)
@@ -278,32 +278,32 @@ void init_neighbor_list(FILE *log,t_forcerec *fr,int homenr)
    /* Start with GB */
    if(fr->bGB)
    {
-       icoul=4;
+       icoul=enbcoulGB;
    }
    else if (fr->bcoultab)
    {
-       icoul = 3;
+       icoul = enbcoulTAB;
    }
    else if (EEL_RF(fr->eeltype))
    {
-       icoul = 2;
+       icoul = enbcoulRF;
    }
    else 
    {
-       icoul = 1;
+       icoul = enbcoulOOR;
    }
    
    if (fr->bvdwtab)
    {
-       ivdw = 3;
+       ivdw = enbvdwTAB;
    }
    else if (fr->bBHAM)
    {
-       ivdw = 2;
+       ivdw = enbvdwBHAM;
    }
    else 
    {
-       ivdw = 1;
+       ivdw = enbvdwLJ;
    }
 
    fr->ns.bCGlist = (getenv("GMX_NBLISTCG") != 0);
@@ -348,9 +348,9 @@ void init_neighbor_list(FILE *log,t_forcerec *fr,int homenr)
        
        if (fr->efep != efepNO) 
        {
-           if (fr->bEwald)
+           if ((fr->bEwald) && (fr->sc_alphacoul > 0)) /* need to handle long range differently if using softcore */
            {
-               icoulf = 5;
+               icoulf = enbcoulFEWALD;
            }
            else
            {
@@ -1790,7 +1790,7 @@ static void do_longrange(t_commrec *cr,gmx_localtop_t *top,t_forcerec *fr,
                          int jgid,int nlr,
                          atom_id lr[],t_excl bexcl[],int shift,
                          rvec x[],rvec box_size,t_nrnb *nrnb,
-                         real lambda,real *dvdlambda,
+                         real *lambda,real *dvdlambda,
                          gmx_grppairener_t *grppener,
                          gmx_bool bDoVdW,gmx_bool bDoCoul,
                          gmx_bool bEvaluateNow,put_in_list_t *put_in_list,
@@ -1918,7 +1918,7 @@ static int nsgrid_core(FILE *log,t_commrec *cr,t_forcerec *fr,
                        t_grid *grid,rvec x[],
                        t_excl bexcl[],gmx_bool *bExcludeAlleg,
                        t_nrnb *nrnb,t_mdatoms *md,
-                       real lambda,real *dvdlambda,
+                       real *lambda,real *dvdlambda,
                        gmx_grppairener_t *grppener,
                        put_in_list_t *put_in_list,
                        gmx_bool bHaveVdW[],
@@ -2519,7 +2519,7 @@ int search_neighbours(FILE *log,t_forcerec *fr,
                       gmx_groups_t *groups,
                       t_commrec *cr,
                       t_nrnb *nrnb,t_mdatoms *md,
-                      real lambda,real *dvdlambda,
+                      real *lambda,real *dvdlambda,
                       gmx_grppairener_t *grppener,
                       gmx_bool bFillGrid,
                       gmx_bool bDoLongRange,
index 029c9f7b93bff95e37da8fd23d58e2fad2c5f03c..e5b8ab249e076f30b0bee23246568874f8645eab 100644 (file)
@@ -877,13 +877,19 @@ gmx_bool setup_parallel_vsites(t_idef *idef,t_commrec *cr,
 
 t_state *partdec_init_local_state(t_commrec *cr,t_state *state_global)
 {
+  int i;
   t_state *state_local;
 
   snew(state_local,1);
 
   /* Copy all the contents */
   *state_local = *state_global;
-
+  snew(state_local->lambda,efptNR);
+  /* local storage for lambda */
+  for (i=0;i<efptNR;i++)
+    {
+      state_local->lambda[i] = state_global->lambda[i];
+    }
   if (state_global->nrngi > 1) {
     /* With stochastic dynamics we need local storage for the random state */
     if (state_local->flags & (1<<estLD_RNG)) {
index e5f0c1ec763e1cf817ad250e31f59f4bd350a4c0..bb85739bf923c303aa0f83fba349199861ca5993 100644 (file)
@@ -1064,9 +1064,9 @@ void dd_make_local_pull_groups(gmx_domdec_t *dd,t_pull *pull,t_mdatoms *md)
 }
 
 static void init_pull_group_index(FILE *fplog,t_commrec *cr,
-                                 int start,int end,
-                                 int g,t_pullgrp *pg,ivec pulldims,
-                                 gmx_mtop_t *mtop,t_inputrec *ir)
+                                  int start,int end,
+                                  int g,t_pullgrp *pg,ivec pulldims,
+                                  gmx_mtop_t *mtop,t_inputrec *ir, real lambda)
 {
   int i,ii,d,nfrozen,ndim;
   real m,w,mbd;
@@ -1126,7 +1126,7 @@ static void init_pull_group_index(FILE *fplog,t_commrec *cr,
     if (ir->efep == efepNO) {
       m = atom->m;
     } else {
-      m = (1 - ir->init_lambda)*atom->m + ir->init_lambda*atom->mB;
+      m = (1 - lambda)*atom->m + lambda*atom->mB;
     }
     if (pg->nweight > 0) {
       w = pg->weight[i];
@@ -1193,7 +1193,7 @@ static void init_pull_group_index(FILE *fplog,t_commrec *cr,
 }
 
 void init_pull(FILE *fplog,t_inputrec *ir,int nfile,const t_filenm fnm[],
-              gmx_mtop_t *mtop,t_commrec *cr,const output_env_t oenv,
+               gmx_mtop_t *mtop,t_commrec *cr,const output_env_t oenv, real lambda,
                gmx_bool bOutFile, unsigned long Flags)
 {
     t_pull    *pull;
@@ -1298,7 +1298,7 @@ void init_pull(FILE *fplog,t_inputrec *ir,int nfile,const t_filenm fnm[],
                 }
             }
             /* Set the indices */
-            init_pull_group_index(fplog,cr,start,end,g,pgrp,pull->dim,mtop,ir);
+            init_pull_group_index(fplog,cr,start,end,g,pgrp,pull->dim,mtop,ir,lambda);
             if (PULL_CYL(pull) && pgrp->invtm == 0)
             {
                 gmx_fatal(FARGS,"Can not have frozen atoms in a cylinder pull group");
index 5b6fa615b44815a0ebb718503bbf243814aec087..e3dc3fd7c9850616ce80f13f932049a6209cb0ba 100644 (file)
@@ -699,7 +699,7 @@ static void init_adir(FILE *log,gmx_shellfc_t shfc,
                      gmx_large_int_t step,t_mdatoms *md,int start,int end,
                      rvec *x_old,rvec *x_init,rvec *x,
                      rvec *f,rvec *acc_dir,matrix box,
-                     real lambda,real *dvdlambda,t_nrnb *nrnb)
+                     real *lambda,real *dvdlambda,t_nrnb *nrnb)
 {
   rvec   *xnold,*xnew;
   double w_dt;
@@ -741,10 +741,10 @@ static void init_adir(FILE *log,gmx_shellfc_t shfc,
   }
   constrain(log,FALSE,FALSE,constr,idef,ir,NULL,cr,step,0,md,
            x,xnold-start,NULL,box,
-           lambda,dvdlambda,NULL,NULL,nrnb,econqCoord,FALSE,0,0);
+           lambda[efptBONDED],&(dvdlambda[efptBONDED]),NULL,NULL,nrnb,econqCoord,FALSE,0,0);
   constrain(log,FALSE,FALSE,constr,idef,ir,NULL,cr,step,0,md,
            x,xnew-start,NULL,box,
-           lambda,dvdlambda,NULL,NULL,nrnb,econqCoord,FALSE,0,0);
+           lambda[efptBONDED],&(dvdlambda[efptBONDED]),NULL,NULL,nrnb,econqCoord,FALSE,0,0);
 
   /* Set xnew to minus the acceleration */
   for (n=start; n<end; n++) {
@@ -758,7 +758,7 @@ static void init_adir(FILE *log,gmx_shellfc_t shfc,
   /* Project the acceleration on the old bond directions */
   constrain(log,FALSE,FALSE,constr,idef,ir,NULL,cr,step,0,md,
            x_old,xnew-start,acc_dir,box,
-           lambda,dvdlambda,NULL,NULL,nrnb,econqDeriv_FlexCon,FALSE,0,0); 
+           lambda[efptBONDED],&(dvdlambda[efptBONDED]),NULL,NULL,nrnb,econqDeriv_FlexCon,FALSE,0,0);
 }
 
 int relax_shell_flexcon(FILE *fplog,t_commrec *cr,gmx_bool bVerbose,
index 26307dac5a6ff02a22ba48047a83a8da5555bf82..bf6743544041b800f1be9c05cca044848f8bbfca 100644 (file)
@@ -1,12 +1,12 @@
 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
  *
- * 
+ *
  *                This source code is part of
- * 
+ *
  *                 G   R   O   M   A   C   S
- * 
+ *
  *          GROningen MAchine for Chemical Simulations
- * 
+ *
  *                        VERSION 3.2.0
  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * If you want to redistribute modifications, please consider that
  * scientific software is very special. Version control is crucial -
  * bugs must be traceable. We will be happy to consider code for
  * inclusion in the official distribution, but derived work must not
  * be called official GROMACS. Details are found in the README & COPYING
  * files - if they are missing, get the official version at www.gromacs.org.
- * 
+ *
  * To help us fund GROMACS development, we humbly ask that you cite
  * the papers on the package - you can find them in the top README file.
- * 
+ *
  * For more info, check our website at http://www.gromacs.org
- * 
+ *
  * And Hey:
  * GROwing Monsters And Cloning Shrimps
  */
@@ -80,6 +80,7 @@
 #include "xtcio.h"
 #include "copyrite.h"
 #include "pull_rotation.h"
+#include "gmx_random.h"
 #include "mpelogging.h"
 #include "domdec.h"
 #include "partdec.h"
@@ -98,7 +99,7 @@
 
 #if 0
 typedef struct gmx_timeprint {
-    
+
 } t_gmx_timeprint;
 #endif
 
@@ -113,17 +114,17 @@ gmx_gettime()
 #ifdef HAVE_GETTIMEOFDAY
        struct timeval t;
        double seconds;
-       
+
        gettimeofday(&t,NULL);
-       
+
        seconds = (double) t.tv_sec + 1e-6*(double)t.tv_usec;
-       
+
        return seconds;
 #else
        double  seconds;
-       
+
        seconds = time(NULL);
-       
+
        return seconds;
 #endif
 }
@@ -131,14 +132,14 @@ gmx_gettime()
 
 #define difftime(end,start) ((double)(end)-(double)(start))
 
-void print_time(FILE *out,gmx_runtime_t *runtime,gmx_large_int_t step,   
+void print_time(FILE *out,gmx_runtime_t *runtime,gmx_large_int_t step,
                 t_inputrec *ir, t_commrec *cr)
 {
     time_t finish;
     char   timebuf[STRLEN];
     double dt;
     char buf[48];
-    
+
 #ifndef GMX_THREAD_MPI
     if (!PAR(cr))
 #endif
@@ -156,11 +157,11 @@ void print_time(FILE *out,gmx_runtime_t *runtime,gmx_large_int_t step,
             runtime->time_per_step = dt/(step - ir->init_step + 1);
         }
         dt = (ir->nsteps + ir->init_step - step)*runtime->time_per_step;
-        
+
         if (ir->nsteps >= 0)
         {
             if (dt >= 300)
-            {    
+            {
                 finish = (time_t) (runtime->last + dt);
                 gmx_ctime_r(&finish,timebuf,STRLEN);
                 sprintf(buf,"%s",timebuf);
@@ -186,7 +187,7 @@ void print_time(FILE *out,gmx_runtime_t *runtime,gmx_large_int_t step,
     fflush(out);
 }
 
-#ifdef NO_CLOCK 
+#ifdef NO_CLOCK
 #define clock() -1
 #endif
 
@@ -198,7 +199,7 @@ static double set_proctime(gmx_runtime_t *runtime)
 
     prev = runtime->proc;
     runtime->proc = dclock();
-    
+
     diff = runtime->proc - prev;
 #else
     clock_t prev;
@@ -231,9 +232,9 @@ void runtime_start(gmx_runtime_t *runtime)
 void runtime_end(gmx_runtime_t *runtime)
 {
     double now;
-    
+
     now = gmx_gettime();
-    
+
     runtime->proctime += set_proctime(runtime);
     runtime->realtime  = now - runtime->real;
     runtime->real      = now;
@@ -277,7 +278,7 @@ void print_date_and_time(FILE *fplog,int nodeid,const char *title,
 static void sum_forces(int start,int end,rvec f[],rvec flr[])
 {
   int i;
-  
+
   if (gmx_debug_at) {
     pr_rvecs(debug,0,"fsr",f+start,end-start);
     pr_rvecs(debug,0,"flr",flr+start,end-start);
@@ -286,17 +287,17 @@ static void sum_forces(int start,int end,rvec f[],rvec flr[])
     rvec_inc(f[i],flr[i]);
 }
 
-/* 
+/*
  * calc_f_el calculates forces due to an electric field.
  *
- * force is kJ mol^-1 nm^-1 = e * kJ mol^-1 nm^-1 / e 
+ * force is kJ mol^-1 nm^-1 = e * kJ mol^-1 nm^-1 / e
  *
- * Et[] contains the parameters for the time dependent 
- * part of the field (not yet used). 
+ * Et[] contains the parameters for the time dependent
+ * part of the field (not yet used).
  * Ex[] contains the parameters for
  * the spatial dependent part of the field. You can have cool periodic
  * fields in principle, but only a constant field is supported
- * now. 
+ * now.
  * The function should return the energy due to the electric field
  * (if any) but for now returns 0.
  *
@@ -316,7 +317,7 @@ static void calc_f_el(FILE *fp,int  start,int homenr,
     rvec Ext;
     real t0;
     int  i,m;
-    
+
     for(m=0; (m<DIM); m++)
     {
         if (Et[m].n > 0)
@@ -365,9 +366,9 @@ static void calc_virial(FILE *fplog,int start,int homenr,rvec x[],rvec f[],
   clear_mat(vir_part);
   calc_vir(fplog,SHIFTS,fr->shift_vec,fr->fshift,vir_part,ePBC==epbcSCREW,box);
   inc_nrnb(nrnb,eNR_VIRIAL,SHIFTS);
-  
-  /* Calculate partial virial, for local atoms only, based on short range. 
-   * Total virial is computed in global_stat, called from do_md 
+
+  /* Calculate partial virial, for local atoms only, based on short range.
+   * Total virial is computed in global_stat, called from do_md
    */
   f_calc_vir(fplog,start,start+homenr,x,f,vir_part,graph,box);
   inc_nrnb(nrnb,eNR_VIRIAL,homenr);
@@ -416,7 +417,7 @@ void do_force(FILE *fplog,t_commrec *cr,
               tensor vir_force,
               t_mdatoms *mdatoms,
               gmx_enerdata_t *enerd,t_fcdata *fcd,
-              real lambda,t_graph *graph,
+              real *lambda,t_graph *graph,
               t_forcerec *fr,gmx_vsite_t *vsite,rvec mu_tot,
               double t,FILE *field,gmx_edsam_t ed,
               gmx_bool bBornRadii,
@@ -424,15 +425,16 @@ void do_force(FILE *fplog,t_commrec *cr,
 {
     int    cg0,cg1,i,j;
     int    start,homenr;
-    double mu[2*DIM]; 
+    double mu[2*DIM];
     gmx_bool   bSepDVDL,bStateChanged,bNS,bFillGrid,bCalcCGCM,bBS;
     gmx_bool   bDoLongRange,bDoForces,bSepLRF;
     gmx_bool   bDoAdressWF;
     matrix boxs;
-    real   e,v,dvdl;
+    real   e,v,dvdlambda[efptNR];
+    real   dvdl_dum,lambda_dum;
     t_pbc  pbc;
     float  cycles_ppdpme,cycles_pme,cycles_seppme,cycles_force;
-  
+
     start  = mdatoms->start;
     homenr = mdatoms->homenr;
 
@@ -462,7 +464,7 @@ void do_force(FILE *fplog,t_commrec *cr,
     }
 
     bStateChanged = (flags & GMX_FORCE_STATECHANGED);
-    bNS           = (flags & GMX_FORCE_NS) && (fr->bAllvsAll==FALSE); 
+    bNS           = (flags & GMX_FORCE_NS) && (fr->bAllvsAll==FALSE);
     bFillGrid     = (bNS && bStateChanged);
     bCalcCGCM     = (bFillGrid && !DOMAINDECOMP(cr));
     bDoLongRange  = (fr->bTwinRange && bNS && (flags & GMX_FORCE_DOLR));
@@ -474,37 +476,37 @@ void do_force(FILE *fplog,t_commrec *cr,
     if (bStateChanged)
     {
         update_forcerec(fplog,fr,box);
-        
-        /* Calculate total (local) dipole moment in a temporary common array. 
+
+        /* Calculate total (local) dipole moment in a temporary common array.
          * This makes it possible to sum them over nodes faster.
          */
         calc_mu(start,homenr,
                 x,mdatoms->chargeA,mdatoms->chargeB,mdatoms->nChargePerturbed,
                 mu,mu+DIM);
     }
-  
-  if (fr->ePBC != epbcNONE) { 
+
+  if (fr->ePBC != epbcNONE) {
     /* Compute shift vectors every step,
      * because of pressure coupling or box deformation!
      */
     if ((flags & GMX_FORCE_DYNAMICBOX) && bStateChanged)
       calc_shifts(box,fr->shift_vec);
-    
-    if (bCalcCGCM) { 
+
+    if (bCalcCGCM) {
       put_charge_groups_in_box(fplog,cg0,cg1,fr->ePBC,box,
                               &(top->cgs),x,fr->cg_cm);
       inc_nrnb(nrnb,eNR_CGCM,homenr);
       inc_nrnb(nrnb,eNR_RESETX,cg1-cg0);
-    } 
+    }
     else if (EI_ENERGY_MINIMIZATION(inputrec->eI) && graph) {
       unshift_self(graph,box,x);
     }
-  } 
+  }
   else if (bCalcCGCM) {
     calc_cgcm(fplog,cg0,cg1,&(top->cgs),x,fr->cg_cm);
     inc_nrnb(nrnb,eNR_CGCM,homenr);
   }
-  
+
   if (bCalcCGCM) {
     if (PAR(cr)) {
       move_cgcm(fplog,cr,fr->cg_cm);
@@ -519,7 +521,7 @@ void do_force(FILE *fplog,t_commrec *cr,
      * Since this is only implemented for domain decomposition
      * and domain decomposition does not use the graph,
      * we do not need to worry about shifting.
-     */    
+     */
 
     wallcycle_start(wcycle,ewcPP_PMESENDX);
     GMX_MPE_LOG(ev_send_coordinates_start);
@@ -531,7 +533,7 @@ void do_force(FILE *fplog,t_commrec *cr,
     }
 
     gmx_pme_send_x(cr,bBS ? boxs : box,x,
-                   mdatoms->nChargePerturbed,lambda,
+                   mdatoms->nChargePerturbed,lambda[efptCOUL],
                    ( flags & GMX_FORCE_VIRIAL),step);
 
     GMX_MPE_LOG(ev_send_coordinates_finish);
@@ -604,7 +606,7 @@ void do_force(FILE *fplog,t_commrec *cr,
         for(j=0; j<DIM; j++)
         {
             mu_tot[j] =
-                (1.0 - lambda)*fr->mu_tot[0][j] + lambda*fr->mu_tot[1][j];
+                (1.0 - lambda[efptCOUL])*fr->mu_tot[0][j] + lambda[efptCOUL]*fr->mu_tot[1][j];
         }
     }
 
@@ -615,7 +617,7 @@ void do_force(FILE *fplog,t_commrec *cr,
     if (bNS)
     {
         wallcycle_start(wcycle,ewcNS);
-        
+
         if (graph && bStateChanged)
         {
             /* Calculate intramolecular shift vectors to make molecules whole */
@@ -632,26 +634,27 @@ void do_force(FILE *fplog,t_commrec *cr,
         /* Do the actual neighbour searching and if twin range electrostatics
          * also do the calculation of long range forces and energies.
          */
-        dvdl = 0; 
+        for (i=0;i<efptNR;i++) {dvdlambda[i] = 0;}
         ns(fplog,fr,x,box,
            groups,&(inputrec->opts),top,mdatoms,
-           cr,nrnb,lambda,&dvdl,&enerd->grpp,bFillGrid,
+           cr,nrnb,lambda,dvdlambda,&enerd->grpp,bFillGrid,
            bDoLongRange,bDoForces,bSepLRF ? fr->f_twin : f);
         if (bSepDVDL)
         {
-            fprintf(fplog,sepdvdlformat,"LR non-bonded",0.0,dvdl);
+            fprintf(fplog,sepdvdlformat,"LR non-bonded",0.0,dvdlambda);
         }
-        enerd->dvdl_lin += dvdl;
-        
+        enerd->dvdl_lin[efptVDW] += dvdlambda[efptVDW];
+        enerd->dvdl_lin[efptCOUL] += dvdlambda[efptCOUL];
+
         wallcycle_stop(wcycle,ewcNS);
     }
-       
-    if (inputrec->implicit_solvent && bNS) 
+
+    if (inputrec->implicit_solvent && bNS)
     {
         make_gb_nblist(cr,inputrec->gb_algorithm,inputrec->rlist,
                        x,box,fr,&top->idef,graph,fr->born);
     }
-       
+
     if (DOMAINDECOMP(cr))
     {
         if (!(cr->duty & DUTY_PME))
@@ -660,7 +663,7 @@ void do_force(FILE *fplog,t_commrec *cr,
             dd_force_flop_start(cr->dd,nrnb);
         }
     }
-    
+
     if (inputrec->bRot)
     {
         /* Enforced rotation has its own cycle counter that starts after the collective
@@ -682,7 +685,7 @@ void do_force(FILE *fplog,t_commrec *cr,
     {
         /* Reset forces for which the virial is calculated separately:
          * PME/Ewald forces if necessary */
-        if (fr->bF_NoVirSum) 
+        if (fr->bF_NoVirSum)
         {
             if (flags & GMX_FORCE_VIRIAL)
             {
@@ -747,39 +750,55 @@ void do_force(FILE *fplog,t_commrec *cr,
         v = posres(top->idef.il[F_POSRES].nr,top->idef.il[F_POSRES].iatoms,
                    top->idef.iparams_posres,
                    (const rvec*)x,fr->f_novirsum,fr->vir_diag_posres,
-                   inputrec->ePBC==epbcNONE ? NULL : &pbc,lambda,&dvdl,
+                   inputrec->ePBC==epbcNONE ? NULL : &pbc,lambda[efptRESTRAINT],&(dvdlambda[efptRESTRAINT]),
                    fr->rc_scaling,fr->ePBC,fr->posres_com,fr->posres_comB);
         if (bSepDVDL)
         {
             fprintf(fplog,sepdvdlformat,
-                    interaction_function[F_POSRES].longname,v,dvdl);
+                    interaction_function[F_POSRES].longname,v,dvdlambda);
         }
         enerd->term[F_POSRES] += v;
         /* This linear lambda dependence assumption is only correct
          * when only k depends on lambda,
          * not when the reference position depends on lambda.
-         * grompp checks for this.
+         * grompp checks for this.  (verify this is still the case?)
          */
-        enerd->dvdl_lin += dvdl;
+        enerd->dvdl_nonlin[efptRESTRAINT] += dvdlambda[efptRESTRAINT]; /* if just the force constant changes, this is linear,
+                                                                          but we can't be sure w/o additional checking that is
+                                                                          hard to do at this level of code. Otherwise,
+                                                                          the dvdl is not differentiable */
         inc_nrnb(nrnb,eNR_POSRES,top->idef.il[F_POSRES].nr/2);
-    }
+        if ((inputrec->fepvals->n_lambda > 0) && (flags & GMX_FORCE_DHDL))
+        {
+            for(i=0; i<enerd->n_lambda; i++)
+            {
+                lambda_dum = (i==0 ? lambda[efptRESTRAINT] : inputrec->fepvals->all_lambda[efptRESTRAINT][i-1]);
+                v = posres(top->idef.il[F_POSRES].nr,top->idef.il[F_POSRES].iatoms,
+                           top->idef.iparams_posres,
+                           (const rvec*)x,NULL,NULL,
+                           inputrec->ePBC==epbcNONE ? NULL : &pbc,lambda_dum,&dvdl_dum,
+                           fr->rc_scaling,fr->ePBC,fr->posres_com,fr->posres_comB);
+                enerd->enerpart_lambda[i] += v;
+            }
+        }
+   }
 
-    /* Compute the bonded and non-bonded energies and optionally forces */    
+    /* Compute the bonded and non-bonded energies and optionally forces */
     do_force_lowlevel(fplog,step,fr,inputrec,&(top->idef),
                       cr,nrnb,wcycle,mdatoms,&(inputrec->opts),
                       x,hist,f,enerd,fcd,mtop,top,fr->born,
                       &(top->atomtypes),bBornRadii,box,
-                      lambda,graph,&(top->excls),fr->mu_tot,
+                      inputrec->fepvals,lambda,graph,&(top->excls),fr->mu_tot,
                       flags,&cycles_pme);
-    
+
     cycles_force = wallcycle_stop(wcycle,ewcFORCE);
     GMX_BARRIER(cr->mpi_comm_mygroup);
-    
+
     if (ed)
     {
         do_flood(fplog,cr,x,f,ed,box,step);
     }
-       
+
     if (DOMAINDECOMP(cr))
     {
         dd_force_flop_stop(cr->dd,nrnb);
@@ -788,7 +807,7 @@ void do_force(FILE *fplog,t_commrec *cr,
             dd_cycles_add(cr->dd,cycles_force-cycles_pme,ddCyclF);
         }
     }
-    
+
     if (bDoForces)
     {
         if (IR_ELEC_FIELD(*inputrec))
@@ -805,7 +824,7 @@ void do_force(FILE *fplog,t_commrec *cr,
             adress_thermo_force(start,homenr,&(top->cgs),x,fr->f_novirsum,fr,mdatoms,
                                 inputrec->ePBC==epbcNONE ? NULL : &pbc);
         }
-        
+
         /* Communicate the forces */
         if (PAR(cr))
         {
@@ -863,7 +882,7 @@ void do_force(FILE *fplog,t_commrec *cr,
                 wallcycle_stop(wcycle,ewcVSITESPREAD);
             }
         }
-        
+
         if (flags & GMX_FORCE_VIRIAL)
         {
             /* Calculation of the virial must be done after vsites! */
@@ -881,17 +900,17 @@ void do_force(FILE *fplog,t_commrec *cr,
          * which is why we call pull_potential after calc_virial.
          */
         set_pbc(&pbc,inputrec->ePBC,box);
-        dvdl = 0; 
+        dvdlambda[efptRESTRAINT] = 0;
         enerd->term[F_COM_PULL] +=
             pull_potential(inputrec->ePull,inputrec->pull,mdatoms,&pbc,
-                           cr,t,lambda,x,f,vir_force,&dvdl);
+                           cr,t,lambda[efptRESTRAINT],x,f,vir_force,&(dvdlambda[efptRESTRAINT]));
         if (bSepDVDL)
         {
-            fprintf(fplog,sepdvdlformat,"Com pull",enerd->term[F_COM_PULL],dvdl);
+            fprintf(fplog,sepdvdlformat,"Com pull",enerd->term[F_COM_PULL],dvdlambda[efptRESTRAINT]);
         }
-        enerd->dvdl_lin += dvdl;
+        enerd->dvdl_lin[efptRESTRAINT] += dvdlambda[efptRESTRAINT];
     }
-    
+
     /* Add the forces from enforced rotation potentials (if any) */
     if (inputrec->bRot)
     {
@@ -905,19 +924,19 @@ void do_force(FILE *fplog,t_commrec *cr,
         cycles_ppdpme = wallcycle_stop(wcycle,ewcPPDURINGPME);
         dd_cycles_add(cr->dd,cycles_ppdpme,ddCyclPPduringPME);
 
-        /* In case of node-splitting, the PP nodes receive the long-range 
+        /* In case of node-splitting, the PP nodes receive the long-range
          * forces, virial and energy from the PME nodes here.
-         */    
+         */
         wallcycle_start(wcycle,ewcPP_PMEWAITRECVF);
-        dvdl = 0;
-        gmx_pme_receive_f(cr,fr->f_novirsum,fr->vir_el_recip,&e,&dvdl,
+        dvdlambda[efptCOUL] = 0;
+        gmx_pme_receive_f(cr,fr->f_novirsum,fr->vir_el_recip,&e,&dvdlambda[efptCOUL],
                           &cycles_seppme);
         if (bSepDVDL)
         {
-            fprintf(fplog,sepdvdlformat,"PME mesh",e,dvdl);
+            fprintf(fplog,sepdvdlformat,"PME mesh",e,dvdlambda[efptCOUL]);
         }
         enerd->term[F_COUL_RECIP] += e;
-        enerd->dvdl_lin += dvdl;
+        enerd->dvdl_lin[efptCOUL] += dvdlambda[efptCOUL];
         if (wcycle)
         {
             dd_cycles_add(cr->dd,cycles_seppme,ddCyclPME);
@@ -929,7 +948,7 @@ void do_force(FILE *fplog,t_commrec *cr,
     {
         if (vsite)
         {
-            /* Spread the mesh force on virtual sites to the other particles... 
+            /* Spread the mesh force on virtual sites to the other particles...
              * This is parallellized. MPI communication is performed
              * if the constructing atoms aren't local.
              */
@@ -962,10 +981,10 @@ void do_force(FILE *fplog,t_commrec *cr,
             }
         }
     }
-    
+
     /* Sum the potential energy terms from group contributions */
     sum_epot(&(inputrec->opts),enerd);
-    
+
     if (fr->print_force >= 0 && bDoForces)
     {
         print_large_forces(stderr,mdatoms,cr,step,fr->print_force,x,f);
@@ -981,14 +1000,14 @@ void do_constrain_first(FILE *fplog,gmx_constr_t constr,
     int    i,m,start,end;
     gmx_large_int_t step;
     real   dt=ir->delta_t;
-    real   dvdlambda;
+    real   dvdl_dum;
     rvec   *savex;
-    
+
     snew(savex,state->natoms);
 
     start = md->start;
     end   = md->homenr + start;
-    
+
     if (debug)
         fprintf(debug,"vcm: start=%d, homenr=%d, end=%d\n",
                 start,md->homenr,end);
@@ -1000,15 +1019,15 @@ void do_constrain_first(FILE *fplog,gmx_constr_t constr,
         fprintf(fplog,"\nConstraining the starting coordinates (step %s)\n",
                 gmx_step_str(step,buf));
     }
-    dvdlambda = 0;
-    
+    dvdl_dum = 0;
+
     /* constrain the current position */
     constrain(NULL,TRUE,FALSE,constr,&(top->idef),
               ir,NULL,cr,step,0,md,
               state->x,state->x,NULL,
-              state->box,state->lambda,&dvdlambda,
+              state->box,state->lambda[efptBONDED],&dvdl_dum,
               NULL,NULL,nrnb,econqCoord,ir->epc==epcMTTK,state->veta,state->veta);
-    if (EI_VV(ir->eI)) 
+    if (EI_VV(ir->eI))
     {
         /* constrain the inital velocity, and save it */
         /* also may be useful if we need the ekin from the halfstep for velocity verlet */
@@ -1016,15 +1035,15 @@ void do_constrain_first(FILE *fplog,gmx_constr_t constr,
         constrain(NULL,TRUE,FALSE,constr,&(top->idef),
                   ir,NULL,cr,step,0,md,
                   state->x,state->v,state->v,
-                  state->box,state->lambda,&dvdlambda,
+                  state->box,state->lambda[efptBONDED],&dvdl_dum,
                   NULL,NULL,nrnb,econqVeloc,ir->epc==epcMTTK,state->veta,state->veta);
     }
     /* constrain the inital velocities at t-dt/2 */
     if (EI_STATE_VELOCITY(ir->eI) && ir->eI!=eiVV)
     {
-        for(i=start; (i<end); i++) 
+        for(i=start; (i<end); i++)
         {
-            for(m=0; (m<DIM); m++) 
+            for(m=0; (m<DIM); m++)
             {
                 /* Reverse the velocity */
                 state->v[i][m] = -state->v[i][m];
@@ -1032,8 +1051,8 @@ void do_constrain_first(FILE *fplog,gmx_constr_t constr,
                 savex[i][m] = state->x[i][m] + dt*state->v[i][m];
             }
         }
-    /* Shake the positions at t=-dt with the positions at t=0                        
-     * as reference coordinates.                                                     
+    /* Shake the positions at t=-dt with the positions at t=0
+     * as reference coordinates.
          */
         if (fplog)
         {
@@ -1041,13 +1060,13 @@ void do_constrain_first(FILE *fplog,gmx_constr_t constr,
             fprintf(fplog,"\nConstraining the coordinates at t0-dt (step %s)\n",
                     gmx_step_str(step,buf));
         }
-        dvdlambda = 0;
+        dvdl_dum = 0;
         constrain(NULL,TRUE,FALSE,constr,&(top->idef),
                   ir,NULL,cr,step,-1,md,
                   state->x,savex,NULL,
-                  state->box,state->lambda,&dvdlambda,
+                  state->box,state->lambda[efptBONDED],&dvdl_dum,
                   state->v,NULL,nrnb,econqCoord,ir->epc==epcMTTK,state->veta,state->veta);
-        
+
         for(i=start; i<end; i++) {
             for(m=0; m<DIM; m++) {
                 /* Re-reverse the velocities */
@@ -1055,7 +1074,6 @@ void do_constrain_first(FILE *fplog,gmx_constr_t constr,
             }
         }
     }
-    
     sfree(savex);
 }
 
@@ -1065,7 +1083,7 @@ void calc_enervirdiff(FILE *fplog,int eDispCorr,t_forcerec *fr)
   double r0,r1,r,rc3,rc9,ea,eb,ec,pa,pb,pc,pd;
   double invscale,invscale2,invscale3;
   int    ri0,ri1,ri,i,offstart,offset;
-  real   scale,*vdwtab; 
+  real   scale,*vdwtab;
 
   fr->enershiftsix = 0;
   fr->enershifttwelve = 0;
@@ -1108,8 +1126,8 @@ void calc_enervirdiff(FILE *fplog,int eDispCorr,t_forcerec *fr)
        */
       eners[0] += 4.0*M_PI*fr->enershiftsix*rc3/3.0;
       eners[1] += 4.0*M_PI*fr->enershifttwelve*rc3/3.0;
-      
-      invscale = 1.0/(scale);  
+
+      invscale = 1.0/(scale);
       invscale2 = invscale*invscale;
       invscale3 = invscale*invscale2;
 
@@ -1122,7 +1140,7 @@ void calc_enervirdiff(FILE *fplog,int eDispCorr,t_forcerec *fr)
        switched function.  We perform both the pressure and energy
        loops at the same time for simplicity, as the computational
        cost is low. */
-      
+
       for (i=0;i<2;i++) {
         enersum = 0.0; virsum = 0.0;
         if (i==0)
@@ -1134,12 +1152,12 @@ void calc_enervirdiff(FILE *fplog,int eDispCorr,t_forcerec *fr)
           ea = invscale3;
           eb = 2.0*invscale2*r;
           ec = invscale*r*r;
-          
+
           pa = invscale3;
           pb = 3.0*invscale2*r;
           pc = 3.0*invscale*r*r;
           pd = r*r*r;
-          
+
           /* this "8" is from the packing in the vdwtab array - perhaps
            should be #define'ed? */
           offset = 8*ri + offstart;
@@ -1147,15 +1165,15 @@ void calc_enervirdiff(FILE *fplog,int eDispCorr,t_forcerec *fr)
           f = vdwtab[offset+1];
           g = vdwtab[offset+2];
           h = vdwtab[offset+3];
-         
+
           enersum += y0*(ea/3 + eb/2 + ec) + f*(ea/4 + eb/3 + ec/2)+
-            g*(ea/5 + eb/4 + ec/3) + h*(ea/6 + eb/5 + ec/4);  
-          virsum  +=  f*(pa/4 + pb/3 + pc/2 + pd) + 
+            g*(ea/5 + eb/4 + ec/3) + h*(ea/6 + eb/5 + ec/4);
+          virsum  +=  f*(pa/4 + pb/3 + pc/2 + pd) +
             2*g*(pa/5 + pb/4 + pc/3 + pd/2) + 3*h*(pa/6 + pb/5 + pc/4 + pd/3);
-         
+
         }
         enersum *= 4.0*M_PI;
-        virsum  *= 4.0*M_PI; 
+        virsum  *= 4.0*M_PI;
         eners[i] -= enersum;
         virs[i]  -= virsum;
       }
@@ -1165,7 +1183,7 @@ void calc_enervirdiff(FILE *fplog,int eDispCorr,t_forcerec *fr)
       eners[1] +=  4.0*M_PI/(9.0*rc9);
       virs[0]  +=  8.0*M_PI/rc3;
       virs[1]  += -16.0*M_PI/(3.0*rc9);
-    } 
+    }
     else if ((fr->vdwtype == evdwCUT) || (fr->vdwtype == evdwUSER)) {
       if (fr->vdwtype == evdwUSER && fplog)
        fprintf(fplog,
@@ -1197,62 +1215,62 @@ void calc_dispcorr(FILE *fplog,t_inputrec *ir,t_forcerec *fr,
     gmx_bool bCorrAll,bCorrPres;
     real dvdlambda,invvol,dens,ninter,avcsix,avctwelve,enerdiff,svir=0,spres=0;
     int  m;
-    
+
     *prescorr = 0;
     *enercorr = 0;
     *dvdlcorr = 0;
-    
+
     clear_mat(virial);
     clear_mat(pres);
-    
+
     if (ir->eDispCorr != edispcNO) {
         bCorrAll  = (ir->eDispCorr == edispcAllEner ||
                      ir->eDispCorr == edispcAllEnerPres);
         bCorrPres = (ir->eDispCorr == edispcEnerPres ||
                      ir->eDispCorr == edispcAllEnerPres);
-        
+
         invvol = 1/det(box);
-        if (fr->n_tpi) 
+        if (fr->n_tpi)
         {
             /* Only correct for the interactions with the inserted molecule */
             dens = (natoms - fr->n_tpi)*invvol;
             ninter = fr->n_tpi;
-        } 
-        else 
+        }
+        else
         {
             dens = natoms*invvol;
             ninter = 0.5*natoms;
         }
-        
-        if (ir->efep == efepNO) 
+
+        if (ir->efep == efepNO)
         {
             avcsix    = fr->avcsix[0];
             avctwelve = fr->avctwelve[0];
-        } 
-        else 
+        }
+        else
         {
             avcsix    = (1 - lambda)*fr->avcsix[0]    + lambda*fr->avcsix[1];
             avctwelve = (1 - lambda)*fr->avctwelve[0] + lambda*fr->avctwelve[1];
         }
-        
+
         enerdiff = ninter*(dens*fr->enerdiffsix - fr->enershiftsix);
         *enercorr += avcsix*enerdiff;
         dvdlambda = 0.0;
-        if (ir->efep != efepNO) 
+        if (ir->efep != efepNO)
         {
             dvdlambda += (fr->avcsix[1] - fr->avcsix[0])*enerdiff;
         }
-        if (bCorrAll) 
+        if (bCorrAll)
         {
             enerdiff = ninter*(dens*fr->enerdifftwelve - fr->enershifttwelve);
             *enercorr += avctwelve*enerdiff;
-            if (fr->efep != efepNO) 
+            if (fr->efep != efepNO)
             {
                 dvdlambda += (fr->avctwelve[1] - fr->avctwelve[0])*enerdiff;
             }
         }
-        
-        if (bCorrPres) 
+
+        if (bCorrPres)
         {
             svir = ninter*dens*avcsix*fr->virdiffsix/3.0;
             if (ir->eDispCorr == edispcAllEnerPres)
@@ -1261,14 +1279,14 @@ void calc_dispcorr(FILE *fplog,t_inputrec *ir,t_forcerec *fr,
             }
             /* The factor 2 is because of the Gromacs virial definition */
             spres = -2.0*invvol*svir*PRESFAC;
-            
+
             for(m=0; m<DIM; m++) {
                 virial[m][m] += svir;
                 pres[m][m] += spres;
             }
             *prescorr += spres;
         }
-        
+
         /* Can't currently control when it prints, for now, just print when degugging */
         if (debug)
         {
@@ -1276,7 +1294,7 @@ void calc_dispcorr(FILE *fplog,t_inputrec *ir,t_forcerec *fr,
                 fprintf(debug,"Long Range LJ corr.: <C6> %10.4e, <C12> %10.4e\n",
                         avcsix,avctwelve);
             }
-            if (bCorrPres) 
+            if (bCorrPres)
             {
                 fprintf(debug,
                         "Long Range LJ corr.: Epot %10g, Pres: %10g, Vir: %10g\n",
@@ -1287,13 +1305,13 @@ void calc_dispcorr(FILE *fplog,t_inputrec *ir,t_forcerec *fr,
                 fprintf(debug,"Long Range LJ corr.: Epot %10g\n",*enercorr);
             }
         }
-        
+
         if (fr->bSepDVDL && do_per_step(step,ir->nstlog))
         {
             fprintf(fplog,sepdvdlformat,"Dispersion correction",
                     *enercorr,dvdlambda);
         }
-        if (fr->efep != efepNO) 
+        if (fr->efep != efepNO)
         {
             *dvdlcorr += dvdlambda;
         }
@@ -1339,7 +1357,7 @@ static void low_do_pbc_mtop(FILE *fplog,int ePBC,matrix box,
   as = 0;
   for(mb=0; mb<mtop->nmolblock; mb++) {
     molb = &mtop->molblock[mb];
-    if (molb->natoms_mol == 1 || 
+    if (molb->natoms_mol == 1 ||
        (!bFirst && mtop->moltype[molb->type].cgs.nr == 1)) {
       /* Just one atom or charge group in the molecule, no PBC required */
       as += molb->nmol*molb->natoms_mol;
@@ -1347,16 +1365,16 @@ static void low_do_pbc_mtop(FILE *fplog,int ePBC,matrix box,
       /* Pass NULL iso fplog to avoid graph prints for each molecule type */
       mk_graph_ilist(NULL,mtop->moltype[molb->type].ilist,
                     0,molb->natoms_mol,FALSE,FALSE,graph);
-      
+
       for(mol=0; mol<molb->nmol; mol++) {
        mk_mshift(fplog,graph,ePBC,box,x+as);
-       
+
        shift_self(graph,box,x+as);
        /* The molecule is whole now.
         * We don't need the second mk_mshift call as in do_pbc_first,
         * since we no longer need this graph.
         */
-       
+
        as += molb->natoms_mol;
       }
       done_graph(graph);
@@ -1397,11 +1415,11 @@ void finish_run(FILE *fplog,t_commrec *cr,const char *confout,
 #ifdef GMX_MPI
     MPI_Reduce(nrnb->n,nrnb_tot->n,eNRNB,MPI_DOUBLE,MPI_SUM,
                MASTERRANK(cr),cr->mpi_comm_mysim);
-#endif  
+#endif
   } else {
     nrnb_tot = nrnb;
   }
-    
+
   if (SIMMASTER(cr)) {
     print_flop(fplog,nrnb_tot,&nbfs,&mflop);
     if (cr->nnodes > 1) {
@@ -1438,7 +1456,7 @@ void finish_run(FILE *fplog,t_commrec *cr,const char *confout,
                      cr->mpi_comm_mysim);
         }
     }
-#endif  
+#endif
 
   if (SIMMASTER(cr)) {
     wallcycle_print(fplog,cr->nnodes,cr->npmenodes,runtime->realtime,
@@ -1449,7 +1467,7 @@ void finish_run(FILE *fplog,t_commrec *cr,const char *confout,
     } else {
       delta_t = 0;
     }
-    
+
     if (fplog) {
         print_perf(fplog,runtime->proctime,runtime->realtime,
                    cr->nnodes-cr->npmenodes,
@@ -1480,10 +1498,73 @@ void finish_run(FILE *fplog,t_commrec *cr,const char *confout,
   }
 }
 
+extern void initialize_lambdas(FILE *fplog,t_inputrec *ir,int *fep_state,real *lambda,double *lam0)
+{
+    /* this function works, but could probably use a logic rewrite to keep all the different
+       types of efep straight. */
+
+    int i;
+    t_lambda *fep = ir->fepvals;
+
+    if ((ir->efep==efepNO) && (ir->bSimTemp == FALSE)) {
+        for (i=0;i<efptNR;i++)  {
+            lambda[i] = 0.0;
+            if (lam0)
+            {
+                lam0[i] = 0.0;
+            }
+        }
+        return;
+    } else {
+        *fep_state = fep->init_fep_state; /* this might overwrite the checkpoint
+                                             if checkpoint is set -- a kludge is in for now
+                                             to prevent this.*/
+        for (i=0;i<efptNR;i++)
+        {
+            /* overwrite lambda state with init_lambda for now for backwards compatibility */
+            if (fep->init_lambda>=0) /* if it's -1, it was never initializd */
+            {
+                lambda[i] = fep->init_lambda;
+                if (lam0) {
+                    lam0[i] = lambda[i];
+                }
+            }
+            else
+            {
+                lambda[i] = fep->all_lambda[i][*fep_state];
+                if (lam0) {
+                    lam0[i] = lambda[i];
+                }
+            }
+        }
+        if (ir->bSimTemp) {
+            /* need to rescale control temperatures to match current state */
+            for (i=0;i<ir->opts.ngtc;i++) {
+                if (ir->opts.ref_t[i] > 0) {
+                    ir->opts.ref_t[i] = ir->simtempvals->temperatures[*fep_state];
+                }
+            }
+        }
+    }
+
+    /* Send to the log the information on the current lambdas */
+    if (fplog != NULL)
+    {
+        fprintf(fplog,"Initial vector of lambda components:[ ");
+        for (i=0;i<efptNR;i++)
+        {
+            fprintf(fplog,"%10.4f ",lambda[i]);
+        }
+        fprintf(fplog,"]\n");
+    }
+    return;
+}
+
+
 void init_md(FILE *fplog,
              t_commrec *cr,t_inputrec *ir,const output_env_t oenv,
              double *t,double *t0,
-             real *lambda,double *lam0,
+             real *lambda, int *fep_state, double *lam0,
              t_nrnb *nrnb,gmx_mtop_t *mtop,
              gmx_update_t *upd,
              int nfile,const t_filenm fnm[],
@@ -1493,18 +1574,9 @@ void init_md(FILE *fplog,
 {
     int  i,j,n;
     real tmpt,mod;
-       
+
     /* Initial values */
     *t = *t0       = ir->init_t;
-    if (ir->efep != efepNO)
-    {
-        *lam0 = ir->init_lambda;
-        *lambda = *lam0 + ir->init_step*ir->delta_lambda;
-    }
-    else
-    {
-        *lambda = *lam0   = 0.0;
-    } 
 
     *bSimAnn=FALSE;
     for(i=0;i<ir->opts.ngtc;i++)
@@ -1519,17 +1591,21 @@ void init_md(FILE *fplog,
     {
         update_annealing_target_temp(&(ir->opts),ir->init_t);
     }
-    
+
+    /* Initialize lambda variables */
+    initialize_lambdas(fplog,ir,fep_state,lambda,lam0);
+
     if (upd)
     {
         *upd = init_update(fplog,ir);
     }
-    
+
+
     if (vcm != NULL)
     {
         *vcm = init_vcm(fplog,&mtop->groups,ir);
     }
-    
+
     if (EI_DYNAMICS(ir->eI) && !(Flags & MD_APPENDFILES))
     {
         if (ir->etc == etcBERENDSEN)
@@ -1541,9 +1617,9 @@ void init_md(FILE *fplog,
             please_cite(fplog,"Bussi2007a");
         }
     }
-    
+
     init_nrnb(nrnb);
-    
+
     if (nfile != -1)
     {
         *outf = init_mdoutf(nfile,fnm,Flags,cr,ir,oenv);
@@ -1551,17 +1627,20 @@ void init_md(FILE *fplog,
         *mdebin = init_mdebin((Flags & MD_APPENDFILES) ? NULL : (*outf)->fp_ene,
                               mtop,ir, (*outf)->fp_dhdl);
     }
-    
+
     if (ir->bAdress)
     {
       please_cite(fplog,"Fritsch12");
       please_cite(fplog,"Junghans10");
     }
-    /* Initiate variables */  
+    /* Initiate variables */
     clear_mat(force_vir);
     clear_mat(shake_vir);
     clear_rvec(mu_tot);
-    
+
     debug_gmx();
 }
 
+
+
+
index d84ab3f2b61a1fee3171b269700d07ee840edfb6..b7343eb93c929d2cb54b598542dfdc396bb8afc4 100644 (file)
@@ -265,8 +265,8 @@ void global_stat(FILE *fplog,gmx_global_stat_t gs,
           where();
           if (inputrec->efep != efepNO) 
           {
-              idvdll  = add_bind(rb,1,&enerd->dvdl_lin);
-              idvdlnl = add_bind(rb,1,&enerd->dvdl_nonlin);
+              idvdll  = add_bind(rb,efptNR,enerd->dvdl_lin);
+              idvdlnl = add_bind(rb,efptNR,enerd->dvdl_nonlin);
               if (enerd->n_lambda > 0) 
               {
                   iepl = add_bind(rb,enerd->n_lambda,enerd->enerpart_lambda);
@@ -367,8 +367,8 @@ void global_stat(FILE *fplog,gmx_global_stat_t gs,
           }
           if (inputrec->efep != efepNO) 
           {
-              extract_bind(rb,idvdll ,1,&enerd->dvdl_lin);
-              extract_bind(rb,idvdlnl,1,&enerd->dvdl_nonlin);
+              extract_bind(rb,idvdll ,efptNR,enerd->dvdl_lin);
+              extract_bind(rb,idvdlnl,efptNR,enerd->dvdl_nonlin);
               if (enerd->n_lambda > 0) 
               {
                   extract_bind(rb,iepl,enerd->n_lambda,enerd->enerpart_lambda);
@@ -385,8 +385,6 @@ void global_stat(FILE *fplog,gmx_global_stat_t gs,
           where();
 
           filter_enerdterm(copyenerd,FALSE,enerd->term,bTemp,bPres,bEner);    
-/* Small hack for temp only - not entirely clear if still needed?*/
-          /* enerd->term[F_TEMP] /= (cr->nnodes - cr->npmenodes); */
       }
   }
 
@@ -449,6 +447,8 @@ gmx_mdoutf_t *init_mdoutf(int nfile,const t_filenm fnm[],int mdrun_flags,
     of->fp_field = NULL;
     
     of->eIntegrator     = ir->eI;
+    of->bExpanded       = ir->bExpanded;
+    of->elamstats       = ir->expandedvals->elamstats;
     of->simulation_part = ir->simulation_part;
 
     if (MASTER(cr))
@@ -483,8 +483,8 @@ gmx_mdoutf_t *init_mdoutf(int nfile,const t_filenm fnm[],int mdrun_flags,
         }
         of->fn_cpt = opt2fn("-cpo",nfile,fnm);
         
-        if (ir->efep != efepNO && ir->nstdhdl > 0 &&
-            (ir->separate_dhdl_file == sepdhdlfileYES ) && 
+        if ((ir->efep != efepNO || ir->bSimTemp) && ir->fepvals->nstdhdl > 0 &&
+            (ir->fepvals->separate_dhdl_file == esepdhdlfileYES ) &&
             EI_DYNAMICS(ir->eI))
         {
             if (bAppendFiles)
@@ -650,13 +650,13 @@ void write_traj(FILE *fplog,t_commrec *cr,
          if (mdof_flags & MDOF_CPT)
          {
              write_checkpoint(of->fn_cpt,of->bKeepAndNumCPT,
-                              fplog,cr,of->eIntegrator,
-                              of->simulation_part,step,t,state_global);
+                              fplog,cr,of->eIntegrator,of->simulation_part,
+                              of->bExpanded,of->elamstats,step,t,state_global);
          }
 
          if (mdof_flags & (MDOF_X | MDOF_V | MDOF_F))
          {
-            fwrite_trn(of->fp_trn,step,t,state_local->lambda,
+            fwrite_trn(of->fp_trn,step,t,state_local->lambda[efptFEP],
                        state_local->box,top_global->natoms,
                        (mdof_flags & MDOF_X) ? state_global->x : NULL,
                        (mdof_flags & MDOF_V) ? global_v : NULL,
index 06262ef1bcd89514434a4e9a4f8d35d35d4b9717..c3c759413b597ec0e6a0eaa43ecca1fc0cb74012 100644 (file)
@@ -233,8 +233,8 @@ real sum_ekin(t_grpopts *opts,gmx_ekindata_t *ekind,real *dekindlambda,
                     msmul(tcstat->ekinf,tcstat->ekinscalef_nhc,tcstat->ekinf);
                 }
             } 
-            else 
-                
+            else
+
             {
                 /* Calculate the full step Ekin as the average of the half steps */
                 for(j=0; (j<DIM); j++)
index 9fcd6c6ee4ffecf934c1e4c755435954b9dab455..96d56632d36a924edc9b997a3c1e04c9204b5534 100644 (file)
@@ -126,7 +126,7 @@ double do_tpi(FILE *fplog,t_commrec *cr,
               t_nrnb *nrnb,gmx_wallcycle_t wcycle,
               gmx_edsam_t ed,
               t_forcerec *fr,
-              int repl_ex_nst,int repl_ex_seed,
+              int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
               gmx_membed_t membed,
               real cpt_period,real max_hours,
               const char *deviceOptions,
@@ -235,10 +235,10 @@ double do_tpi(FILE *fplog,t_commrec *cr,
     sscanf(dump_pdb,"%lf",&dump_ener);
 
   atoms2md(top_global,inputrec,0,NULL,0,top_global->natoms,mdatoms);
-  update_mdatoms(mdatoms,inputrec->init_lambda);
+  update_mdatoms(mdatoms,inputrec->fepvals->init_lambda);
 
   snew(enerd,1);
-  init_enerdata(groups->grps[egcENER].nr,inputrec->n_flambda,enerd);
+  init_enerdata(groups->grps[egcENER].nr,inputrec->fepvals->n_lambda,enerd);
   snew(f,top_global->natoms);
 
   /* Print to log file  */
@@ -568,7 +568,8 @@ double do_tpi(FILE *fplog,t_commrec *cr,
                          step,nrnb,wcycle,top,top_global,&top_global->groups,
                          rerun_fr.box,state->x,&state->hist,
                          f,force_vir,mdatoms,enerd,fcd,
-                         lambda,NULL,fr,NULL,mu_tot,t,NULL,NULL,FALSE,
+                         state->lambda,
+                         NULL,fr,NULL,mu_tot,t,NULL,NULL,FALSE,
                          GMX_FORCE_NONBONDED |
                          (bNS ? GMX_FORCE_NS | GMX_FORCE_DOLR : 0) |
                          (bStateChanged ? GMX_FORCE_STATECHANGED : 0)); 
@@ -577,13 +578,14 @@ double do_tpi(FILE *fplog,t_commrec *cr,
                 bNS = FALSE;
                 
                 /* Calculate long range corrections to pressure and energy */
-                calc_dispcorr(fplog,inputrec,fr,step,top_global->natoms,rerun_fr.box,
+                calc_dispcorr(fplog,inputrec,fr,step,top_global->natoms,
+                              rerun_fr.box,
                               lambda,pres,vir,&prescorr,&enercorr,&dvdlcorr);
                 /* figure out how to rearrange the next 4 lines MRS 8/4/2009 */
                 enerd->term[F_DISPCORR] = enercorr;
                 enerd->term[F_EPOT] += enercorr;
                 enerd->term[F_PRES] += prescorr;
-                enerd->term[F_DVDL] += dvdlcorr;
+                enerd->term[F_DVDL_VDW] += dvdlcorr;
 
                 epot = enerd->term[F_EPOT];
                 bEnergyOutOfBounds = FALSE;
index 09c501cac86c1d6bfae6f82b521186685ee9c218..1ca0b6148bec1dc35a52208888b4abce3d270f25 100644 (file)
@@ -1,12 +1,12 @@
 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
  *
- * 
+ *
  *                This source code is part of
- * 
+ *
  *                 G   R   O   M   A   C   S
- * 
+ *
  *          GROningen MAchine for Chemical Simulations
- * 
+ *
  *                        VERSION 3.2.0
  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * If you want to redistribute modifications, please consider that
  * scientific software is very special. Version control is crucial -
  * bugs must be traceable. We will be happy to consider code for
  * inclusion in the official distribution, but derived work must not
  * be called official GROMACS. Details are found in the README & COPYING
  * files - if they are missing, get the official version at www.gromacs.org.
- * 
+ *
  * To help us fund GROMACS development, we humbly ask that you cite
  * the papers on the package - you can find them in the top README file.
- * 
+ *
  * For more info, check our website at http://www.gromacs.org
- * 
+ *
  * And Hey:
  * GROwing Monsters And Cloning Shrimps
  */
@@ -97,13 +97,23 @@ typedef struct {
   gmx_sd_sigma_t *sdsig;
   rvec *sd_V;
   int  sd_V_nalloc;
+  /* andersen temperature control stuff */
+  gmx_bool *randomize_group;
+  real *boltzfac;
 } gmx_stochd_t;
 
 typedef struct gmx_update
 {
     gmx_stochd_t *sd;
+    /* xprime for constraint algorithms */
     rvec *xp;
     int  xp_nalloc;
+
+    /* variable size arrays for andersen */
+    gmx_bool *randatom;
+    int *randatom_list;
+    gmx_bool randatom_list_init;
+
     /* Variables for the deform algorithm */
     gmx_large_int_t deformref_step;
     matrix     deformref_box;
@@ -126,21 +136,21 @@ static void do_update_md(int start,int nrend,double dt,
   real   lg,vxi=0,u;
   int    n,d;
 
-  if (bNH || bPR) 
+  if (bNH || bPR)
   {
-      /* Update with coupling to extended ensembles, used for                     
-       * Nose-Hoover and Parrinello-Rahman coupling                               
-       * Nose-Hoover uses the reversible leap-frog integrator from                
-       * Holian et al. Phys Rev E 52(3) : 2338, 1995                              
+      /* Update with coupling to extended ensembles, used for
+       * Nose-Hoover and Parrinello-Rahman coupling
+       * Nose-Hoover uses the reversible leap-frog integrator from
+       * Holian et al. Phys Rev E 52(3) : 2338, 1995
        */
-      for(n=start; n<nrend; n++) 
+      for(n=start; n<nrend; n++)
       {
           imass = invmass[n];
-          if (cFREEZE) 
+          if (cFREEZE)
           {
               gf   = cFREEZE[n];
           }
-          if (cACC) 
+          if (cACC)
           {
               ga   = cACC[n];
           }
@@ -153,33 +163,33 @@ static void do_update_md(int start,int nrend,double dt,
               vxi   = nh_vxi[gt];
           }
           rvec_sub(v[n],gstat[ga].u,vrel);
-          
-          for(d=0; d<DIM; d++) 
+
+          for(d=0; d<DIM; d++)
           {
-              if((ptype[n] != eptVSite) && (ptype[n] != eptShell) && !nFreeze[gf][d]) 
+              if((ptype[n] != eptVSite) && (ptype[n] != eptShell) && !nFreeze[gf][d])
               {
                   vnrel = (lg*vrel[d] + dt*(imass*f[n][d] - 0.5*vxi*vrel[d]
-                                            - iprod(M[d],vrel)))/(1 + 0.5*vxi*dt);  
+                                            - iprod(M[d],vrel)))/(1 + 0.5*vxi*dt);
                   /* do not scale the mean velocities u */
-                  vn             = gstat[ga].u[d] + accel[ga][d]*dt + vnrel; 
+                  vn             = gstat[ga].u[d] + accel[ga][d]*dt + vnrel;
                   v[n][d]        = vn;
                   xprime[n][d]   = x[n][d]+vn*dt;
-              } 
-              else 
+              }
+              else
               {
                   v[n][d]        = 0.0;
                   xprime[n][d]   = x[n][d];
               }
           }
       }
-  } 
-  else 
+  }
+  else
   {
       /* Classic version of update, used with berendsen coupling */
-      for(n=start; n<nrend; n++) 
+      for(n=start; n<nrend; n++)
       {
           w_dt = invmass[n]*dt;
-          if (cFREEZE) 
+          if (cFREEZE)
           {
               gf   = cFREEZE[n];
           }
@@ -187,27 +197,27 @@ static void do_update_md(int start,int nrend,double dt,
           {
               ga   = cACC[n];
           }
-          if (cTC) 
+          if (cTC)
           {
               gt   = cTC[n];
           }
           lg   = tcstat[gt].lambda;
-          
-          for(d=0; d<DIM; d++) 
+
+          for(d=0; d<DIM; d++)
           {
               vn             = v[n][d];
-              if((ptype[n] != eptVSite) && (ptype[n] != eptShell) && !nFreeze[gf][d]) 
+              if((ptype[n] != eptVSite) && (ptype[n] != eptShell) && !nFreeze[gf][d])
               {
                   vv             = lg*vn + f[n][d]*w_dt;
-                  
+
                   /* do not scale the mean velocities u */
                   u              = gstat[ga].u[d];
                   va             = vv + accel[ga][d]*dt;
                   vb             = va + (1.0-lg)*u;
                   v[n][d]        = vb;
                   xprime[n][d]   = x[n][d]+vb*dt;
-              } 
-              else 
+              }
+              else
               {
                   v[n][d]        = 0.0;
                   xprime[n][d]   = x[n][d];
@@ -220,30 +230,29 @@ static void do_update_md(int start,int nrend,double dt,
 static void do_update_vv_vel(int start,int nrend,double dt,
                              t_grp_tcstat *tcstat,t_grp_acc *gstat,
                              rvec accel[],ivec nFreeze[],real invmass[],
-                             unsigned short ptype[],
-                             unsigned short cFREEZE[],unsigned short cACC[],
-                             rvec v[],rvec f[],
+                             unsigned short ptype[],unsigned short cFREEZE[],
+                             unsigned short cACC[],rvec v[],rvec f[],
                              gmx_bool bExtended, real veta, real alpha)
 {
     double imass,w_dt;
-    int    gf=0,ga=0,gt=0;
+    int    gf=0,ga=0;
     rvec   vrel;
     real   u,vn,vv,va,vb,vnrel;
     int    n,d;
     double g,mv1,mv2;
-    
+
     if (bExtended)
     {
         g        = 0.25*dt*veta*alpha;
         mv1      = exp(-g);
         mv2      = series_sinhx(g);
     }
-    else 
+    else
     {
         mv1      = 1.0;
         mv2      = 1.0;
     }
-    for(n=start; n<nrend; n++) 
+    for(n=start; n<nrend; n++)
     {
         w_dt = invmass[n]*dt;
         if (cFREEZE)
@@ -254,14 +263,14 @@ static void do_update_vv_vel(int start,int nrend,double dt,
         {
             ga   = cACC[n];
         }
-        
-        for(d=0; d<DIM; d++) 
+
+        for(d=0; d<DIM; d++)
         {
-            if((ptype[n] != eptVSite) && (ptype[n] != eptShell) && !nFreeze[gf][d]) 
+            if((ptype[n] != eptVSite) && (ptype[n] != eptShell) && !nFreeze[gf][d])
             {
                 v[n][d]             = mv1*(mv1*v[n][d] + 0.5*(w_dt*mv2*f[n][d]))+0.5*accel[ga][d]*dt;
-            } 
-            else 
+            }
+            else
             {
                 v[n][d]        = 0.0;
             }
@@ -272,8 +281,7 @@ static void do_update_vv_vel(int start,int nrend,double dt,
 static void do_update_vv_pos(int start,int nrend,double dt,
                              t_grp_tcstat *tcstat,t_grp_acc *gstat,
                              rvec accel[],ivec nFreeze[],real invmass[],
-                             unsigned short ptype[],
-                             unsigned short cFREEZE[],
+                             unsigned short ptype[],unsigned short cFREEZE[],
                              rvec x[],rvec xprime[],rvec v[],
                              rvec f[],gmx_bool bExtended, real veta, real alpha)
 {
@@ -282,30 +290,31 @@ static void do_update_vv_pos(int start,int nrend,double dt,
   int    n,d;
   double g,mr1,mr2;
 
-  if (bExtended) {
+  /* Would it make more sense if Parrinello-Rahman was put here? */
+  if (bExtended)
+  {
       g        = 0.5*dt*veta;
       mr1      = exp(g);
       mr2      = series_sinhx(g);
-  }
-  else 
-  {
+  } else {
       mr1      = 1.0;
       mr2      = 1.0;
   }
-  
+
   for(n=start; n<nrend; n++) {
+
       if (cFREEZE)
       {
           gf   = cFREEZE[n];
       }
-      
-      for(d=0; d<DIM; d++) 
+
+      for(d=0; d<DIM; d++)
       {
-          if ((ptype[n] != eptVSite) && (ptype[n] != eptShell) && !nFreeze[gf][d]) 
+          if ((ptype[n] != eptVSite) && (ptype[n] != eptShell) && !nFreeze[gf][d])
           {
               xprime[n][d]   = mr1*(mr1*x[n][d]+mr2*dt*v[n][d]);
-          } 
-          else 
+          }
+          else
           {
               xprime[n][d]   = x[n][d];
           }
@@ -328,87 +337,87 @@ static void do_update_visc(int start,int nrend,double dt,
     real   fac,cosz;
     rvec   vrel;
     int    n,d;
-    
+
     fac = 2*M_PI/(box[ZZ][ZZ]);
-    
+
     if (bNH || bPR) {
         /* Update with coupling to extended ensembles, used for
          * Nose-Hoover and Parrinello-Rahman coupling
          */
         for(n=start; n<nrend; n++) {
             imass = invmass[n];
-            if (cTC) 
+            if (cTC)
             {
                 gt   = cTC[n];
             }
             lg   = tcstat[gt].lambda;
             cosz = cos(fac*x[n][ZZ]);
-            
+
             copy_rvec(v[n],vrel);
-            
+
             vc            = cosz*vcos;
             vrel[XX]     -= vc;
-            if (bNH) 
+            if (bNH)
             {
                 vxi        = nh_vxi[gt];
             }
-            for(d=0; d<DIM; d++) 
+            for(d=0; d<DIM; d++)
             {
                 vn             = v[n][d];
-                
-                if((ptype[n] != eptVSite) && (ptype[n] != eptShell)) 
+
+                if((ptype[n] != eptVSite) && (ptype[n] != eptShell))
                 {
                     vn  = (lg*vrel[d] + dt*(imass*f[n][d] - 0.5*vxi*vrel[d]
                                             - iprod(M[d],vrel)))/(1 + 0.5*vxi*dt);
-                    if(d == XX) 
+                    if(d == XX)
                     {
                         vn += vc + dt*cosz*cos_accel;
                     }
                     v[n][d]        = vn;
                     xprime[n][d]   = x[n][d]+vn*dt;
-                } 
-                else 
+                }
+                else
                 {
                     xprime[n][d]   = x[n][d];
                 }
             }
         }
-    } 
-    else 
+    }
+    else
     {
         /* Classic version of update, used with berendsen coupling */
-        for(n=start; n<nrend; n++) 
+        for(n=start; n<nrend; n++)
         {
             w_dt = invmass[n]*dt;
-            if (cTC) 
+            if (cTC)
             {
                 gt   = cTC[n];
             }
             lg   = tcstat[gt].lambda;
             cosz = cos(fac*x[n][ZZ]);
-            
-            for(d=0; d<DIM; d++) 
+
+            for(d=0; d<DIM; d++)
             {
                 vn             = v[n][d];
-                
-                if((ptype[n] != eptVSite) && (ptype[n] != eptShell)) 
+
+                if((ptype[n] != eptVSite) && (ptype[n] != eptShell))
                 {
-                    if(d == XX) 
+                    if(d == XX)
                     {
                         vc           = cosz*vcos;
                         /* Do not scale the cosine velocity profile */
                         vv           = vc + lg*(vn - vc + f[n][d]*w_dt);
                         /* Add the cosine accelaration profile */
                         vv          += dt*cosz*cos_accel;
-                    } 
-                    else 
+                    }
+                    else
                     {
                         vv           = lg*(vn + f[n][d]*w_dt);
                     }
                     v[n][d]        = vv;
                     xprime[n][d]   = x[n][d]+vv*dt;
-                } 
-                else 
+                }
+                else
                 {
                     v[n][d]        = 0.0;
                     xprime[n][d]   = x[n][d];
@@ -424,7 +433,7 @@ static gmx_stochd_t *init_stochd(FILE *fplog,t_inputrec *ir)
     gmx_sd_const_t *sdc;
     int  ngtc,n;
     real y;
-    
+
     snew(sd,1);
 
     /* Initiate random number generator for langevin type dynamics,
@@ -442,7 +451,7 @@ static gmx_stochd_t *init_stochd(FILE *fplog,t_inputrec *ir)
     {
         snew(sd->sdc,ngtc);
         snew(sd->sdsig,ngtc);
-    
+
         sdc = sd->sdc;
         for(n=0; n<ngtc; n++)
         {
@@ -463,7 +472,7 @@ static gmx_stochd_t *init_stochd(FILE *fplog,t_inputrec *ir)
             }
             if (sdc[n].gdt >= 0.05)
             {
-                sdc[n].b = sdc[n].gdt*(sdc[n].eph*sdc[n].eph - 1) 
+                sdc[n].b = sdc[n].gdt*(sdc[n].eph*sdc[n].eph - 1)
                     - 4*(sdc[n].eph - 1)*(sdc[n].eph - 1);
                 sdc[n].c = sdc[n].gdt - 3 + 4*sdc[n].emh - sdc[n].em;
                 sdc[n].d = 2 - sdc[n].eph - sdc[n].emh;
@@ -481,7 +490,32 @@ static gmx_stochd_t *init_stochd(FILE *fplog,t_inputrec *ir)
                         n,sdc[n].b,sdc[n].c,sdc[n].d);
         }
     }
+    else if (ETC_ANDERSEN(ir->etc))
+    {
+        int ngtc;
+        t_grpopts *opts;
+        real reft;
+
+        opts = &ir->opts;
+        ngtc = opts->ngtc;
+
+        snew(sd->randomize_group,ngtc);
+        snew(sd->boltzfac,ngtc);
 
+        /* for now, assume that all groups, if randomized, are randomized at the same rate, i.e. tau_t is the same. */
+        /* since constraint groups don't necessarily match up with temperature groups! This is checked in readir.c */
+
+        for (n=0;n<ngtc;n++) {
+            reft = max(0.0,opts->ref_t[n]);
+            if ((opts->tau_t[n] > 0) && (reft > 0))  /* tau_t or ref_t = 0 means that no randomization is done */
+            {
+                sd->randomize_group[n] = TRUE;
+                sd->boltzfac[n] = BOLTZ*opts->ref_t[n];
+            } else {
+                sd->randomize_group[n] = FALSE;
+            }
+        }
+    }
     return sd;
 }
 
@@ -498,16 +532,19 @@ void set_stochd_state(gmx_update_t upd,t_state *state)
 gmx_update_t init_update(FILE *fplog,t_inputrec *ir)
 {
     t_gmx_update *upd;
-    
+
     snew(upd,1);
-    
-    if (ir->eI == eiBD || EI_SD(ir->eI) || ir->etc == etcVRESCALE)
+
+    if (ir->eI == eiBD || EI_SD(ir->eI) || ir->etc == etcVRESCALE || ETC_ANDERSEN(ir->etc))
     {
         upd->sd = init_stochd(fplog,ir);
     }
 
     upd->xp = NULL;
     upd->xp_nalloc = 0;
+    upd->randatom = NULL;
+    upd->randatom_list = NULL;
+    upd->randatom_list_init = FALSE; /* we have not yet cleared the data structure at this point */
 
     return upd;
 }
@@ -532,24 +569,24 @@ static void do_update_sd1(gmx_stochd_t *sd,
 
   sdc = sd->sdc;
   sig = sd->sdsig;
-  if (homenr > sd->sd_V_nalloc) 
+  if (homenr > sd->sd_V_nalloc)
   {
       sd->sd_V_nalloc = over_alloc_dd(homenr);
       srenew(sd->sd_V,sd->sd_V_nalloc);
   }
   gaussrand = sd->gaussrand;
-  
-  for(n=0; n<ngtc; n++) 
+
+  for(n=0; n<ngtc; n++)
   {
       kT = BOLTZ*ref_t[n];
       /* The mass is encounted for later, since this differs per atom */
       sig[n].V  = sqrt(kT*(1 - sdc[n].em*sdc[n].em));
   }
-  
-  for(n=start; n<start+homenr; n++) 
+
+  for(n=start; n<start+homenr; n++)
   {
       ism = sqrt(invmass[n]);
-      if (cFREEZE) 
+      if (cFREEZE)
       {
           gf  = cFREEZE[n];
       }
@@ -561,20 +598,20 @@ static void do_update_sd1(gmx_stochd_t *sd,
       {
           gt  = cTC[n];
       }
-      
-      for(d=0; d<DIM; d++) 
+
+      for(d=0; d<DIM; d++)
       {
-          if((ptype[n] != eptVSite) && (ptype[n] != eptShell) && !nFreeze[gf][d]) 
+          if((ptype[n] != eptVSite) && (ptype[n] != eptShell) && !nFreeze[gf][d])
           {
               sd_V = ism*sig[gt].V*gmx_rng_gaussian_table(gaussrand);
-              
-              v[n][d] = v[n][d]*sdc[gt].em 
+
+              v[n][d] = v[n][d]*sdc[gt].em
                   + (invmass[n]*f[n][d] + accel[ga][d])*tau_t[gt]*(1 - sdc[gt].em)
                   + sd_V;
-              
+
               xprime[n][d] = x[n][d] + v[n][d]*dt;
-          } 
-          else 
+          }
+          else
           {
               v[n][d]      = 0.0;
               xprime[n][d] = x[n][d];
@@ -609,7 +646,7 @@ static void do_update_sd2(gmx_stochd_t *sd,gmx_bool bInitStep,
 
   sdc = sd->sdc;
   sig = sd->sdsig;
-  if (homenr > sd->sd_V_nalloc) 
+  if (homenr > sd->sd_V_nalloc)
   {
       sd->sd_V_nalloc = over_alloc_dd(homenr);
       srenew(sd->sd_V,sd->sd_V_nalloc);
@@ -617,9 +654,9 @@ static void do_update_sd2(gmx_stochd_t *sd,gmx_bool bInitStep,
   sd_V = sd->sd_V;
   gaussrand = sd->gaussrand;
 
-  if (bFirstHalf) 
+  if (bFirstHalf)
   {
-      for (n=0; n<ngtc; n++) 
+      for (n=0; n<ngtc; n++)
       {
           kT = BOLTZ*ref_t[n];
           /* The mass is encounted for later, since this differs per atom */
@@ -629,15 +666,15 @@ static void do_update_sd2(gmx_stochd_t *sd,gmx_bool bInitStep,
           sig[n].Yx = sqrt(kT*sqr(tau_t[n])*sdc[n].b/(1-sdc[n].em));
       }
   }
-  
-  for (n=start; n<start+homenr; n++) 
+
+  for (n=start; n<start+homenr; n++)
   {
       ism = sqrt(invmass[n]);
-      if (cFREEZE) 
+      if (cFREEZE)
       {
           gf  = cFREEZE[n];
       }
-      if (cACC) 
+      if (cACC)
       {
           ga  = cACC[n];
       }
@@ -645,52 +682,52 @@ static void do_update_sd2(gmx_stochd_t *sd,gmx_bool bInitStep,
       {
           gt  = cTC[n];
       }
-      
-      for(d=0; d<DIM; d++) 
+
+      for(d=0; d<DIM; d++)
       {
-          if (bFirstHalf) 
+          if (bFirstHalf)
           {
               vn             = v[n][d];
           }
-          if((ptype[n] != eptVSite) && (ptype[n] != eptShell) && !nFreeze[gf][d]) 
+          if((ptype[n] != eptVSite) && (ptype[n] != eptShell) && !nFreeze[gf][d])
           {
-              if (bFirstHalf) 
+              if (bFirstHalf)
               {
-                  if (bInitStep) 
+                  if (bInitStep)
                   {
                       sd_X[n][d] = ism*sig[gt].X*gmx_rng_gaussian_table(gaussrand);
                   }
-                  Vmh = sd_X[n][d]*sdc[gt].d/(tau_t[gt]*sdc[gt].c) 
+                  Vmh = sd_X[n][d]*sdc[gt].d/(tau_t[gt]*sdc[gt].c)
                       + ism*sig[gt].Yv*gmx_rng_gaussian_table(gaussrand);
                   sd_V[n-start][d] = ism*sig[gt].V*gmx_rng_gaussian_table(gaussrand);
-                  
-                  v[n][d] = vn*sdc[gt].em 
+
+                  v[n][d] = vn*sdc[gt].em
                       + (invmass[n]*f[n][d] + accel[ga][d])*tau_t[gt]*(1 - sdc[gt].em)
                       + sd_V[n-start][d] - sdc[gt].em*Vmh;
-                  
-                  xprime[n][d] = x[n][d] + v[n][d]*tau_t[gt]*(sdc[gt].eph - sdc[gt].emh); 
-              } 
-              else 
+
+                  xprime[n][d] = x[n][d] + v[n][d]*tau_t[gt]*(sdc[gt].eph - sdc[gt].emh);
+              }
+              else
               {
-                  
+
                   /* Correct the velocities for the constraints.
                    * This operation introduces some inaccuracy,
                    * since the velocity is determined from differences in coordinates.
                    */
-                  v[n][d] = 
-                      (xprime[n][d] - x[n][d])/(tau_t[gt]*(sdc[gt].eph - sdc[gt].emh));  
-                  
-                  Xmh = sd_V[n-start][d]*tau_t[gt]*sdc[gt].d/(sdc[gt].em-1) 
+                  v[n][d] =
+                      (xprime[n][d] - x[n][d])/(tau_t[gt]*(sdc[gt].eph - sdc[gt].emh));
+
+                  Xmh = sd_V[n-start][d]*tau_t[gt]*sdc[gt].d/(sdc[gt].em-1)
                       + ism*sig[gt].Yx*gmx_rng_gaussian_table(gaussrand);
                   sd_X[n][d] = ism*sig[gt].X*gmx_rng_gaussian_table(gaussrand);
-                  
+
                   xprime[n][d] += sd_X[n][d] - Xmh;
-                  
+
               }
-          } 
-          else 
+          }
+          else
           {
-              if (bFirstHalf) 
+              if (bFirstHalf)
               {
                   v[n][d]        = 0.0;
                   xprime[n][d]   = x[n][d];
@@ -714,25 +751,25 @@ static void do_update_bd(int start,int nrend,double dt,
     real   vn;
     real   invfr=0;
     int    n,d;
-    
-    if (friction_coefficient != 0) 
+
+    if (friction_coefficient != 0)
     {
         invfr = 1.0/friction_coefficient;
-        for(n=0; n<ngtc; n++) 
+        for(n=0; n<ngtc; n++)
         {
             rf[n] = sqrt(2.0*BOLTZ*ref_t[n]/(friction_coefficient*dt));
-        } 
+        }
     }
-    else 
+    else
     {
-        for(n=0; n<ngtc; n++) 
+        for(n=0; n<ngtc; n++)
         {
             rf[n] = sqrt(2.0*BOLTZ*ref_t[n]);
         }
     }
-    for(n=start; (n<nrend); n++) 
+    for(n=start; (n<nrend); n++)
     {
-        if (cFREEZE) 
+        if (cFREEZE)
         {
             gf = cFREEZE[n];
         }
@@ -740,14 +777,14 @@ static void do_update_bd(int start,int nrend,double dt,
         {
             gt = cTC[n];
         }
-        for(d=0; (d<DIM); d++) 
+        for(d=0; (d<DIM); d++)
         {
-            if((ptype[n]!=eptVSite) && (ptype[n]!=eptShell) && !nFreeze[gf][d]) 
+            if((ptype[n]!=eptVSite) && (ptype[n]!=eptShell) && !nFreeze[gf][d])
             {
                 if (friction_coefficient != 0) {
                     vn = invfr*f[n][d] + rf[gt]*gmx_rng_gaussian_table(gaussrand);
-                } 
-                else 
+                }
+                else
                 {
                     /* NOTE: invmass = 2/(mass*friction_constant*dt) */
                     vn = 0.5*invmass[n]*f[n][d]*dt 
@@ -757,7 +794,7 @@ static void do_update_bd(int start,int nrend,double dt,
                 v[n][d]      = vn;
                 xprime[n][d] = x[n][d]+vn*dt;
             }
-            else 
+            else
             {
                 v[n][d]      = 0.0;
                 xprime[n][d] = x[n][d];
@@ -770,7 +807,7 @@ static void dump_it_all(FILE *fp,const char *title,
                         int natoms,rvec x[],rvec xp[],rvec v[],rvec f[])
 {
 #ifdef DEBUG
-  if (fp) 
+  if (fp)
   {
     fprintf(fp,"%s\n",title);
     pr_rvecs(fp,0,"x",x,natoms);
@@ -782,7 +819,7 @@ static void dump_it_all(FILE *fp,const char *title,
 }
 
 static void calc_ke_part_normal(rvec v[], t_grpopts *opts,t_mdatoms *md,
-                                gmx_ekindata_t *ekind,t_nrnb *nrnb,gmx_bool bEkinAveVel, 
+                                gmx_ekindata_t *ekind,t_nrnb *nrnb,gmx_bool bEkinAveVel,
                                 gmx_bool bSaveEkinOld)
 {
   int          start=md->start,homenr=md->homenr;
@@ -794,9 +831,9 @@ static void calc_ke_part_normal(rvec v[], t_grpopts *opts,t_mdatoms *md,
   real         dekindl;
 
   /* three main: VV with AveVel, vv with AveEkin, leap with AveEkin.  Leap with AveVel is also
-     an option, but not supported now.  Additionally, if we are doing iterations.  
+     an option, but not supported now.  Additionally, if we are doing iterations.
      bEkinAveVel: If TRUE, we sum into ekin, if FALSE, into ekinh.
-     bSavEkinOld: If TRUE (in the case of iteration = bIterate is TRUE), we don't copy over the ekinh_old.  
+     bSavEkinOld: If TRUE (in the case of iteration = bIterate is TRUE), we don't copy over the ekinh_old.
      If FALSE, we overrwrite it.
   */
 
@@ -804,12 +841,12 @@ static void calc_ke_part_normal(rvec v[], t_grpopts *opts,t_mdatoms *md,
    * accumulated in acumulate_groups.
    * Now the partial global and groups ekin.
    */
-  for(g=0; (g<opts->ngtc); g++) 
+  for(g=0; (g<opts->ngtc); g++)
   {
-      
+
       if (!bSaveEkinOld) {
           copy_mat(tcstat[g].ekinh,tcstat[g].ekinh_old);
-      } 
+      }
       if(bEkinAveVel) {
           clear_mat(tcstat[g].ekinf);
       } else {
@@ -820,9 +857,9 @@ static void calc_ke_part_normal(rvec v[], t_grpopts *opts,t_mdatoms *md,
       }
   }
   ekind->dekindl_old = ekind->dekindl;
-  
+
   dekindl = 0;
-  for(n=start; (n<start+homenr); n++) 
+  for(n=start; (n<start+homenr); n++)
   {
       if (md->cACC)
       {
@@ -833,27 +870,27 @@ static void calc_ke_part_normal(rvec v[], t_grpopts *opts,t_mdatoms *md,
           gt = md->cTC[n];
       }
       hm   = 0.5*md->massT[n];
-      
-      for(d=0; (d<DIM); d++) 
+
+      for(d=0; (d<DIM); d++)
       {
           v_corrt[d]  = v[n][d]  - grpstat[ga].u[d];
       }
-      for(d=0; (d<DIM); d++) 
+      for(d=0; (d<DIM); d++)
       {
-          for (m=0;(m<DIM); m++) 
+          for (m=0;(m<DIM); m++)
           {
               /* if we're computing a full step velocity, v_corrt[d] has v(t).  Otherwise, v(t+dt/2) */
-              if (bEkinAveVel) 
+              if (bEkinAveVel)
               {
                   tcstat[gt].ekinf[m][d]+=hm*v_corrt[m]*v_corrt[d];
-              } 
-              else 
+              }
+              else
               {
-                  tcstat[gt].ekinh[m][d]+=hm*v_corrt[m]*v_corrt[d]; 
+                  tcstat[gt].ekinh[m][d]+=hm*v_corrt[m]*v_corrt[d];
               }
           }
       }
-      if (md->nMassPerturbed && md->bPerturbed[n]) 
+      if (md->nMassPerturbed && md->bPerturbed[n])
       {
           dekindl -= 0.5*(md->massB[n] - md->massA[n])*iprod(v_corrt,v_corrt);
       }
@@ -877,7 +914,7 @@ static void calc_ke_part_visc(matrix box,rvec x[],rvec v[],
   real         fac,cosz;
   double       mvcos;
 
-  for(g=0; g<opts->ngtc; g++) 
+  for(g=0; g<opts->ngtc; g++)
   {
       copy_mat(ekind->tcstat[g].ekinh,ekind->tcstat[g].ekinh_old);
       clear_mat(ekind->tcstat[g].ekinh);
@@ -887,46 +924,46 @@ static void calc_ke_part_visc(matrix box,rvec x[],rvec v[],
   fac = 2*M_PI/box[ZZ][ZZ];
   mvcos = 0;
   dekindl = 0;
-  for(n=start; n<start+homenr; n++) 
+  for(n=start; n<start+homenr; n++)
   {
-      if (md->cTC) 
+      if (md->cTC)
       {
           gt = md->cTC[n];
       }
       hm   = 0.5*md->massT[n];
-      
+
       /* Note that the times of x and v differ by half a step */
       /* MRS -- would have to be changed for VV */
       cosz         = cos(fac*x[n][ZZ]);
       /* Calculate the amplitude of the new velocity profile */
       mvcos       += 2*cosz*md->massT[n]*v[n][XX];
-      
+
       copy_rvec(v[n],v_corrt);
       /* Subtract the profile for the kinetic energy */
       v_corrt[XX] -= cosz*cosacc->vcos;
-      for (d=0; (d<DIM); d++) 
+      for (d=0; (d<DIM); d++)
       {
-          for (m=0; (m<DIM); m++) 
+          for (m=0; (m<DIM); m++)
           {
               /* if we're computing a full step velocity, v_corrt[d] has v(t).  Otherwise, v(t+dt/2) */
-              if (bEkinAveVel) 
+              if (bEkinAveVel)
               {
                   tcstat[gt].ekinf[m][d]+=hm*v_corrt[m]*v_corrt[d];
-              } 
-              else 
+              }
+              else
               {
                   tcstat[gt].ekinh[m][d]+=hm*v_corrt[m]*v_corrt[d];
               }
           }
       }
-      if(md->nPerturbed && md->bPerturbed[n]) 
+      if(md->nPerturbed && md->bPerturbed[n])
       {
           dekindl -= 0.5*(md->massB[n] - md->massA[n])*iprod(v_corrt,v_corrt);
       }
   }
   ekind->dekindl = dekindl;
   cosacc->mvcos = mvcos;
-  
+
   inc_nrnb(nrnb,eNR_EKIN,homenr);
 }
 
@@ -943,7 +980,7 @@ void calc_ke_part(t_state *state,t_grpopts *opts,t_mdatoms *md,
     }
 }
 
-void init_ekinstate(ekinstate_t *ekinstate,const t_inputrec *ir)
+extern void init_ekinstate(ekinstate_t *ekinstate,const t_inputrec *ir)
 {
     ekinstate->ekin_n = ir->opts.ngtc;
     snew(ekinstate->ekinh,ekinstate->ekin_n);
@@ -959,12 +996,12 @@ void init_ekinstate(ekinstate_t *ekinstate,const t_inputrec *ir)
 void update_ekinstate(ekinstate_t *ekinstate,gmx_ekindata_t *ekind)
 {
   int i;
-  
-  for(i=0;i<ekinstate->ekin_n;i++) 
+
+  for(i=0;i<ekinstate->ekin_n;i++)
   {
       copy_mat(ekind->tcstat[i].ekinh,ekinstate->ekinh[i]);
-      copy_mat(ekind->tcstat[i].ekinf,ekinstate->ekinf[i]); 
-      copy_mat(ekind->tcstat[i].ekinh_old,ekinstate->ekinh_old[i]); 
+      copy_mat(ekind->tcstat[i].ekinf,ekinstate->ekinf[i]);
+      copy_mat(ekind->tcstat[i].ekinh_old,ekinstate->ekinh_old[i]);
       ekinstate->ekinscalef_nhc[i] = ekind->tcstat[i].ekinscalef_nhc;
       ekinstate->ekinscaleh_nhc[i] = ekind->tcstat[i].ekinscaleh_nhc;
       ekinstate->vscale_nhc[i] = ekind->tcstat[i].vscale_nhc;
@@ -973,7 +1010,7 @@ void update_ekinstate(ekinstate_t *ekinstate,gmx_ekindata_t *ekind)
   copy_mat(ekind->ekin,ekinstate->ekin_total);
   ekinstate->dekindl = ekind->dekindl;
   ekinstate->mvcos = ekind->cosacc.mvcos;
-  
+
 }
 
 void restore_ekinstate_from_state(t_commrec *cr,
@@ -981,9 +1018,9 @@ void restore_ekinstate_from_state(t_commrec *cr,
 {
   int i,n;
 
-  if (MASTER(cr)) 
+  if (MASTER(cr))
   {
-      for(i=0;i<ekinstate->ekin_n;i++) 
+      for(i=0;i<ekinstate->ekin_n;i++)
       {
           copy_mat(ekinstate->ekinh[i],ekind->tcstat[i].ekinh);
           copy_mat(ekinstate->ekinf[i],ekind->tcstat[i].ekinf);
@@ -992,18 +1029,18 @@ void restore_ekinstate_from_state(t_commrec *cr,
           ekind->tcstat[i].ekinscaleh_nhc = ekinstate->ekinscaleh_nhc[i];
           ekind->tcstat[i].vscale_nhc = ekinstate->vscale_nhc[i];
       }
-      
+
       copy_mat(ekinstate->ekin_total,ekind->ekin);
 
       ekind->dekindl = ekinstate->dekindl;
       ekind->cosacc.mvcos = ekinstate->mvcos;
       n = ekinstate->ekin_n;
   }
-  if (PAR(cr)) 
+
+  if (PAR(cr))
   {
       gmx_bcast(sizeof(n),&n,cr);
-      for(i=0;i<n;i++) 
+      for(i=0;i<n;i++)
       {
           gmx_bcast(DIM*DIM*sizeof(ekind->tcstat[i].ekinh[0][0]),
                     ekind->tcstat[i].ekinh[0],cr);
@@ -1039,8 +1076,8 @@ static void deform(gmx_update_t upd,
 {
     matrix bnew,invbox,mu;
     real   elapsed_time;
-    int    i,j;  
-    
+    int    i,j;
+
     elapsed_time = (step + 1 - upd->deformref_step)*ir->delta_t;
     copy_mat(box,bnew);
     for(i=0; i<DIM; i++)
@@ -1075,7 +1112,7 @@ static void deform(gmx_update_t upd,
     m_inv_ur0(box,invbox);
     copy_mat(bnew,box);
     mmul_ur0(box,invbox,mu);
-  
+
     for(i=start; i<start+homenr; i++)
     {
         x[i][XX] = mu[XX][XX]*x[i][XX]+mu[YY][XX]*x[i][YY]+mu[ZZ][XX]*x[i][ZZ];
@@ -1115,10 +1152,10 @@ static void combine_forces(int nstlist,
          */
         /* MRS -- need to make sure this works with trotter integration -- the constraint calls may not be right.*/
         constrain(NULL,FALSE,FALSE,constr,idef,ir,NULL,cr,step,0,md,
-                  state->x,f_lr,f_lr,state->box,state->lambda,NULL,
+                  state->x,f_lr,f_lr,state->box,state->lambda[efptBONDED],NULL,
                   NULL,NULL,nrnb,econqForce,ir->epc==epcMTTK,state->veta,state->veta);
     }
-    
+
     /* Add nstlist-1 times the LR force to the sum of both forces
      * and store the result in forces_lr.
      */
@@ -1134,34 +1171,41 @@ static void combine_forces(int nstlist,
 
 void update_tcouple(FILE         *fplog,
                     gmx_large_int_t   step,
-                    t_inputrec   *inputrec,   
+                    t_inputrec   *inputrec,
                     t_state      *state,
                     gmx_ekindata_t *ekind,
                     gmx_wallcycle_t wcycle,
                     gmx_update_t upd,
                     t_extmass    *MassQ,
                     t_mdatoms  *md)
-    
+
 {
     gmx_bool   bTCouple=FALSE;
     real   dttc;
-    int    i,start,end,homenr;
-    
-    /* if using vv, we do this elsewhere in the code */
+    int    i,start,end,homenr,offset;
+
+    /* if using vv with trotter decomposition methods, we do this elsewhere in the code */
     if (inputrec->etc != etcNO &&
-        !(IR_NVT_TROTTER(inputrec) || IR_NPT_TROTTER(inputrec)))
+        !(IR_NVT_TROTTER(inputrec) || IR_NPT_TROTTER(inputrec) || IR_NPH_TROTTER(inputrec)))
     {
-        /* We should only couple after a step where energies were determined */
+        /* We should only couple after a step where energies were determined (for leapfrog versions)
+         or the step energies are determined, for velocity verlet versions */
+
+        if (EI_VV(inputrec->eI)) {
+            offset = 0;
+        } else {
+            offset = 1;
+        }
         bTCouple = (inputrec->nsttcouple == 1 ||
-                    do_per_step(step+inputrec->nsttcouple-1,
+                    do_per_step(step+inputrec->nsttcouple-offset,
                                 inputrec->nsttcouple));
     }
-    
+
     if (bTCouple)
     {
         dttc = inputrec->nsttcouple*inputrec->delta_t;
 
-        switch (inputrec->etc) 
+        switch (inputrec->etc)
         {
         case etcNO:
             break;
@@ -1183,7 +1227,7 @@ void update_tcouple(FILE         *fplog,
             rescale_velocities(ekind,md,md->start,md->start+md->homenr,state->v);
         }
     }
-    else 
+    else
     {
         /* Set the T scaling lambda to 1 to have no scaling */
         for(i=0; (i<inputrec->opts.ngtc); i++)
@@ -1195,7 +1239,7 @@ void update_tcouple(FILE         *fplog,
 
 void update_pcouple(FILE         *fplog,
                     gmx_large_int_t   step,
-                    t_inputrec   *inputrec,   
+                    t_inputrec   *inputrec,
                     t_state      *state,
                     matrix       pcoupl_mu,
                     matrix       M,
@@ -1206,30 +1250,29 @@ void update_pcouple(FILE         *fplog,
     gmx_bool   bPCouple=FALSE;
     real   dtpc=0;
     int    i;
-    
-    /* if using vv, we do this elsewhere in the code */
-    if (inputrec->epc != epcNO &&
-        !(IR_NVT_TROTTER(inputrec) || IR_NPT_TROTTER(inputrec)))
+
+    /* if using Trotter pressure, we do this in coupling.c, so we leave it false. */
+    if (inputrec->epc != epcNO && (!(IR_NPT_TROTTER(inputrec) || IR_NPH_TROTTER(inputrec))))
     {
         /* We should only couple after a step where energies were determined */
         bPCouple = (inputrec->nstpcouple == 1 ||
                     do_per_step(step+inputrec->nstpcouple-1,
                                 inputrec->nstpcouple));
     }
-    
+
     clear_mat(pcoupl_mu);
     for(i=0; i<DIM; i++)
     {
         pcoupl_mu[i][i] = 1.0;
     }
-    
+
     clear_mat(M);
-     
+
     if (bPCouple)
     {
         dtpc = inputrec->nstpcouple*inputrec->delta_t;
 
-        switch (inputrec->epc) 
+        switch (inputrec->epc)
         {
             /* We can always pcoupl, even if we did not sum the energies
              * the previous step, since state->pres_prev is only updated
@@ -1238,7 +1281,7 @@ void update_pcouple(FILE         *fplog,
         case (epcNO):
             break;
         case (epcBERENDSEN):
-            if (!bInitStep) 
+            if (!bInitStep)
             {
                 berendsen_pcoupl(fplog,step,inputrec,dtpc,state->pres_prev,state->box,
                                  pcoupl_mu);
@@ -1251,8 +1294,8 @@ void update_pcouple(FILE         *fplog,
             break;
         default:
             break;
-        }  
-    } 
+        }
+    }
 }
 
 static rvec *get_xprime(const t_state *state,gmx_update_t upd)
@@ -1262,18 +1305,18 @@ static rvec *get_xprime(const t_state *state,gmx_update_t upd)
         upd->xp_nalloc = state->nalloc;
         srenew(upd->xp,upd->xp_nalloc);
     }
+
     return upd->xp;
 }
 
 void update_constraints(FILE         *fplog,
                         gmx_large_int_t   step,
-                        real         *dvdlambda,    /* FEP stuff */
+                        real         *dvdlambda,    /* the contribution to be added to the bonded interactions */
                         t_inputrec   *inputrec,      /* input record and box stuff     */
                         gmx_ekindata_t *ekind,
                         t_mdatoms    *md,
                         t_state      *state,
-                        t_graph      *graph,  
+                        t_graph      *graph,
                         rvec         force[],        /* forces on home particles */
                         t_idef       *idef,
                         tensor       vir_part,
@@ -1288,38 +1331,38 @@ void update_constraints(FILE         *fplog,
                         gmx_bool         bCalcVir,
                         real         vetanew)
 {
-    gmx_bool             bExtended,bTrotter,bLastStep,bLog=FALSE,bEner=FALSE,bDoConstr=FALSE;
+    gmx_bool             bExtended,bLastStep,bLog=FALSE,bEner=FALSE,bDoConstr=FALSE;
     double           dt;
     real             dt_1;
     int              start,homenr,nrend,i,n,m,g,d;
     tensor           vir_con;
     rvec             *vbuf,*xprime=NULL;
-    
+
     if (constr) {bDoConstr=TRUE;}
-    if (bFirstHalf && !EI_VV(inputrec->eI)) {bDoConstr=FALSE;} 
+    if (bFirstHalf && !EI_VV(inputrec->eI)) {bDoConstr=FALSE;}
 
-    /* for now, SD update is here -- though it really seems like it 
+    /* for now, SD update is here -- though it really seems like it
        should be reformulated as a velocity verlet method, since it has two parts */
-    
+
     start  = md->start;
     homenr = md->homenr;
     nrend = start+homenr;
-    
+
     dt   = inputrec->delta_t;
     dt_1 = 1.0/dt;
-    
-    /* 
+
+    /*
      *  Steps (7C, 8C)
      *  APPLY CONSTRAINTS:
-     *  BLOCK SHAKE 
+     *  BLOCK SHAKE
 
      * When doing PR pressure coupling we have to constrain the
      * bonds in each iteration. If we are only using Nose-Hoover tcoupling
-     * it is enough to do this once though, since the relative velocities 
+     * it is enough to do this once though, since the relative velocities
      * after this will be normal to the bond vector
      */
-    
-    if (bDoConstr) 
+
+    if (bDoConstr)
     {
         /* clear out constraints before applying */
         clear_mat(vir_part);
@@ -1331,58 +1374,58 @@ void update_constraints(FILE         *fplog,
         bEner = (do_per_step(step,inputrec->nstenergy) || bLastStep);
         /* Constrain the coordinates xprime */
         wallcycle_start(wcycle,ewcCONSTR);
-        if (EI_VV(inputrec->eI) && bFirstHalf) 
+        if (EI_VV(inputrec->eI) && bFirstHalf)
         {
             constrain(NULL,bLog,bEner,constr,idef,
                       inputrec,ekind,cr,step,1,md,
                       state->x,state->v,state->v,
-                      state->box,state->lambda,dvdlambda,
+                      state->box,state->lambda[efptBONDED],dvdlambda,
                       NULL,bCalcVir ? &vir_con : NULL,nrnb,econqVeloc,
                       inputrec->epc==epcMTTK,state->veta,vetanew);
-        } 
-        else 
+        }
+        else
         {
             constrain(NULL,bLog,bEner,constr,idef,
                       inputrec,ekind,cr,step,1,md,
                       state->x,xprime,NULL,
-                      state->box,state->lambda,dvdlambda,
+                      state->box,state->lambda[efptBONDED],dvdlambda,
                       state->v,bCalcVir ? &vir_con : NULL ,nrnb,econqCoord,
                       inputrec->epc==epcMTTK,state->veta,state->veta);
         }
         wallcycle_stop(wcycle,ewcCONSTR);
-        
+
         where();
-    
+
         dump_it_all(fplog,"After Shake",
                     state->natoms,state->x,xprime,state->v,force);
-        
-        if (bCalcVir) 
+
+        if (bCalcVir)
         {
-            if (inputrec->eI == eiSD2) 
+            if (inputrec->eI == eiSD2)
             {
                 /* A correction factor eph is needed for the SD constraint force */
                 /* Here we can, unfortunately, not have proper corrections
                  * for different friction constants, so we use the first one.
                  */
-                for(i=0; i<DIM; i++) 
+                for(i=0; i<DIM; i++)
                 {
                     for(m=0; m<DIM; m++)
                     {
                         vir_part[i][m] += upd->sd->sdc[0].eph*vir_con[i][m];
                     }
                 }
-            } 
-            else 
+            }
+            else
             {
                 m_add(vir_part,vir_con,vir_part);
             }
-            if (debug) 
+            if (debug)
             {
                 pr_rvecs(debug,0,"constraint virial",vir_part,DIM);
             }
         }
     }
-    
+
     where();
     if ((inputrec->eI == eiSD2) && !(bFirstHalf))
     {
@@ -1397,42 +1440,42 @@ void update_constraints(FILE         *fplog,
                       inputrec->opts.ngtc,inputrec->opts.tau_t,
                       inputrec->opts.ref_t,FALSE);
         inc_nrnb(nrnb, eNR_UPDATE, homenr);
-        
-        if (bDoConstr) 
+
+        if (bDoConstr)
         {
             /* Constrain the coordinates xprime */
             wallcycle_start(wcycle,ewcCONSTR);
             constrain(NULL,bLog,bEner,constr,idef,
                       inputrec,NULL,cr,step,1,md,
                       state->x,xprime,NULL,
-                      state->box,state->lambda,dvdlambda,
+                      state->box,state->lambda[efptBONDED],dvdlambda,
                       NULL,NULL,nrnb,econqCoord,FALSE,0,0);
             wallcycle_stop(wcycle,ewcCONSTR);
         }
-    }    
+    }
 
     /* We must always unshift after updating coordinates; if we did not shake
        x was shifted in do_force */
-    
+
     if (!(bFirstHalf)) /* in the first half of vv, no shift. */
     {
-        if (graph && (graph->nnodes > 0)) 
+        if (graph && (graph->nnodes > 0))
         {
             unshift_x(graph,state->box,state->x,upd->xp);
-            if (TRICLINIC(state->box)) 
+            if (TRICLINIC(state->box))
             {
                 inc_nrnb(nrnb,eNR_SHIFTX,2*graph->nnodes);
             }
             else
             {
-                inc_nrnb(nrnb,eNR_SHIFTX,graph->nnodes);    
+                inc_nrnb(nrnb,eNR_SHIFTX,graph->nnodes);
             }
         }
-        else 
+        else
         {
             copy_rvecn(upd->xp,state->x,start,nrend);
         }
-        
+
         dump_it_all(fplog,"After unshift",
                     state->natoms,state->x,upd->xp,state->v,force);
     }
@@ -1454,23 +1497,23 @@ void update_box(FILE         *fplog,
                 gmx_bool         bInitStep,
                 gmx_bool         bFirstHalf)
 {
-    gmx_bool             bExtended,bTrotter,bLastStep,bLog=FALSE,bEner=FALSE;
+    gmx_bool             bExtended,bLastStep,bLog=FALSE,bEner=FALSE;
     double           dt;
     real             dt_1;
     int              start,homenr,nrend,i,n,m,g;
     tensor           vir_con;
-    
+
     start  = md->start;
     homenr = md->homenr;
     nrend = start+homenr;
-    
+
     bExtended =
         (inputrec->etc == etcNOSEHOOVER) ||
         (inputrec->epc == epcPARRINELLORAHMAN) ||
         (inputrec->epc == epcMTTK);
-    
+
     dt = inputrec->delta_t;
-    
+
     where();
 
     /* now update boxes */
@@ -1481,7 +1524,7 @@ void update_box(FILE         *fplog,
         berendsen_pscale(inputrec,pcoupl_mu,state->box,state->box_rel,
                          start,homenr,state->x,md->cFREEZE,nrnb);
         break;
-    case (epcPARRINELLORAHMAN): 
+    case (epcPARRINELLORAHMAN):
         /* The box velocities were updated in do_pr_pcoupl in the update
          * iteration, but we dont change the box vectors until we get here
          * since we need to be able to shift/unshift above.
@@ -1494,23 +1537,23 @@ void update_box(FILE         *fplog,
             }
         }
         preserve_box_shape(inputrec,state->box_rel,state->box);
-        
+
         /* Scale the coordinates */
-        for(n=start; (n<start+homenr); n++) 
+        for(n=start; (n<start+homenr); n++)
         {
             tmvmul_ur0(pcoupl_mu,state->x[n],state->x[n]);
         }
         break;
     case (epcMTTK):
-        switch (inputrec->epct) 
+        switch (inputrec->epct)
         {
         case (epctISOTROPIC):
-            /* DIM * eta = ln V.  so DIM*eta_new = DIM*eta_old + DIM*dt*veta => 
-               ln V_new = ln V_old + 3*dt*veta => V_new = V_old*exp(3*dt*veta) => 
+            /* DIM * eta = ln V.  so DIM*eta_new = DIM*eta_old + DIM*dt*veta =>
+               ln V_new = ln V_old + 3*dt*veta => V_new = V_old*exp(3*dt*veta) =>
                Side length scales as exp(veta*dt) */
-            
+
             msmul(state->box,exp(state->veta*dt),state->box);
-            
+
             /* Relate veta to boxv.  veta = d(eta)/dT = (1/DIM)*1/V dV/dT.
 o               If we assume isotropic scaling, and box length scaling
                factor L, then V = L^DIM (det(M)).  So dV/dt = DIM
@@ -1519,7 +1562,7 @@ o               If we assume isotropic scaling, and box length scaling
                of dB/dt is (dL/dT)^DIM det (M).  veta will be
                (det(dB/dT)/det(B))^(1/3).  Then since M =
                B_new*(vol_new)^(1/3), dB/dT_new = (veta_new)*B(new). */
-            
+
             msmul(state->box,state->veta,state->boxv);
             break;
         default:
@@ -1529,8 +1572,8 @@ o               If we assume isotropic scaling, and box length scaling
     default:
         break;
     }
-    
-    if ((!(IR_NPT_TROTTER(inputrec))) && scale_tot) 
+
+    if ((!(IR_NPT_TROTTER(inputrec) || IR_NPH_TROTTER(inputrec))) && scale_tot)
     {
         /* The transposes of the scaling matrices are stored,
          * therefore we need to reverse the order in the multiplication.
@@ -1538,7 +1581,7 @@ o               If we assume isotropic scaling, and box length scaling
         mmul_ur0(*scale_tot,pcoupl_mu,*scale_tot);
     }
 
-    if (DEFORM(*inputrec)) 
+    if (DEFORM(*inputrec))
     {
         deform(upd,start,homenr,state->x,state->box,scale_tot,inputrec,step);
     }
@@ -1567,7 +1610,7 @@ void update_coords(FILE         *fplog,
                    gmx_constr_t constr,
                    t_idef       *idef)
 {
-    gmx_bool             bExtended,bNH,bPR,bTrotter,bLastStep,bLog=FALSE,bEner=FALSE;
+    gmx_bool         bNH,bPR,bLastStep,bLog=FALSE,bEner=FALSE;
     double           dt,alpha;
     real             *imass,*imassin;
     rvec             *force;
@@ -1577,7 +1620,7 @@ void update_coords(FILE         *fplog,
     int              *icom = NULL;
     tensor           vir_con;
     rvec             *vcom,*xcom,*vall,*xall,*xin,*vin,*forcein,*fall,*xpall,*xprimein,*xprime;
-    
+
 
     /* Running the velocity half does nothing except for velocity verlet */
     if ((UpdatePart == etrtVELOCITY1 || UpdatePart == etrtVELOCITY2) &&
@@ -1589,27 +1632,26 @@ void update_coords(FILE         *fplog,
     start  = md->start;
     homenr = md->homenr;
     nrend = start+homenr;
-    
+
     xprime = get_xprime(state,upd);
-    
+
     dt   = inputrec->delta_t;
     dt_1 = 1.0/dt;
 
     /* We need to update the NMR restraint history when time averaging is used */
-    if (state->flags & (1<<estDISRE_RM3TAV)) 
+    if (state->flags & (1<<estDISRE_RM3TAV))
     {
         update_disres_history(fcd,&state->hist);
     }
-    if (state->flags & (1<<estORIRE_DTAV)) 
+    if (state->flags & (1<<estORIRE_DTAV))
     {
         update_orires_history(fcd,&state->hist);
     }
-    
+
+
     bNH = inputrec->etc == etcNOSEHOOVER;
-    bPR = ((inputrec->epc == epcPARRINELLORAHMAN) || (inputrec->epc == epcMTTK)); 
+    bPR = ((inputrec->epc == epcPARRINELLORAHMAN) || (inputrec->epc == epcMTTK));
 
-    bExtended = bNH || bPR;
-    
     if (bDoLR && inputrec->nstlist > 1 && !EI_VV(inputrec->eI))  /* get this working with VV? */
     {
         /* Store the total force + nstlist-1 times the LR force
@@ -1630,7 +1672,7 @@ void update_coords(FILE         *fplog,
     where();
     dump_it_all(fplog,"Before update",
                 state->natoms,state->x,xprime,state->v,force);
-    
+
     switch (inputrec->eI) {
     case (eiMD):
         if (ekind->cosacc.cos_accel == 0) {
@@ -1641,8 +1683,8 @@ void update_coords(FILE         *fplog,
                          md->cFREEZE,md->cACC,md->cTC,
                          state->x,xprime,state->v,force,M,
                          bNH,bPR);
-        } 
-        else 
+        }
+        else
         {
             do_update_visc(start,nrend,dt,
                            ekind->tcstat,md->invmass,state->nosehoover_vxi,
@@ -1660,7 +1702,7 @@ void update_coords(FILE         *fplog,
         break;
     case (eiSD2):
         /* The SD update is done in 2 parts, because an extra constraint step
-         * is needed 
+         * is needed
          */
         do_update_sd2(upd->sd,bInitStep,start,homenr,
                       inputrec->opts.acc,inputrec->opts.nFreeze,
@@ -1688,10 +1730,8 @@ void update_coords(FILE         *fplog,
             do_update_vv_vel(start,nrend,dt,
                              ekind->tcstat,ekind->grpstat,
                              inputrec->opts.acc,inputrec->opts.nFreeze,
-                             md->invmass,md->ptype,
-                             md->cFREEZE,md->cACC,
-                             state->v,force,
-                             bExtended,state->veta,alpha);  
+                             md->invmass,md->ptype,md->cFREEZE,md->cACC,
+                             state->v,force,(bNH || bPR),state->veta,alpha);
             break;
         case etrtPOSITION:
             do_update_vv_pos(start,nrend,dt,
@@ -1699,7 +1739,7 @@ void update_coords(FILE         *fplog,
                              inputrec->opts.acc,inputrec->opts.nFreeze,
                              md->invmass,md->ptype,md->cFREEZE,
                              state->x,xprime,state->v,force,
-                             bExtended,state->veta,alpha);
+                             (bNH || bPR) ,state->veta,alpha);
             break;
         }
         break;
@@ -1707,13 +1747,14 @@ void update_coords(FILE         *fplog,
         gmx_fatal(FARGS,"Don't know how to update coordinates");
         break;
     }
+
 }
 
 
 void correct_ekin(FILE *log,int start,int end,rvec v[],rvec vcm,real mass[],
                   real tmass,tensor ekin)
 {
-  /* 
+  /*
    * This is a debugging routine. It should not be called for production code
    *
    * The kinetic energy should calculated according to:
@@ -1731,27 +1772,27 @@ void correct_ekin(FILE *log,int start,int end,rvec v[],rvec vcm,real mass[],
   rvec   hvcm,mv;
   tensor dekin;
 
-  /* Local particles */  
+  /* Local particles */
   clear_rvec(mv);
 
   /* Processor dependent part. */
   tm = 0;
-  for(i=start; (i<end); i++) 
+  for(i=start; (i<end); i++)
   {
     m      = mass[i];
     tm    += m;
-    for(j=0; (j<DIM); j++) 
+    for(j=0; (j<DIM); j++)
     {
         mv[j] += m*v[i][j];
     }
   }
-  /* Shortcut */ 
-  svmul(1/tmass,vcm,vcm); 
+  /* Shortcut */
+  svmul(1/tmass,vcm,vcm);
   svmul(0.5,vcm,hvcm);
   clear_mat(dekin);
-  for(j=0; (j<DIM); j++) 
+  for(j=0; (j<DIM); j++)
   {
-      for(k=0; (k<DIM); k++) 
+      for(k=0; (k<DIM); k++)
       {
           dekin[j][k] += vcm[k]*(tm*hvcm[j]-mv[j]);
       }
@@ -1763,3 +1804,31 @@ void correct_ekin(FILE *log,int start,int end,rvec v[],rvec vcm,real mass[],
   fprintf(log,"mv = (%8.4f %8.4f %8.4f)\n",
           mv[XX],mv[YY],mv[ZZ]);
 }
+
+extern gmx_bool update_randomize_velocities(t_inputrec *ir, gmx_large_int_t step, t_mdatoms *md, t_state *state, gmx_update_t upd, t_idef *idef, gmx_constr_t constr) {
+
+    int i;
+    real rate = (ir->delta_t)/ir->opts.tau_t[0];
+    /* proceed with andersen if 1) it's fixed probability per
+       particle andersen or 2) it's massive andersen and it's tau_t/dt */
+    if ((ir->etc==etcANDERSEN) || do_per_step(step,(int)(1.0/rate)))
+    {
+        srenew(upd->randatom,state->nalloc);
+        srenew(upd->randatom_list,state->nalloc);
+        if (upd->randatom_list_init == FALSE) {
+            for (i=0;i<state->nalloc;i++) {
+                upd->randatom[i] = FALSE;
+                upd->randatom_list[i] = 0;
+            }
+            upd->randatom_list_init = TRUE;
+        }
+        andersen_tcoupl(ir,md,state,upd->sd->gaussrand,rate,
+                        (ir->etc==etcANDERSEN)?idef:NULL,
+                        constr?get_nblocks(constr):0,
+                        constr?get_sblock(constr):NULL,
+                        upd->randatom,upd->randatom_list,
+                        upd->sd->randomize_group,upd->sd->boltzfac);
+        return TRUE;
+    }
+    return FALSE;
+}
index beb4d7cf5c34483e11bb6c93af59c9c12cef3c9d..d1be14c8d246aaf77ddedf91a3cb78d2a5c83c4a 100644 (file)
@@ -317,6 +317,6 @@ real do_walls(t_inputrec *ir,t_forcerec *fr,matrix box,t_mdatoms *md,
     {
         fr->vir_wall_z[i] = -0.5*xf_z[i];
     }
-    
+
     return dvdlambda;
 }
index 5641cc53d95109f37454f485e8ea18205b5ad12a..aad6a64a7c5483dc8093d5eded1089e199b146df 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 
+ *
  *                This source code is part of
- * 
+ *
  *                 G   R   O   M   A   C   S
- * 
+ *
  *          GROningen MAchine for Chemical Simulations
- * 
+ *
  *                        VERSION 3.2.0
  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * If you want to redistribute modifications, please consider that
  * scientific software is very special. Version control is crucial -
  * bugs must be traceable. We will be happy to consider code for
  * inclusion in the official distribution, but derived work must not
  * be called official GROMACS. Details are found in the README & COPYING
  * files - if they are missing, get the official version at www.gromacs.org.
- * 
+ *
  * To help us fund GROMACS development, we humbly ask that you cite
  * the papers on the package - you can find them in the top README file.
- * 
+ *
  * For more info, check our website at http://www.gromacs.org
- * 
+ *
  * And Hey:
  * Green Red Orange Magenta Azure Cyan Skyblue
  */
@@ -58,12 +58,12 @@ static real max_dist(rvec *x, real *r, int start, int end)
 {
   real maxd;
   int i,j;
-  
+
   maxd=0;
   for(i=start; i<end; i++)
     for(j=i+1; j<end; j++)
       maxd=max(maxd,sqrt(distance2(x[i],x[j]))+0.5*(r[i]+r[j]));
-  
+
   return 0.5*maxd;
 }
 
@@ -84,7 +84,7 @@ static gmx_bool outside_box_plus_margin(rvec x,matrix box)
 static int mark_res(int at, gmx_bool *mark, int natoms, t_atom *atom,int *nmark)
 {
   int resind;
-  
+
   resind = atom[at].resind;
   while( (at > 0) && (resind==atom[at-1].resind) )
     at--;
@@ -95,7 +95,7 @@ static int mark_res(int at, gmx_bool *mark, int natoms, t_atom *atom,int *nmark)
     }
     at++;
   }
-  
+
   return at;
 }
 
@@ -103,7 +103,7 @@ static real find_max_real(int n,real radius[])
 {
   int  i;
   real rmax;
-  
+
   rmax = 0;
   if (n > 0) {
     rmax = radius[0];
@@ -120,16 +120,16 @@ static void combine_atoms(t_atoms *ap,t_atoms *as,
   t_atoms *ac;
   rvec    *xc,*vc=NULL;
   int     i,j,natot,res0;
-  
+
   /* Total number of atoms */
   natot = ap->nr+as->nr;
-  
+
   snew(ac,1);
   init_t_atoms(ac,natot,FALSE);
-  
+
   snew(xc,natot);
   if (vp && vs) snew(vc,natot);
-    
+
   /* Fill the new structures */
   for(i=j=0; (i<ap->nr); i++,j++) {
     copy_rvec(xp[i],xc[j]);
@@ -183,15 +183,15 @@ void do_nsgrid(FILE *fp,gmx_bool bVerbose,
   ivec       *nFreeze;
   int        i,m,natoms;
   rvec       box_size;
-  real       lambda=0,dvdlambda=0;
+  real       *lambda,*dvdl;
 
   natoms = atoms->nr;
-    
-  /* Charge group index */  
+
+  /* Charge group index */
   snew(cg_index,natoms);
   for(i=0; (i<natoms); i++)
     cg_index[i]=i;
-  
+
   /* Topology needs charge groups and exclusions */
   snew(mtop,1);
   init_mtop(mtop);
@@ -214,9 +214,9 @@ void do_nsgrid(FILE *fp,gmx_bool bVerbose,
   mtop->groups.grps[egcENER].nr = 1;
   mtop->groups.ngrpnr[egcENER]  = 0;
   mtop->groups.grpnr[egcENER]   = NULL;
-  
+
   ffp = &mtop->ffparams;
-  
+
   ffp->ntypes = 1;
   ffp->atnr   = 1;
   ffp->reppow = 12;
@@ -224,7 +224,7 @@ void do_nsgrid(FILE *fp,gmx_bool bVerbose,
   snew(ffp->iparams,1);
   ffp->iparams[0].lj.c6  = 1;
   ffp->iparams[0].lj.c12 = 1;
-  
+
   /* inputrec structure */
   snew(ir,1);
   ir->coulombtype = eelCUT;
@@ -232,60 +232,64 @@ void do_nsgrid(FILE *fp,gmx_bool bVerbose,
   ir->ndelta      = 2;
   ir->ns_type     = ensGRID;
   snew(ir->opts.egp_flags,1);
-  
+
   top = gmx_mtop_generate_local_top(mtop,ir);
-       
+
   /* Some nasty shortcuts */
-  cgs  = &(top->cgs);  
-       
+  cgs  = &(top->cgs);
+
     /* mdatoms structure */
   snew(nFreeze,2);
   snew(md,1);
   md = init_mdatoms(fp,mtop,FALSE);
   atoms2md(mtop,ir,0,NULL,0,mtop->natoms,md);
   sfree(nFreeze);
-  
+
   /* forcerec structure */
   if (fr == NULL)
     fr = mk_forcerec();
   snew(cr,1);
   cr->nnodes   = 1;
   /* cr->nthreads = 1; */
-  
+
   /*    ir->rlist       = ir->rcoulomb = ir->rvdw = rlong;
        printf("Neighborsearching with a cut-off of %g\n",rlong);
        init_forcerec(stdout,fr,ir,top,cr,md,box,FALSE,NULL,NULL,NULL,TRUE);*/
   fr->cg0 = 0;
   fr->hcg = top->cgs.nr;
   fr->nWatMol = 0;
-  
+
   /* Prepare for neighboursearching */
   init_nrnb(&nrnb);
-  
-  /* Init things dependent on parameters */  
+
+  /* Init things dependent on parameters */
   ir->rlistlong = ir->rlist = ir->rcoulomb = ir->rvdw = rlong;
+  /* create free energy data to avoid NULLs */
+  snew(ir->fepvals,1);
   printf("Neighborsearching with a cut-off of %g\n",rlong);
   init_forcerec(stdout,oenv,fr,NULL,ir,mtop,cr,box,FALSE,NULL,NULL,NULL,NULL,
                 TRUE,-1);
   if (debug)
     pr_forcerec(debug,fr,cr);
-               
+
   /* Calculate new stuff dependent on coords and box */
   for(m=0; (m<DIM); m++)
     box_size[m] = box[m][m];
   calc_shifts(box,fr->shift_vec);
   put_charge_groups_in_box(fp,0,cgs->nr,fr->ePBC,box,cgs,x,fr->cg_cm);
-  
+
   /* Do the actual neighboursearching */
+  snew(lambda,efptNR);
+  snew(dvdl,efptNR);
   init_neighbor_list(fp,fr,md->homenr);
   search_neighbours(fp,fr,x,box,top,
-                   &mtop->groups,cr,&nrnb,md,lambda,&dvdlambda,NULL,
+                   &mtop->groups,cr,&nrnb,md,lambda,dvdl,NULL,
                    TRUE,FALSE,FALSE,NULL);
 
   if (debug)
     dump_nblist(debug,cr,fr,0);
 
-  if (bVerbose)    
+  if (bVerbose)
     fprintf(stderr,"Successfully made neighbourlist\n");
 }
 
@@ -317,13 +321,13 @@ void add_conf(t_atoms *atoms, rvec **x, rvec **v, real **r, gmx_bool bSrenew,
     fprintf(stderr,"WARNING: Nothing to add\n");
     return;
   }
-  
+
   if (ePBC == epbcSCREW)
     gmx_fatal(FARGS,"Sorry, %s pbc is not yet supported",epbc_names[ePBC]);
 
   if (bVerbose)
     fprintf(stderr,"Calculating Overlap...\n");
-  
+
   /* Set margin around box edges to largest solvent dimension.
    * The maximum distance between atoms in a solvent molecule should
    * be calculated. At the moment a fudge factor of 3 is used.
@@ -332,7 +336,7 @@ void add_conf(t_atoms *atoms, rvec **x, rvec **v, real **r, gmx_bool bSrenew,
   box_margin = 3*find_max_real(natoms_solvt,r_solvt);
   max_vdw    = max(3*find_max_real(natoms_prot,r_prot),box_margin);
   fprintf(stderr,"box_margin = %g\n",box_margin);
-  
+
   snew(remove,natoms_solvt);
 
   nremove = 0;
@@ -342,7 +346,7 @@ void add_conf(t_atoms *atoms, rvec **x, rvec **v, real **r, gmx_bool bSrenew,
        i=mark_res(i,remove,atoms_solvt->nr,atoms_solvt->atom,&nremove);
     fprintf(stderr,"Removed %d atoms that were outside the box\n",nremove);
   }
-  
+
   /* Define grid stuff for genbox */
   /* Largest VDW radius */
   snew(r_all,natoms_prot+natoms_solvt);
@@ -354,10 +358,10 @@ void add_conf(t_atoms *atoms, rvec **x, rvec **v, real **r, gmx_bool bSrenew,
   /* Combine arrays */
   combine_atoms(atoms,atoms_solvt,*x,v?*v:NULL,x_solvt,v_solvt,
                &atoms_all,&x_all,&v_all);
-            
+
   /* Do neighboursearching step */
   do_nsgrid(stdout,bVerbose,box,x_all,atoms_all,max_vdw,oenv);
-  
+
   /* check solvent with solute */
   nlist = &(fr->nblists[0].nlist_sr[eNL_VDW]);
   fprintf(stderr,"nri = %d, nrj = %d\n",nlist->nri,nlist->nrj);
@@ -370,25 +374,25 @@ void add_conf(t_atoms *atoms, rvec **x, rvec **v, real **r, gmx_bool bSrenew,
       j0  = nlist->jindex[i];
       j1  = nlist->jindex[i+1];
       rvec_add(x_all[inr],fr->shift_vec[nlist->shift[i]],xi);
-      
+
       for(j=j0; (j<j1 && nremove<natoms_solvt); j++) {
        jnr = nlist->jjnr[j];
        copy_rvec(x_all[jnr],xj);
-       
+
        /* Check solvent-protein and solvent-solvent */
        is1 = inr-natoms_prot;
        is2 = jnr-natoms_prot;
-       
+
        /* Check if at least one of the atoms is a solvent that is not yet
         * listed for removal, and if both are solvent, that they are not in the
         * same residue.
         */
-       if ((!bSolSol && 
+       if ((!bSolSol &&
             bXor((is1 >= 0),(is2 >= 0)) &&  /* One atom is protein */
             ((is1 < 0) || ((is1 >= 0) && !remove[is1])) &&
             ((is2 < 0) || ((is2 >= 0) && !remove[is2]))) ||
-           
-           (bSolSol  && 
+
+           (bSolSol  &&
             (is1 >= 0) && (!remove[is1]) &&   /* is1 is solvent */
             (is2 >= 0) && (!remove[is2]) &&   /* is2 is solvent */
             (bInsert || /* when inserting also check inside the box */
@@ -397,7 +401,7 @@ void add_conf(t_atoms *atoms, rvec **x, rvec **v, real **r, gmx_bool bSrenew,
              ) &&
             (atoms_solvt->atom[is1].resind !=  /* Not the same residue */
              atoms_solvt->atom[is2].resind))) {
-         
+
          ntest++;
          rvec_sub(xi,xj,dx);
          n2 = norm2(dx);
@@ -426,10 +430,10 @@ void add_conf(t_atoms *atoms, rvec **x, rvec **v, real **r, gmx_bool bSrenew,
       fprintf(stderr," tested %d pairs, removed %d atoms.\n",ntest,nremove);
     }
   }
-  if (debug) 
+  if (debug)
     for(i=0; i<natoms_solvt; i++)
       fprintf(debug,"remove[%5d] = %s\n",i,bool_names[remove[i]]);
-      
+
   /* Search again, now with another cut-off */
   if (rshell > 0) {
     do_nsgrid(stdout,bVerbose,box,x_all,atoms_all,rshell,oenv);
@@ -441,21 +445,21 @@ void add_conf(t_atoms *atoms, rvec **x, rvec **v, real **r, gmx_bool bSrenew,
       inr = nlist->iinr[i];
       j0  = nlist->jindex[i];
       j1  = nlist->jindex[i+1];
-      
+
       for(j=j0; j<j1; j++) {
        jnr = nlist->jjnr[j];
-       
+
        /* Check solvent-protein and solvent-solvent */
        is1 = inr-natoms_prot;
        is2 = jnr-natoms_prot;
-       
+
        /* Check if at least one of the atoms is a solvent that is not yet
         * listed for removal, and if both are solvent, that they are not in the
         * same residue.
         */
-       if (is1>=0 && is2<0) 
+       if (is1>=0 && is2<0)
          mark_res(is1,keep,natoms_solvt,atoms_solvt->atom,&nkeep);
-       else if (is1<0 && is2>=0) 
+       else if (is1<0 && is2>=0)
          mark_res(is2,keep,natoms_solvt,atoms_solvt->atom,&nkeep);
       }
     }
@@ -472,11 +476,11 @@ void add_conf(t_atoms *atoms, rvec **x, rvec **v, real **r, gmx_bool bSrenew,
   } else {
     j     = 0;
     jnres = 0;
-    for (i=0; ((i<atoms_solvt->nr) && 
+    for (i=0; ((i<atoms_solvt->nr) &&
               ((max_sol == 0) || (jnres < max_sol))); i++) {
       if (!remove[i]) {
        j++;
-       if ((i == 0) || 
+       if ((i == 0) ||
            (atoms_solvt->atom[i].resind != atoms_solvt->atom[i-1].resind))
          jnres++;
       }
@@ -503,7 +507,7 @@ void add_conf(t_atoms *atoms, rvec **x, rvec **v, real **r, gmx_bool bSrenew,
     if (v) srenew(*v,       atoms->nr+j);
     srenew(*r,              atoms->nr+j);
   }
-  
+
   /* add the selected atoms_solvt to atoms */
   if (atoms->nr > 0) {
     resnr = atoms->resinfo[atoms->atom[atoms->nr-1].resind].nr;
@@ -514,7 +518,7 @@ void add_conf(t_atoms *atoms, rvec **x, rvec **v, real **r, gmx_bool bSrenew,
   nresadd = 0;
   for (i=0; i<atoms_solvt->nr; i++) {
     if (!remove[i]) {
-      if (prev == -1 || 
+      if (prev == -1 ||
          atoms_solvt->atom[i].resind != atoms_solvt->atom[prev].resind) {
        nresadd ++;
        atoms->nres++;
@@ -539,10 +543,10 @@ void add_conf(t_atoms *atoms, rvec **x, rvec **v, real **r, gmx_bool bSrenew,
   }
   if (bSrenew)
     srenew(atoms->resinfo,  atoms->nres+nresadd);
-  
+
   if (bVerbose)
     fprintf(stderr,"Added %d molecules\n",nresadd);
-  
+
   sfree(remove);
   done_atom(atoms_all);
   sfree(x_all);
index 623ad4c65f0aec3de25e9012b81ab6f7bad8cea9..3b7ebedc7727245ccddd87b0f4ad00dda901ec88 100644 (file)
@@ -170,7 +170,7 @@ void calc_pot(FILE *logf,t_commrec *cr,
              t_mdatoms *mdatoms,real pot[],matrix box,t_graph *graph)
 {
   static t_nrnb      nrnb;
-  real        lam=0,dum=0;
+  real        lam[efptNR],dum[efptNR];
   rvec        box_size;
   int         i,m;
 
@@ -187,9 +187,8 @@ void calc_pot(FILE *logf,t_commrec *cr,
   /* Do the actual neighbour searching and if twin range electrostatics
    * also do the calculation of long range forces and energies.
    */
-  
   ns(logf,fr,x,box,&mtop->groups,&(inputrec->opts),top,mdatoms,cr,
-     &nrnb,lam,&dum,&enerd->grpp,TRUE,FALSE,FALSE,NULL);
+     &nrnb,&lam[0],&dum[0],&enerd->grpp,TRUE,FALSE,FALSE,NULL);
   for(m=0; (m<DIM); m++)
     box_size[m] = box[m][m];
   for(i=0; (i<mdatoms->nr); i++)
@@ -218,7 +217,8 @@ FILE *init_calcpot(const char *log,const char *tpx,const char *table,
   gmx_localtop_t *ltop;
   double   t,t0,lam0;
   real     lam;
-  gmx_bool     bSA;
+  int      fep_state;
+  gmx_bool     bNEMD,bSA;
   int      traj=0,xtc_traj=0;
   t_state  *state;
   rvec     mutot;
@@ -247,7 +247,7 @@ FILE *init_calcpot(const char *log,const char *tpx,const char *table,
   }
 
   clear_rvec(mutot);
-  init_md(fplog,*cr,inputrec,oenv,&t,&t0,&lam,&lam0,
+  init_md(fplog,*cr,inputrec,oenv,&t,&t0,&lam,&fep_state,&lam0,
          &nrnb,mtop,NULL,-1,NULL,NULL,NULL,
          force_vir,shake_vir,mutot,&bSA,NULL,NULL,0);
 
index 52874843aec6114197e0a710c0e1137d720d1fea..605b297617ba670f67357c4661e4ebbadf38e8a1 100644 (file)
@@ -95,8 +95,7 @@ real derf;
  erfarg=(x-a[3])/(a[4]*a[4]);
         erfarg2=erfarg*erfarg;
         erfval=gmx_erf(erfarg)/2;
-        derf=(2./sqrt(M_PI))*(a[1]-a[2])/2*exp(-erfarg2)/(a[4]*a[4]);
-
+        derf=(2.0/sqrt(M_PI))*(a[1]-a[2])/2*exp(-erfarg2)/(a[4]*a[4]);
         *y=(a[1]+a[2])/2-(a[1]-a[2])*erfval;
         dyda[1]=1/2-erfval;
         dyda[2]=1/2+erfval;
index d2a71e0258f74f51c21e1428484abad6d138927b..6a49d389d7df6963591dcc268ae928348026bf9e 100644 (file)
@@ -145,7 +145,7 @@ typedef struct sample_range_t
     foreign lambda) */
 typedef struct sample_coll_t
 {
-    double native_lambda;  /* these should be the same for all samples in the */
+    double native_lambda;  /* these should be the same for all samples in the histogram?*/
     double foreign_lambda; /* collection */
     double temp; /* the temperature */
 
@@ -2672,14 +2672,13 @@ int gmx_bar(int argc,char *argv[])
         return 0;
     }
 
-#if 1
     if (sum_disc_err > prec)
     {
         prec=sum_disc_err;
         nd = ceil(-log10(prec));
         printf("WARNING: setting the precision to %g because that is the minimum\n         reasonable number, given the expected discretization error.\n", prec);
     }
-#endif
+
 
     sprintf(lamformat,"%%6.3f");
     sprintf( dgformat,"%%%d.%df",3+nd,nd);
@@ -2701,7 +2700,7 @@ int gmx_bar(int argc,char *argv[])
         fpb = xvgropen_type(opt2fn("-o",NFILE,fnm),"Free energy differences",
                             "\\lambda",buf,exvggtXYDY,oenv);
     }
-    
+
     fpi = NULL;
     if (opt2bSet("-oi",NFILE,fnm))
     {
index 1a98aac553b0141614548870f518f4c738ec316e..715d48c8f65e9429fa9e4e0c7dadeb5a95656f58 100644 (file)
@@ -708,7 +708,7 @@ int gmx_disre(int argc,char *argv[])
 
   mdatoms = init_mdatoms(fplog,&mtop,ir.efep!=efepNO);
   atoms2md(&mtop,&ir,0,NULL,0,mtop.natoms,mdatoms);
-  update_mdatoms(mdatoms,ir.init_lambda);
+  update_mdatoms(mdatoms,ir.fepvals->init_lambda);
   fr      = mk_forcerec();
   fprintf(fplog,"Made forcerec\n");
   init_forcerec(fplog,oenv,fr,NULL,&ir,&mtop,cr,box,FALSE,NULL,NULL,NULL,NULL,
index ccbfa431f43f216b4f26ebe436f0f6c4e08c6099..52ec7ffbd14d7aff53e061a015647f3a2aa4cbb7 100644 (file)
@@ -1,12 +1,12 @@
 /*  -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
  *
- * 
+ *
  *                This source code is part of
- * 
+ *
  *                 G   R   O   M   A   C   S
- * 
+ *
  *          GROningen MAchine for Chemical Simulations
- * 
+ *
  *                        VERSION 3.2.0
  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * If you want to redistribute modifications, please consider that
  * scientific software is very special. Version control is crucial -
  * bugs must be traceable. We will be happy to consider code for
  * inclusion in the official distribution, but derived work must not
  * be called official GROMACS. Details are found in the README & COPYING
  * files - if they are missing, get the official version at www.gromacs.org.
- * 
+ *
  * To help us fund GROMACS development, we humbly ask that you cite
  * the papers on the package - you can find them in the top README file.
- * 
+ *
  * For more info, check our website at http://www.gromacs.org
- * 
+ *
  * And Hey:
  * Green Red Orange Magenta Azure Cyan Skyblue
  */
@@ -58,7 +58,7 @@
 #include "viewit.h"
 #include "mtop_util.h"
 #include "gmx_ana.h"
-
+#include "mdebin.h"
 
 static real       minthird=-1.0/3.0,minsixth=-1.0/6.0;
 
@@ -91,7 +91,7 @@ static double mypow(double x,double y)
 {
   if (x > 0)
     return pow(x,y);
-  else 
+  else
     return 0.0;
 }
 
@@ -101,16 +101,16 @@ static int *select_it(int nre,char *nm[],int *nset)
   int  n,k,j,i;
   int  *set;
   gmx_bool bVerbose = TRUE;
-  
+
   if ((getenv("VERBOSE")) != NULL)
     bVerbose = FALSE;
-  
+
   fprintf(stderr,"Select the terms you want from the following list\n");
   fprintf(stderr,"End your selection with 0\n");
 
   if ( bVerbose ) {
     for(k=0; (k<nre); ) {
-      for(j=0; (j<4) && (k<nre); j++,k++) 
+      for(j=0; (j<4) && (k<nre); j++,k++)
        fprintf(stderr," %3d=%14s",k+1,nm[k]);
       fprintf(stderr,"\n");
     }
@@ -130,16 +130,16 @@ static int *select_it(int nre,char *nm[],int *nset)
   for(i=(*nset)=0; (i<nre); i++)
     if (bE[i])
       set[(*nset)++]=i;
+
   sfree(bE);
-  
+
   return set;
 }
 
 static void chomp(char *buf)
 {
   int len = strlen(buf);
-  
+
   while ((len > 0) && (buf[len-1] == '\n')) {
     buf[len-1] = '\0';
     len--;
@@ -156,16 +156,16 @@ static int *select_by_name(int nre,gmx_enxnm_t *nm,int *nset)
   const char *fm4="%3d  %-14s";
   const char *fm2="%3d  %-34s";
   char **newnm=NULL;
-  
+
   if ((getenv("VERBOSE")) != NULL)
     bVerbose = FALSE;
+
   fprintf(stderr,"\n");
   fprintf(stderr,"Select the terms you want from the following list by\n");
   fprintf(stderr,"selecting either (part of) the name or the number or a combination.\n");
   fprintf(stderr,"End your selection with an empty line or a zero.\n");
   fprintf(stderr,"-------------------------------------------------------------------\n");
-  
+
   snew(newnm,nre);
   j = 0;
   for(k=0; k<nre; k++) {
@@ -206,17 +206,17 @@ static int *select_by_name(int nre,gmx_enxnm_t *nm,int *nset)
   if ( bVerbose ) {
     fprintf(stderr,"\n\n");
   }
-  
+
   snew(bE,nre);
-  
+
   bEOF = FALSE;
   while (!bEOF && (fgets2(buf,STRLEN-1,stdin))) {
     /* Remove newlines */
     chomp(buf);
-    
+
     /* Remove spaces */
     trim(buf);
-    
+
     /* Empty line means end of input */
     bEOF = (strlen(buf) == 0);
     if (!bEOF) {
@@ -267,26 +267,37 @@ static int *select_by_name(int nre,gmx_enxnm_t *nm,int *nset)
       } while (!bEOF && (ptr && (strlen(ptr) > 0)));
     }
   }
-  
+
   snew(set,nre);
   for(i=(*nset)=0; (i<nre); i++)
     if (bE[i])
       set[(*nset)++]=i;
+
   sfree(bE);
-  
+
   if (*nset == 0)
     gmx_fatal(FARGS,"No energy terms selected");
 
-  for(i=0; (i<nre); i++) 
+  for(i=0; (i<nre); i++)
     sfree(newnm[i]);
   sfree(newnm);
-  
+
   return set;
 }
 
+static void get_dhdl_parms(const char *topnm, t_inputrec *ir)
+{
+    gmx_mtop_t mtop;
+    int        natoms;
+    t_iatom    *iatom;
+    matrix     box;
+
+    /* all we need is the ir to be able to write the label */
+    read_tpx(topnm,ir,box,&natoms,NULL,NULL,NULL,&mtop);
+}
+
 static void get_orires_parms(const char *topnm,
-                            int *nor,int *nex,int **label,real **obs)
+                               int *nor,int *nex,int **label,real **obs)
 {
   gmx_mtop_t mtop;
   gmx_localtop_t *top;
@@ -302,12 +313,12 @@ static void get_orires_parms(const char *topnm,
 
   ip       = top->idef.iparams;
   iatom    = top->idef.il[F_ORIRES].iatoms;
-  
+
   /* Count how many distance restraint there are... */
   nb = top->idef.il[F_ORIRES].nr;
   if (nb == 0)
     gmx_fatal(FARGS,"No orientation restraints in topology!\n");
-  
+
   *nor = nb/3;
   *nex = 0;
   snew(*label,*nor);
@@ -344,17 +355,17 @@ static int get_bounds(const char *topnm,
 
   functype = top->idef.functype;
   ip       = top->idef.iparams;
-  
+
   /* Count how many distance restraint there are... */
   nb=top->idef.il[F_DISRES].nr;
   if (nb == 0)
     gmx_fatal(FARGS,"No distance restraints in topology!\n");
-  
+
   /* Allocate memory */
   snew(b,nb);
   snew(ind,nb);
   snew(pair,nb+1);
-  
+
   /* Fill the bound array */
   nb=0;
   for(i=0; (i<top->idef.ntypes); i++) {
@@ -368,7 +379,7 @@ static int get_bounds(const char *topnm,
     }
   }
   *bounds = b;
-  
+
   /* Fill the index array */
   label1  = -1;
   disres  = &(top->idef.il[F_DISRES]);
@@ -379,7 +390,7 @@ static int get_bounds(const char *topnm,
     natom = interaction_function[ftype].nratoms+1;
     if (label1 != top->idef.iparams[type].disres.label) {
       pair[j] = k;
-      label1  = top->idef.iparams[type].disres.label; 
+      label1  = top->idef.iparams[type].disres.label;
       j ++;
     }
     k++;
@@ -392,7 +403,7 @@ static int get_bounds(const char *topnm,
 
   *index   = ind;
   *dr_pair = pair;
-  
+
   return nb;
 }
 
@@ -402,7 +413,7 @@ static void calc_violations(real rt[],real rav3[],int nb,int index[],
   const   real sixth=1.0/6.0;
   int     i,j;
   double  rsum,rav,sumaver,sumt;
-  
+
   sumaver = 0;
   sumt    = 0;
   for(i=0; (i<nb); i++) {
@@ -416,7 +427,7 @@ static void calc_violations(real rt[],real rav3[],int nb,int index[],
     }
     rsum    = max(0.0,mypow(rsum,-sixth)-bounds[i]);
     rav     = max(0.0,mypow(rav, -sixth)-bounds[i]);
-    
+
     sumt    += rsum;
     sumaver += rav;
   }
@@ -442,7 +453,7 @@ static void analyse_disre(const char *voutfn,    int nframes,
             sumaver);
     fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",
             sumt);
-#endif             
+#endif
     vout=xvgropen(voutfn,"r\\S-3\\N average violations","DR Index","nm",
             oenv);
     sum  = 0.0;
@@ -450,8 +461,8 @@ static void analyse_disre(const char *voutfn,    int nframes,
     for(i=0; (i<nbounds); i++) {
         /* Do ensemble averaging */
         sumaver = 0;
-        for(j=pair[i]; (j<pair[i+1]); j++) 
-            sumaver += sqr(violaver[j]/nframes); 
+        for(j=pair[i]; (j<pair[i+1]); j++)
+            sumaver += sqr(violaver[j]/nframes);
         sumaver = max(0.0,mypow(sumaver,minsixth)-bounds[i]);
 
         sumt   += sumaver;
@@ -555,7 +566,7 @@ static void add_ee_sum(ee_sum_t *ees,double sum,int np)
 static void add_ee_av(ee_sum_t *ees)
 {
     double av;
-    
+
     av = ees->sum/ees->np;
     ees->sav  += av;
     ees->sav2 += av*av;
@@ -626,7 +637,7 @@ static void calc_averages(int nset,enerdata_t *edat,int nbmin,int nbmax)
     for(i=0; i<nset; i++)
     {
         ed = &edat->s[i];
-        
+
         sum  = 0;
         sum2 = 0;
         np   = 0;
@@ -664,7 +675,7 @@ static void calc_averages(int nset,enerdata_t *edat,int nbmin,int nbmax)
                 sump  = ed->ener[f];
                 sum2 += dsqr(sump);
             }
-            
+
             /* sum has to be increased after sum2 */
             np  += p;
             sum += sump;
@@ -771,14 +782,14 @@ static enerdata_t *calc_sum(int nset,enerdata_t *edat,int nbmin,int nbmax)
     enerdat_t *s;
     int f,i;
     double sum;
-    
+
     snew(esum,1);
     *esum = *edat;
     snew(esum->s,1);
     s = &esum->s[0];
     snew(s->ener,esum->nframes);
     snew(s->es  ,esum->nframes);
-    
+
     s->bExactStat = TRUE;
     s->slope      = 0;
     for(i=0; i<nset; i++)
@@ -789,7 +800,7 @@ static enerdata_t *calc_sum(int nset,enerdata_t *edat,int nbmin,int nbmax)
         }
         s->slope += edat->s[i].slope;
     }
-    
+
     for(f=0; f<edat->nframes; f++)
     {
         sum = 0;
@@ -806,7 +817,7 @@ static enerdata_t *calc_sum(int nset,enerdata_t *edat,int nbmin,int nbmax)
         s->es[f].sum  = sum;
         s->es[f].sum2 = 0;
     }
-    
+
     calc_averages(1,esum,nbmin,nbmax);
 
     return esum;
@@ -816,7 +827,7 @@ static char *ee_pr(double ee,char *buf)
 {
     char   tmp[100];
     double rnd;
-    
+
     if (ee < 0)
     {
         sprintf(buf,"%s","--");
@@ -841,16 +852,16 @@ static void remove_drift(int nset,int nbmin,int nbmax,real dt,enerdata_t *edat)
 
     edat->npoints = edat->nframes;
     edat->nsteps = edat->nframes;
-        
+
     for(k=0; (k<5); k++)
     {
-        for(i=0; (i<nset); i++) 
+        for(i=0; (i<nset); i++)
         {
             delta = edat->s[i].slope*dt;
-            
+
             if (NULL != debug)
                 fprintf(debug,"slope for set %d is %g\n",i,edat->s[i].slope);
-            
+
             for(j=0; (j<edat->nframes); j++)
             {
                 edat->s[i].ener[j]   -= j*delta;
@@ -874,7 +885,7 @@ static void calc_fluctuation_props(FILE *fp,
     enum { eVol, eEnth, eTemp, eEtot, eNR };
     const char *my_ener[] = { "Volume", "Enthalpy", "Temperature", "Total Energy" };
     int ii[eNR];
-    
+
     NANO3 = NANO*NANO*NANO;
     if (!bDriftCorr)
     {
@@ -886,9 +897,9 @@ static void calc_fluctuation_props(FILE *fp,
     {
         remove_drift(nset,nbmin,nbmax,dt,edat);
     }
-    for(i=0; (i<eNR); i++) 
+    for(i=0; (i<eNR); i++)
     {
-        for(ii[i]=0; (ii[i]<nset && 
+        for(ii[i]=0; (ii[i]<nset &&
                       (gmx_strcasecmp(leg[ii[i]],my_ener[i]) != 0)); ii[i]++)
             ;
 /*        if (ii[i] < nset)
@@ -896,7 +907,7 @@ static void calc_fluctuation_props(FILE *fp,
 */  }
     /* Compute it all! */
     vvhh = alpha = kappa = cp = dcp = cv = NOTSET;
-    
+
     /* Temperature */
     tt = NOTSET;
     if (ii[eTemp] < nset)
@@ -959,7 +970,7 @@ static void calc_fluctuation_props(FILE *fp,
 
         if (debug != NULL)
         {
-            if (varv != NOTSET)    
+            if (varv != NOTSET)
                 fprintf(fp,"varv  =  %10g (m^6)\n",varv*AVOGADRO/nmol);
             if (vvhh != NOTSET)
                 fprintf(fp,"vvhh  =  %10g (m^3 J)\n",vvhh);
@@ -991,7 +1002,7 @@ static void calc_fluctuation_props(FILE *fp,
                     dcp);
         please_cite(fp,"Allen1987a");
     }
-    else 
+    else
     {
         fprintf(fp,"You should select the temperature in order to obtain fluctuation properties.\n");
     }
@@ -1032,12 +1043,12 @@ static void analyse_ener(gmx_bool bCorr,const char *corrfn,
   else {
     /* Calculate the time difference */
     delta_t = t - start_t;
-    
+
     fprintf(stdout,"\nStatistics over %s steps [ %.4f through %.4f ps ], %d data sets\n",
            gmx_step_str(nsteps,buf),start_t,t,nset);
 
     calc_averages(nset,edat,nbmin,nbmax);
-    
+
     if (bSum) {
         esum = calc_sum(nset,edat,nbmin,nbmax);
     }
@@ -1056,7 +1067,7 @@ static void analyse_ener(gmx_bool bCorr,const char *corrfn,
        }
       }
     }
-    
+
     if (nnotexact == 0) {
       fprintf(stdout,"All statistics are over %s points\n",
              gmx_step_str(edat->npoints,buf));
@@ -1084,7 +1095,7 @@ static void analyse_ener(gmx_bool bCorr,const char *corrfn,
     else
       fprintf(stdout,"\n");
     fprintf(stdout,"-------------------------------------------------------------------------------\n");
-    
+
     /* Initiate locals, only used with -sum */
     expEtot=0;
     if (bFee) {
@@ -1101,9 +1112,9 @@ static void analyse_ener(gmx_bool bCorr,const char *corrfn,
        for(j=0; (j<edat->nframes); j++) {
          expE += exp(beta*(edat->s[i].ener[j] - aver)/nmol);
        }
-       if (bSum) 
+       if (bSum)
          expEtot+=expE/edat->nframes;
-       
+
        fee[i] = log(expE/edat->nframes)/beta + aver/nmol;
       }
       if (strstr(leg[i],"empera") != NULL) {
@@ -1112,7 +1123,7 @@ static void analyse_ener(gmx_bool bCorr,const char *corrfn,
        Vaver= aver;
       } else if (strstr(leg[i],"essure") != NULL) {
        Pres = aver;
-      } 
+      }
       if (bIsEner[i]) {
        pr_aver   = aver/nmol-ezero;
        pr_stddev = stddev/nmol;
@@ -1133,9 +1144,9 @@ static void analyse_ener(gmx_bool bCorr,const char *corrfn,
 
       fprintf(stdout,"%-24s %10g %10s %10g %10g",
              leg[i],pr_aver,ee_pr(pr_errest,eebuf),pr_stddev,totaldrift);
-      if (bFee) 
+      if (bFee)
        fprintf(stdout,"  %10g",fee[i]);
-      
+
       fprintf(stdout,"  (%s)\n",enm[set[i]].unit);
 
       if (bFluct) {
@@ -1149,13 +1160,13 @@ static void analyse_ener(gmx_bool bCorr,const char *corrfn,
              "Total",esum->s[0].av/nmol,ee_pr(esum->s[0].ee/nmol,eebuf),
              "--",totaldrift/nmol,enm[set[0]].unit);
       /* pr_aver,pr_stddev,a,totaldrift */
-      if (bFee) 
+      if (bFee)
        fprintf(stdout,"  %10g  %10g\n",
                log(expEtot)/beta + esum->s[0].av/nmol,log(expEtot)/beta);
       else
        fprintf(stdout,"\n");
     }
-      
+
     /* Do correlation function */
     if (edat->nframes > 1)
     {
@@ -1170,10 +1181,10 @@ static void analyse_ener(gmx_bool bCorr,const char *corrfn,
       real factor;
       real **eneset;
       real **enesum;
-    
+
       /* Assume pressure tensor is in Pxx Pxy Pxz Pyx Pyy Pyz Pzx Pzy Pzz */
-      
-      /* Symmetrise tensor! (and store in first three elements) 
+
+      /* Symmetrise tensor! (and store in first three elements)
        * And subtract average pressure!
        */
       snew(eneset,12);
@@ -1196,34 +1207,34 @@ static void analyse_ener(gmx_bool bCorr,const char *corrfn,
        enesum[1][i] = 0.5*(edat->s[2].es[i].sum+edat->s[6].es[i].sum);
        enesum[2][i] = 0.5*(edat->s[5].es[i].sum+edat->s[7].es[i].sum);
       }
-      
+
       einstein_visco("evisco.xvg","eviscoi.xvg",
                     3,edat->nframes,enesum,Vaver,Temp,nsteps,time,oenv);
-      
+
       /*do_autocorr(corrfn,buf,nenergy,3,eneset,Dt,eacNormal,TRUE);*/
       /* Do it for shear viscosity */
       strcpy(buf,"Shear Viscosity");
       low_do_autocorr(corrfn,oenv,buf,edat->nframes,3,
                      (edat->nframes+1)/2,eneset,Dt,
                      eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
-       
+
       /* Now for bulk viscosity */
       strcpy(buf,"Bulk Viscosity");
       low_do_autocorr(corrfn,oenv,buf,edat->nframes,1,
                      (edat->nframes+1)/2,&(eneset[11]),Dt,
                      eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
-      
+
       factor = (Vaver*1e-26/(BOLTZMANN*Temp))*Dt;
       fp=xvgropen(visfn,buf,"Time (ps)","\\8h\\4 (cp)",oenv);
       xvgr_legend(fp,asize(leg),leg,oenv);
-      
+
       /* Use trapezium rule for integration */
       integral = 0;
       intBulk  = 0;
       nout = get_acfnout();
       if ((nout < 2) || (nout >= edat->nframes/2))
           nout = edat->nframes/2;
-      for(i=1; (i<nout); i++) 
+      for(i=1; (i<nout); i++)
       {
           integral += 0.5*(eneset[0][i-1]  + eneset[0][i])*factor;
           intBulk  += 0.5*(eneset[11][i-1] + eneset[11][i])*factor;
@@ -1259,12 +1270,12 @@ static void print1(FILE *fp,gmx_bool bDp,real e)
     fprintf(fp,"  %10.6f",e);
 }
 
-static void fec(const char *ene2fn, const char *runavgfn, 
-               real reftemp, int nset, int set[], char *leg[], 
+static void fec(const char *ene2fn, const char *runavgfn,
+               real reftemp, int nset, int set[], char *leg[],
                enerdata_t *edat, double time[],
                 const output_env_t oenv)
 {
-  const char* ravgleg[] = { "\\8D\\4E = E\\sB\\N-E\\sA\\N", 
+  const char* ravgleg[] = { "\\8D\\4E = E\\sB\\N-E\\sA\\N",
                            "<e\\S-\\8D\\4E/kT\\N>\\s0..t\\N" };
   FILE *fp;
   ener_file_t enx;
@@ -1277,29 +1288,29 @@ static void fec(const char *ene2fn, const char *runavgfn,
   gmx_enxnm_t *enm=NULL;
   t_enxframe *fr;
   char buf[22];
-  
+
   /* read second energy file */
   snew(fr,1);
   enm = NULL;
   enx = open_enx(ene2fn,"r");
   do_enxnms(enx,&(fr->nre),&enm);
-  
+
   snew(eneset2,nset+1);
   nenergy2=0;
   maxenergy=0;
   timecheck=0;
   do {
-    /* This loop searches for the first frame (when -b option is given), 
+    /* This loop searches for the first frame (when -b option is given),
      * or when this has been found it reads just one energy frame
      */
     do {
       bCont = do_enx(enx,fr);
-      
+
       if (bCont)
        timecheck = check_times(fr->t);
-      
+
     } while (bCont && (timecheck < 0));
-    
+
     /* Store energies for analysis afterwards... */
     if ((timecheck == 0) && bCont) {
       if (fr->nre > 0) {
@@ -1317,14 +1328,14 @@ static void fec(const char *ene2fn, const char *runavgfn,
       }
     }
   } while (bCont && (timecheck == 0));
-  
+
   /* check */
   if (edat->nframes != nenergy2) {
     fprintf(stderr,"\nWARNING file length mismatch %d!=%d\n",
            edat->nframes,nenergy2);
   }
   nenergy = min(edat->nframes,nenergy2);
-  
+
   /* calculate fe difference dF = -kT ln < exp(-(E_B-E_A)/kT) >_A */
   fp=NULL;
   if (runavgfn) {
@@ -1344,7 +1355,7 @@ static void fec(const char *ene2fn, const char *runavgfn,
       dE = eneset2[i][j] - edat->s[i].ener[j];
       sum += exp(-dE*beta);
       if (fp)
-       fprintf(fp,"%10g %10g %10g\n", 
+       fprintf(fp,"%10g %10g %10g\n",
                time[j], dE, -BOLTZ*reftemp*log(sum/(j+1)) );
     }
     aver = -BOLTZ*reftemp*log(sum/nenergy);
@@ -1355,9 +1366,8 @@ static void fec(const char *ene2fn, const char *runavgfn,
 }
 
 
-static void do_dhdl(t_enxframe *fr, FILE **fp_dhdl, const char *filename,
-                    int *blocks, int *hists, int *samples, int *nlambdas,
-                    const output_env_t oenv)
+static void do_dhdl(t_enxframe *fr, t_inputrec *ir, FILE **fp_dhdl, const char *filename, gmx_bool bDp,
+                    int *blocks, int *hists, int *samples, int *nlambdas, const output_env_t oenv)
 {
     const char *dhdl="dH/d\\lambda",*deltag="\\DeltaH",*lambda="\\lambda";
     char title[STRLEN],label_x[STRLEN],label_y[STRLEN], legend[STRLEN];
@@ -1414,37 +1424,24 @@ static void do_dhdl(t_enxframe *fr, FILE **fp_dhdl, const char *filename,
     {
         if (nblock_dh>0)
         {
-            sprintf(title,"%s, %s",dhdl,deltag);
-            sprintf(label_x,"%s (%s)","Time",unit_time);
-            sprintf(label_y,"(%s)",unit_energy);
+            /* we have standard, non-histogram data -- call open_dhdl to open the file */
+            *fp_dhdl=open_dhdl(filename,ir,oenv);
         }
         else
         {
             sprintf(title,"N(%s)",deltag);
             sprintf(label_x,"%s (%s)",deltag,unit_energy);
             sprintf(label_y,"Samples");
-        }
-        *fp_dhdl=xvgropen_type(filename, title, label_x, label_y, exvggtXNY, 
-                               oenv);
-        if (! changing_lambda)
-        {
+            *fp_dhdl=xvgropen_type(filename, title, label_x, label_y, exvggtXNY,oenv);
             sprintf(buf,"T = %g (K), %s = %g", temp, lambda, start_lambda);
+            xvgr_subtitle(*fp_dhdl,buf,oenv);
         }
-        else
-        {
-            sprintf(buf,"T = %g (K)", temp);
-        }
-        xvgr_subtitle(*fp_dhdl,buf,oenv);
-        first=TRUE;
     }
 
-
-
     (*hists)+=nblock_hist;
     (*blocks)+=nblock_dh;
     (*nlambdas) = nblock_hist+nblock_dh;
 
-
     /* write the data */
     if (nblock_hist > 0)
     {
@@ -1480,27 +1477,27 @@ static void do_dhdl(t_enxframe *fr, FILE **fp_dhdl, const char *filename,
                     if (!derivative)
                     {
                         sprintf(legend, "N(%s(%s=%g) | %s=%g)",
-                                deltag, lambda, foreign_lambda, 
+                                deltag, lambda, foreign_lambda,
                                 lambda, start_lambda);
                     }
                     else
                     {
-                        sprintf(legend, "N(%s | %s=%g)", 
+                        sprintf(legend, "N(%s | %s=%g)",
                                 dhdl, lambda, start_lambda);
                     }
-                                       
+
                     lg[0]=legend;
-                    xvgr_new_dataset(*fp_dhdl, setnr, 1, lg, oenv); 
+                    xvgr_new_dataset(*fp_dhdl, setnr, 1, lg, oenv);
                     setnr++;
                     for(k=0;k<blk->sub[j+2].nr;k++)
                     {
                         int hist;
                         double xmin, xmax;
-                    
+
                         hist=blk->sub[j+2].ival[k];
                         xmin=(x0+k)*dx;
                         xmax=(x0+k+1)*dx;
-                        fprintf(*fp_dhdl,"%g %d\n%g %d\n", xmin, hist, 
+                        fprintf(*fp_dhdl,"%g %d\n%g %d\n", xmin, hist,
                                 xmax, hist);
                         sum+=hist;
                     }
@@ -1512,7 +1509,6 @@ static void do_dhdl(t_enxframe *fr, FILE **fp_dhdl, const char *filename,
                 }
             }
         }
-
         (*samples) += (int)(sum/nblock_hist);
     }
     else
@@ -1522,52 +1518,13 @@ static void do_dhdl(t_enxframe *fr, FILE **fp_dhdl, const char *filename,
         char **setnames=NULL;
         int nnames=nblock_dh;
 
-        if (changing_lambda)
-        {
-            nnames++;
-        }
-        if (first)
-        {
-            snew(setnames, nnames);
-        }
-        j=0;
-
-        if ( changing_lambda && first)
-        {
-            /* lambda is a plotted value */
-            setnames[j]=gmx_strdup(lambda);
-            j++;
-        }
-
-
         for(i=0;i<fr->nblock;i++)
         {
             t_enxblock *blk=&(fr->block[i]);
             if (blk->id == enxDH)
             {
-                if (first)
-                {
-                    /* do the legends */
-                    int derivative;
-                    double foreign_lambda;
-
-                    derivative=blk->sub[0].ival[0];
-                    foreign_lambda=blk->sub[1].dval[0];
-
-                    if (derivative)
-                    {
-                        sprintf(buf, "%s %s %g",dhdl,lambda,start_lambda);
-                    }
-                    else
-                    {
-                        sprintf(buf, "%s %s %g",deltag,lambda, foreign_lambda);
-                    }
-                    setnames[j] = gmx_strdup(buf);
-                    j++;
-                }
-
                 if (len == 0)
-                {   
+                {
                     len=blk->sub[2].nr;
                 }
                 else
@@ -1579,30 +1536,14 @@ static void do_dhdl(t_enxframe *fr, FILE **fp_dhdl, const char *filename,
                 }
             }
         }
-
-
-        if (first)
-        {
-            xvgr_legend(*fp_dhdl, nblock_dh, (const char**)setnames, oenv);
-            setnr += nblock_dh;
-            for(i=0;i<nblock_dh;i++)
-            {
-                sfree(setnames[i]);
-            }
-            sfree(setnames);
-        }
-
         (*samples) += len;
+
         for(i=0;i<len;i++)
         {
             double time=start_time + delta_time*i;
 
-            fprintf(*fp_dhdl,"%.4f", time);
-            if (fabs(delta_lambda) > 1e-9)
-            {
-                double lambda_now=i*delta_lambda + start_lambda;
-                fprintf(*fp_dhdl,"  %.4f", lambda_now);
-            }
+            fprintf(*fp_dhdl,"%.4f ", time);
+
             for(j=0;j<fr->nblock;j++)
             {
                 t_enxblock *blk=&(fr->block[j]);
@@ -1617,7 +1558,20 @@ static void do_dhdl(t_enxframe *fr, FILE **fp_dhdl, const char *filename,
                     {
                         value=blk->sub[2].dval[i];
                     }
-                    fprintf(*fp_dhdl,"  %g", value);
+                    /* we need to decide which data type it is based on the count*/
+
+                    if (j==1 && ir->bExpanded)
+                    {
+                        fprintf(*fp_dhdl,"%4d", (int)value);   /* if expanded ensembles and zero, this is a state value, it's an integer. We need a cleaner conditional than if j==1! */
+                    } else {
+                        if (bDp) {
+                            fprintf(*fp_dhdl," %#.12g", value);   /* print normal precision */
+                        }
+                        else
+                        {
+                            fprintf(*fp_dhdl," %#.8g", value);   /* print normal precision */
+                        }
+                    }
                 }
             }
             fprintf(*fp_dhdl, "\n");
@@ -1629,11 +1583,11 @@ static void do_dhdl(t_enxframe *fr, FILE **fp_dhdl, const char *filename,
 int gmx_energy(int argc,char *argv[])
 {
   const char *desc[] = {
-    
+
     "[TT]g_energy[tt] extracts energy components or distance restraint",
     "data from an energy file. The user is prompted to interactively",
     "select the desired energy terms.[PAR]",
-    
+
     "Average, RMSD, and drift are calculated with full precision from the",
     "simulation (see printed manual). Drift is calculated by performing",
     "a least-squares fit of the data to a straight line. The reported total drift",
@@ -1650,7 +1604,7 @@ int gmx_energy(int argc,char *argv[])
     "energy values.[PAR]",
 
     "The term fluctuation gives the RMSD around the least-squares fit.[PAR]",
-    
+
     "Some fluctuation-dependent properties can be calculated provided",
     "the correct energy terms are selected. The following properties",
     "will be computed:[BR]",
@@ -1706,14 +1660,14 @@ int gmx_energy(int argc,char *argv[])
     "  [GRK]Delta[grk] S(N,V,T) = S(N,V,T) - S[SUB]idealgas[sub](N,V,T) = ([CHEVRON]U[SUB]pot[sub][chevron] - [GRK]Delta[grk] A)/T[BR]",
     "  [GRK]Delta[grk] S(N,p,T) = S(N,p,T) - S[SUB]idealgas[sub](N,p,T) = ([CHEVRON]U[SUB]pot[sub][chevron] + pV - [GRK]Delta[grk] G)/T",
     "[PAR]",
-    
+
     "When a second energy file is specified ([TT]-f2[tt]), a free energy",
     "difference is calculated [BR] dF = -kT [LN][CHEVRON][EXP]-(E[SUB]B[sub]-E[SUB]A[sub])/kT[exp][chevron][SUB]A[sub][ln] ,",
     "where E[SUB]A[sub] and E[SUB]B[sub] are the energies from the first and second energy",
     "files, and the average is over the ensemble A. The running average",
     "of the free energy difference is printed to a file specified by [TT]-ravg[tt].",
     "[BB]Note[bb] that the energies must both be calculated from the same trajectory."
-    
+
   };
   static gmx_bool bSum=FALSE,bFee=FALSE,bPrAll=FALSE,bFluct=FALSE,bDriftCorr=FALSE;
   static gmx_bool bDp=FALSE,bMutot=FALSE,bOrinst=FALSE,bOvec=FALSE;
@@ -1732,7 +1686,7 @@ int gmx_energy(int argc,char *argv[])
       "Print energies in high precision" },
     { "-nbmin", FALSE, etINT, {&nbmin},
       "Minimum number of blocks for error estimate" },
-    { "-nbmax", FALSE, etINT, {&nbmax}, 
+    { "-nbmax", FALSE, etINT, {&nbmax},
       "Maximum number of blocks for error estimate" },
     { "-mutot",FALSE, etBOOL, {&bMutot},
       "Compute the total dipole moment from the components" },
@@ -1760,7 +1714,7 @@ int gmx_energy(int argc,char *argv[])
     "Pres-YZ", "Pres-ZX", "Pres-ZY", "Pres-ZZ", "Temperature",
     "Volume",  "Pressure"
   };
-  
+
   FILE       *out=NULL,*fp_pairs=NULL,*fort=NULL,*fodt=NULL,*foten=NULL;
   FILE       *fp_dhdl=NULL;
   FILE       **drout;
@@ -1823,14 +1777,14 @@ int gmx_energy(int argc,char *argv[])
 #define NFILE asize(fnm)
   int     npargs;
   t_pargs *ppa;
-  
+
   CopyRight(stderr,argv[0]);
   npargs = asize(pa);
   ppa    = add_acf_pargs(&npargs,pa);
   parse_common_args(&argc,argv,
                     PCA_CAN_VIEW | PCA_CAN_BEGIN | PCA_CAN_END | PCA_BE_NICE,
                    NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL,&oenv);
-  
+
   bDRAll = opt2bSet("-pairs",NFILE,fnm);
   bDisRe = opt2bSet("-viol",NFILE,fnm) || bDRAll;
   bORA   = opt2bSet("-ora",NFILE,fnm);
@@ -1849,10 +1803,10 @@ int gmx_energy(int argc,char *argv[])
   do_enxnms(fp,&nre,&enm);
 
   Vaver = -1;
-  
+
   bVisco = opt2bSet("-vis",NFILE,fnm);
-  
-  if (!bDisRe && !bDHDL) 
+
+  if ((!bDisRe) && (!bDHDL))
   {
       if (bVisco) {
           nset=asize(setnm);
@@ -1879,7 +1833,7 @@ int gmx_energy(int argc,char *argv[])
               }
           }
       }
-      else 
+      else
       {
           set=select_by_name(nre,enm,&nset);
       }
@@ -2019,296 +1973,286 @@ int gmx_energy(int argc,char *argv[])
       snew(violaver,npairs);
       out=xvgropen(opt2fn("-o",NFILE,fnm),"Sum of Violations",
                    "Time (ps)","nm",oenv);
-      xvgr_legend(out,2,drleg,oenv);  
-      if (bDRAll) { 
+      xvgr_legend(out,2,drleg,oenv);
+      if (bDRAll) {
           fp_pairs=xvgropen(opt2fn("-pairs",NFILE,fnm),"Pair Distances",
                             "Time (ps)","Distance (nm)",oenv);
           if (output_env_get_print_xvgr_codes(oenv))
               fprintf(fp_pairs,"@ subtitle \"averaged (tau=%g) and instantaneous\"\n",
                       ir.dr_tau);
       }
+  } else if (bDHDL) {
+      get_dhdl_parms(ftp2fn(efTPX,NFILE,fnm),&ir);
   }
 
-
-  /* Initiate energies and set them to zero */
-  edat.nsteps  = 0;
-  edat.npoints = 0;
-  edat.nframes = 0;
-  edat.step    = NULL;
-  edat.steps   = NULL;
-  edat.points  = NULL;
-  snew(edat.s,nset);
-  
-  /* Initiate counters */
-  teller       = 0;
-  teller_disre = 0;
-  bFoundStart  = FALSE;
-  start_step   = 0;
-  start_t      = 0;
-  do {
-    /* This loop searches for the first frame (when -b option is given), 
-     * or when this has been found it reads just one energy frame
-     */
-    do {
-      bCont = do_enx(fp,&(frame[NEXT]));
-      
-      if (bCont) {
-       timecheck = check_times(frame[NEXT].t);
-      }      
-    } while (bCont && (timecheck < 0));
-    
-    if ((timecheck == 0) && bCont) {
-      /* We read a valid frame, so we can use it */
-      fr = &(frame[NEXT]);
-      
-      if (fr->nre > 0) {
-       /* The frame contains energies, so update cur */
-       cur  = NEXT;
-
-               if (edat.nframes % 1000 == 0)
-            {
-                srenew(edat.step,edat.nframes+1000);
-                memset(&(edat.step[edat.nframes]),0,1000*sizeof(edat.step[0]));
-                srenew(edat.steps,edat.nframes+1000);
-                memset(&(edat.steps[edat.nframes]),0,1000*sizeof(edat.steps[0]));
-                srenew(edat.points,edat.nframes+1000);
-                memset(&(edat.points[edat.nframes]),0,1000*sizeof(edat.points[0]));
-                for(i=0; i<nset; i++)
-                {
-                    srenew(edat.s[i].ener,edat.nframes+1000);
-                    memset(&(edat.s[i].ener[edat.nframes]),0,
-                           1000*sizeof(edat.s[i].ener[0]));
-
-                    srenew(edat.s[i].es  ,edat.nframes+1000);
-                    memset(&(edat.s[i].es[edat.nframes]),0,
-                           1000*sizeof(edat.s[i].es[0]));
-                }
-            }
-
-               nfr = edat.nframes;
-            edat.step[nfr] = fr->step;
-
-            if (!bFoundStart)
-            {
-                bFoundStart = TRUE;
-                /* Initiate the previous step data */
-                start_step = fr->step;
-                start_t    = fr->t;
-                /* Initiate the energy sums */
-                edat.steps[nfr]  = 1;
-                edat.points[nfr] = 1;
-                for(i=0; i<nset; i++)
-                {
-                    sss = set[i];
-                    edat.s[i].es[nfr].sum  = fr->ener[sss].e;
-                    edat.s[i].es[nfr].sum2 = 0;
-                }
-                edat.nsteps  = 1;
-                edat.npoints = 1;
-            }
-            else
-            {
-                edat.steps[nfr] = fr->nsteps;
-                {
-                    if (fr->step - start_step + 1 == edat.nsteps + fr->nsteps)
-                    {
-                        if (fr->nsum <= 1)
-                        {
-                            edat.points[nfr] = 1;
-                            for(i=0; i<nset; i++)
-                            {
-                                sss = set[i];
-                                edat.s[i].es[nfr].sum  = fr->ener[sss].e;
-                                edat.s[i].es[nfr].sum2 = 0;
-                            }
-                            edat.npoints += 1;
-                        }
-                        else
-                        {
-                            edat.points[nfr] = fr->nsum;
-                            for(i=0; i<nset; i++)
-                            {
-                                sss = set[i];
-                                edat.s[i].es[nfr].sum  = fr->ener[sss].esum;
-                                edat.s[i].es[nfr].sum2 = fr->ener[sss].eav;
-                            }
-                            edat.npoints += fr->nsum;
-                        }
-                    }
-                    else
-                    {
-                        /* The interval does not match fr->nsteps:
-                         * can not do exact averages.
-                         */
-                        edat.npoints = 0;
-                    }
-                    edat.nsteps = fr->step - start_step + 1;
-                }
-            }
-            for(i=0; i<nset; i++)
-            {
-                edat.s[i].ener[nfr] = fr->ener[set[i]].e;
-            }
-      }
-      /*
-       * Define distance restraint legends. Can only be done after
-       * the first frame has been read... (Then we know how many there are)
-       */
-      blk_disre=find_block_id_enxframe(fr, enxDISRE, NULL);
-      if (bDisRe && bDRAll && !leg && blk_disre) 
-      {
-          t_iatom   *fa;
-          t_iparams *ip;
-
-          fa = top->idef.il[F_DISRES].iatoms; 
-          ip = top->idef.iparams;
-          if (blk_disre->nsub != 2 || 
-              (blk_disre->sub[0].nr != blk_disre->sub[1].nr) )
-          {
-              gmx_incons("Number of disre sub-blocks not equal to 2");
-          }
-
-          ndisre=blk_disre->sub[0].nr ;
-          if (ndisre != top->idef.il[F_DISRES].nr/3)
-          {
-              gmx_fatal(FARGS,"Number of disre pairs in the energy file (%d) does not match the number in the run input file (%d)\n",
-                        ndisre,top->idef.il[F_DISRES].nr/3);
-          }
-          snew(pairleg,ndisre);
-          for(i=0; i<ndisre; i++) 
-          {
-              snew(pairleg[i],30);
-              j=fa[3*i+1];
-              k=fa[3*i+2];
-              gmx_mtop_atominfo_global(&mtop,j,&anm_j,&resnr_j,&resnm_j);
-              gmx_mtop_atominfo_global(&mtop,k,&anm_k,&resnr_k,&resnm_k);
-              sprintf(pairleg[i],"%d %s %d %s (%d)",
-                      resnr_j,anm_j,resnr_k,anm_k,
-                      ip[fa[3*i]].disres.label);
-          }
-          set=select_it(ndisre,pairleg,&nset);
-          snew(leg,2*nset);
-          for(i=0; (i<nset); i++) 
-          {
-              snew(leg[2*i],32);
-              sprintf(leg[2*i],  "a %s",pairleg[set[i]]);
-              snew(leg[2*i+1],32);
-              sprintf(leg[2*i+1],"i %s",pairleg[set[i]]);
-          }
-          xvgr_legend(fp_pairs,2*nset,(const char**)leg,oenv);    
-      }
-
-      /* 
-       * Store energies for analysis afterwards... 
-       */
-      if (!bDisRe && !bDHDL && (fr->nre > 0)) {
-       if (edat.nframes % 1000 == 0) {
-         srenew(time,edat.nframes+1000);
-       }
-       time[edat.nframes] = fr->t;
-       edat.nframes++;
-      }
-      /* 
-       * Printing time, only when we do not want to skip frames
-       */
-      if (!skip || teller % skip == 0) {
-       if (bDisRe) {
-         /*******************************************
-          * D I S T A N C E   R E S T R A I N T S  
-          *******************************************/
-         if (ndisre > 0) 
-          {
-#ifndef GMX_DOUBLE
-            float *disre_rt =     blk_disre->sub[0].fval;
-            float *disre_rm3tav = blk_disre->sub[1].fval;
-#else
-            double *disre_rt =     blk_disre->sub[0].dval;
-            double *disre_rm3tav = blk_disre->sub[1].dval;
-#endif
-
-           print_time(out,fr->t);
-           if (violaver == NULL)
-             snew(violaver,ndisre);
-           
-           /* Subtract bounds from distances, to calculate violations */
-           calc_violations(disre_rt, disre_rm3tav,
-                           nbounds,pair,bounds,violaver,&sumt,&sumaver);
-
-           fprintf(out,"  %8.4f  %8.4f\n",sumaver,sumt);
-           if (bDRAll) {
-             print_time(fp_pairs,fr->t);
-             for(i=0; (i<nset); i++) {
-               sss=set[i];
-               fprintf(fp_pairs,"  %8.4f", mypow(disre_rm3tav[sss],minthird));
-               fprintf(fp_pairs,"  %8.4f", disre_rt[sss]);
-             }
-             fprintf(fp_pairs,"\n");
-           }
-           teller_disre++;
-         }
-       }
-        else if (bDHDL)
-        {
-            do_dhdl(fr, &fp_dhdl, opt2fn("-odh",NFILE,fnm), 
-                    &dh_blocks, &dh_hists, &dh_samples, &dh_lambdas,
-                    oenv);
-        }
-       /*******************************************
-        * E N E R G I E S
-        *******************************************/
-       else {
-         if (fr->nre > 0) {
-            if (bPrAll)
-            {
-                /* We skip frames with single points (usually only the first frame),
-                 * since they would result in an average plot with outliers.
-                 */
-                if (fr->nsum > 1) {
-                    print_time(out,fr->t);
-                     print1(out,bDp,fr->ener[set[0]].e);
-                     print1(out,bDp,fr->ener[set[0]].esum/fr->nsum);
-                     print1(out,bDp,sqrt(fr->ener[set[0]].eav/fr->nsum));
-                     fprintf(out,"\n");
-                }
-            }
-            else
-            {
-                print_time(out,fr->t);
-                if (bSum)
-                {
-                    sum = 0;
-                    for(i=0; i<nset; i++)
-                    {
-                        sum += fr->ener[set[i]].e;
-                    }
-                    print1(out,bDp,sum/nmol-ezero);
-                }
-                else
-                {
-                    for(i=0; (i<nset); i++)
-                    {
-                        if (bIsEner[i])
-                        {
-                            print1(out,bDp,(fr->ener[set[i]].e)/nmol-ezero);
-                        }
-                        else
-                        {
-                            print1(out,bDp,fr->ener[set[i]].e);
-                        }
-                    }
-                }
-                fprintf(out,"\n");
-            }
-         }
-#if 0
-          /* we first count the blocks that have id 0: the orire blocks */
-          block_orire=0;
-          for(b=0;b<fr->nblock;b++)
-          {
-              if (fr->block[b].id == mde_block_type_orire)
-                  nblock_orire++;
-          }
-#endif
+   /* Initiate energies and set them to zero */
+   edat.nsteps  = 0;
+   edat.npoints = 0;
+   edat.nframes = 0;
+   edat.step    = NULL;
+   edat.steps   = NULL;
+   edat.points  = NULL;
+   snew(edat.s,nset);
+
+   /* Initiate counters */
+   teller       = 0;
+   teller_disre = 0;
+   bFoundStart  = FALSE;
+   start_step   = 0;
+   start_t      = 0;
+   do {
+     /* This loop searches for the first frame (when -b option is given),
+      * or when this has been found it reads just one energy frame
+      */
+     do {
+         bCont = do_enx(fp,&(frame[NEXT]));
+         if (bCont) {
+             timecheck = check_times(frame[NEXT].t);
+         }
+     } while (bCont && (timecheck < 0));
+
+     if ((timecheck == 0) && bCont) {
+       /* We read a valid frame, so we can use it */
+       fr = &(frame[NEXT]);
+
+       if (fr->nre > 0) {
+         /* The frame contains energies, so update cur */
+         cur  = NEXT;
+
+             if (edat.nframes % 1000 == 0)
+             {
+                 srenew(edat.step,edat.nframes+1000);
+                 memset(&(edat.step[edat.nframes]),0,1000*sizeof(edat.step[0]));
+                 srenew(edat.steps,edat.nframes+1000);
+                 memset(&(edat.steps[edat.nframes]),0,1000*sizeof(edat.steps[0]));
+                 srenew(edat.points,edat.nframes+1000);
+                 memset(&(edat.points[edat.nframes]),0,1000*sizeof(edat.points[0]));
+
+                 for(i=0; i<nset; i++)
+                 {
+                     srenew(edat.s[i].ener,edat.nframes+1000);
+                     memset(&(edat.s[i].ener[edat.nframes]),0,
+                            1000*sizeof(edat.s[i].ener[0]));
+                     srenew(edat.s[i].es  ,edat.nframes+1000);
+                     memset(&(edat.s[i].es[edat.nframes]),0,
+                            1000*sizeof(edat.s[i].es[0]));
+                 }
+             }
+
+             nfr = edat.nframes;
+             edat.step[nfr] = fr->step;
+
+             if (!bFoundStart)
+             {
+                 bFoundStart = TRUE;
+                 /* Initiate the previous step data */
+                 start_step = fr->step;
+                 start_t    = fr->t;
+                 /* Initiate the energy sums */
+                 edat.steps[nfr]  = 1;
+                 edat.points[nfr] = 1;
+                 for(i=0; i<nset; i++)
+                 {
+                     sss = set[i];
+                     edat.s[i].es[nfr].sum  = fr->ener[sss].e;
+                     edat.s[i].es[nfr].sum2 = 0;
+                 }
+                 edat.nsteps  = 1;
+                 edat.npoints = 1;
+             }
+             else
+             {
+                 edat.steps[nfr] = fr->nsteps;
+                 {
+                     if (fr->step - start_step + 1 == edat.nsteps + fr->nsteps)
+                     {
+                         if (fr->nsum <= 1)
+                         {
+                             edat.points[nfr] = 1;
+                             for(i=0; i<nset; i++)
+                             {
+                                 sss = set[i];
+                                 edat.s[i].es[nfr].sum  = fr->ener[sss].e;
+                                 edat.s[i].es[nfr].sum2 = 0;
+                             }
+                             edat.npoints += 1;
+                         }
+                         else
+                         {
+                             edat.points[nfr] = fr->nsum;
+                             for(i=0; i<nset; i++)
+                             {
+                                 sss = set[i];
+                                 edat.s[i].es[nfr].sum  = fr->ener[sss].esum;
+                                 edat.s[i].es[nfr].sum2 = fr->ener[sss].eav;
+                             }
+                             edat.npoints += fr->nsum;
+                         }
+                     }
+                     else
+                     {
+                         /* The interval does not match fr->nsteps:
+                          * can not do exact averages.
+                          */
+                         edat.npoints = 0;
+                     }
+                     edat.nsteps = fr->step - start_step + 1;
+                 }
+             }
+             for(i=0; i<nset; i++)
+             {
+                 edat.s[i].ener[nfr] = fr->ener[set[i]].e;
+             }
+       }
+       /*
+        * Define distance restraint legends. Can only be done after
+        * the first frame has been read... (Then we know how many there are)
+        */
+       blk_disre=find_block_id_enxframe(fr, enxDISRE, NULL);
+       if (bDisRe && bDRAll && !leg && blk_disre)
+       {
+           t_iatom   *fa;
+           t_iparams *ip;
+
+           fa = top->idef.il[F_DISRES].iatoms;
+           ip = top->idef.iparams;
+           if (blk_disre->nsub != 2 ||
+               (blk_disre->sub[0].nr != blk_disre->sub[1].nr) )
+           {
+               gmx_incons("Number of disre sub-blocks not equal to 2");
+           }
+
+           ndisre=blk_disre->sub[0].nr ;
+           if (ndisre != top->idef.il[F_DISRES].nr/3)
+           {
+               gmx_fatal(FARGS,"Number of disre pairs in the energy file (%d) does not match the number in the run input file (%d)\n",
+                         ndisre,top->idef.il[F_DISRES].nr/3);
+           }
+           snew(pairleg,ndisre);
+           for(i=0; i<ndisre; i++)
+           {
+               snew(pairleg[i],30);
+               j=fa[3*i+1];
+               k=fa[3*i+2];
+               gmx_mtop_atominfo_global(&mtop,j,&anm_j,&resnr_j,&resnm_j);
+               gmx_mtop_atominfo_global(&mtop,k,&anm_k,&resnr_k,&resnm_k);
+               sprintf(pairleg[i],"%d %s %d %s (%d)",
+                       resnr_j,anm_j,resnr_k,anm_k,
+                       ip[fa[3*i]].disres.label);
+           }
+           set=select_it(ndisre,pairleg,&nset);
+           snew(leg,2*nset);
+           for(i=0; (i<nset); i++)
+           {
+               snew(leg[2*i],32);
+               sprintf(leg[2*i],  "a %s",pairleg[set[i]]);
+               snew(leg[2*i+1],32);
+               sprintf(leg[2*i+1],"i %s",pairleg[set[i]]);
+           }
+           xvgr_legend(fp_pairs,2*nset,(const char**)leg,oenv);
+       }
+
+       /*
+        * Store energies for analysis afterwards...
+        */
+       if (!bDisRe && !bDHDL && (fr->nre > 0)) {
+           if (edat.nframes % 1000 == 0) {
+               srenew(time,edat.nframes+1000);
+           }
+           time[edat.nframes] = fr->t;
+           edat.nframes++;
+       }
+       /*
+        * Printing time, only when we do not want to skip frames
+        */
+       if (!skip || teller % skip == 0) {
+     if (bDisRe) {
+       /*******************************************
+        * D I S T A N C E   R E S T R A I N T S
+        *******************************************/
+       if (ndisre > 0)
+           {
+ #ifndef GMX_DOUBLE
+             float *disre_rt =     blk_disre->sub[0].fval;
+             float *disre_rm3tav = blk_disre->sub[1].fval;
+ #else
+             double *disre_rt =     blk_disre->sub[0].dval;
+             double *disre_rm3tav = blk_disre->sub[1].dval;
+ #endif
+
+         print_time(out,fr->t);
+         if (violaver == NULL)
+           snew(violaver,ndisre);
+
+         /* Subtract bounds from distances, to calculate violations */
+         calc_violations(disre_rt, disre_rm3tav,
+                 nbounds,pair,bounds,violaver,&sumt,&sumaver);
+
+         fprintf(out,"  %8.4f  %8.4f\n",sumaver,sumt);
+         if (bDRAll) {
+           print_time(fp_pairs,fr->t);
+           for(i=0; (i<nset); i++) {
+         sss=set[i];
+         fprintf(fp_pairs,"  %8.4f", mypow(disre_rm3tav[sss],minthird));
+         fprintf(fp_pairs,"  %8.4f", disre_rt[sss]);
+           }
+           fprintf(fp_pairs,"\n");
+         }
+         teller_disre++;
+       }
+     }
+     else if (bDHDL)
+     {
+         do_dhdl(fr, &ir, &fp_dhdl, opt2fn("-odh",NFILE,fnm), bDp, &dh_blocks, &dh_hists, &dh_samples, &dh_lambdas, oenv);
+     }
+
+     /*******************************************
+      * E N E R G I E S
+      *******************************************/
+     else {
+         if (fr->nre > 0) {
+             if (bPrAll)
+             {
+                 /* We skip frames with single points (usually only the first frame),
+                  * since they would result in an average plot with outliers.
+                  */
+                 if (fr->nsum > 1) {
+                     print_time(out,fr->t);
+                      print1(out,bDp,fr->ener[set[0]].e);
+                      print1(out,bDp,fr->ener[set[0]].esum/fr->nsum);
+                      print1(out,bDp,sqrt(fr->ener[set[0]].eav/fr->nsum));
+                      fprintf(out,"\n");
+                 }
+             }
+             else
+             {
+                 print_time(out,fr->t);
+                 if (bSum)
+                 {
+                     sum = 0;
+                     for(i=0; i<nset; i++)
+                     {
+                         sum += fr->ener[set[i]].e;
+                     }
+                     print1(out,bDp,sum/nmol-ezero);
+                 }
+                 else
+                 {
+                     for(i=0; (i<nset); i++)
+                     {
+                         if (bIsEner[i])
+                         {
+                             print1(out,bDp,(fr->ener[set[i]].e)/nmol-ezero);
+                         }
+                         else
+                         {
+                             print1(out,bDp,fr->ener[set[i]].e);
+                         }
+                     }
+                 }
+                 fprintf(out,"\n");
+             }
+         }
           blk = find_block_id_enxframe(fr, enx_i, NULL);
          if (bORIRE && blk)
           {
@@ -2329,7 +2273,7 @@ int gmx_energy(int argc,char *argv[])
               vals=blk->sub[0].dval;
 #endif
 
-              if (blk->sub[0].nr != (size_t)nor) 
+              if (blk->sub[0].nr != (size_t)nor)
                   gmx_fatal(FARGS,"Number of orientation restraints in energy file (%d) does not match with the topology (%d)", blk->sub[0].nr);
               if (bORA || bODA)
               {
@@ -2341,14 +2285,14 @@ int gmx_energy(int argc,char *argv[])
                   for(i=0; i<nor; i++)
                       odrms[i] += sqr(vals[i]-oobs[i]);
               }
-              if (bORT) 
+              if (bORT)
               {
                   fprintf(fort,"  %10f",fr->t);
                   for(i=0; i<norsel; i++)
                       fprintf(fort," %g",vals[orsel[i]]);
                   fprintf(fort,"\n");
               }
-              if (bODT) 
+              if (bODT)
               {
                   fprintf(fodt,"  %10f",fr->t);
                   for(i=0; i<norsel; i++)
@@ -2357,22 +2301,22 @@ int gmx_energy(int argc,char *argv[])
               }
               norfr++;
           }
-          blk = find_block_id_enxframe(fr, enxORT, NULL);
-          if (bOTEN && blk) 
-          {
+         blk = find_block_id_enxframe(fr, enxORT, NULL);
+         if (bOTEN && blk)
+         {
 #ifndef GMX_DOUBLE
-              xdr_datatype dt=xdr_datatype_float;
+             xdr_datatype dt=xdr_datatype_float;
 #else
-              xdr_datatype dt=xdr_datatype_double;
+             xdr_datatype dt=xdr_datatype_double;
 #endif
-              real *vals;
-              if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
-                  gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
+             real *vals;
+
+             if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
+                 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
 #ifndef GMX_DOUBLE
-              vals=blk->sub[0].fval;
+             vals=blk->sub[0].fval;
 #else
-              vals=blk->sub[0].dval;
+             vals=blk->sub[0].dval;
 #endif
 
               if (blk->sub[0].nr != (size_t)(nex*12))
@@ -2389,10 +2333,10 @@ int gmx_energy(int argc,char *argv[])
       teller++;
     }
   } while (bCont && (timecheck == 0));
-  
+
   fprintf(stderr,"\n");
   close_enx(fp);
-  if (out) 
+  if (out)
       ffclose(out);
 
   if (bDRAll)
@@ -2402,7 +2346,7 @@ int gmx_energy(int argc,char *argv[])
       ffclose(fort);
   if (bODT)
       ffclose(fodt);
-  if (bORA) 
+  if (bORA)
   {
       out = xvgropen(opt2fn("-ora",NFILE,fnm),
                      "Average calculated orientations",
@@ -2436,17 +2380,17 @@ int gmx_energy(int argc,char *argv[])
   if (bOTEN)
       ffclose(foten);
 
-  if (bDisRe) 
+  if (bDisRe)
   {
       analyse_disre(opt2fn("-viol",NFILE,fnm),
                     teller_disre,violaver,bounds,index,pair,nbounds,oenv);
-  } 
+  }
   else if (bDHDL)
   {
       if (fp_dhdl)
       {
           ffclose(fp_dhdl);
-          printf("\n\nWrote %d lambda values with %d samples as ", 
+          printf("\n\nWrote %d lambda values with %d samples as ",
                  dh_lambdas, dh_samples);
           if (dh_hists > 0)
           {
@@ -2480,7 +2424,7 @@ int gmx_energy(int argc,char *argv[])
                              nbmin,nbmax);
   }
   if (opt2bSet("-f2",NFILE,fnm)) {
-      fec(opt2fn("-f2",NFILE,fnm), opt2fn("-ravg",NFILE,fnm), 
+      fec(opt2fn("-f2",NFILE,fnm), opt2fn("-ravg",NFILE,fnm),
           reftemp, nset, set, leg, &edat, time ,oenv);
   }
 
index b159ecae2f94f59f4d39137b1dddc9a61b7a65f3..6105583a2f414c2f1f2b2d3aeef118624a9558fe 100644 (file)
@@ -84,8 +84,8 @@ static void fill_ft_ind(int nft,int *ft,t_idef *idef,
                  idef->iparams[i].harmonic.krA);
          break;
        case F_UREY_BRADLEY:
-         sprintf(buf,"UB_th=%.1f_%.2f2f",idef->iparams[i].u_b.theta,
-                 idef->iparams[i].u_b.ktheta);
+         sprintf(buf,"UB_th=%.1f_%.2f2f",idef->iparams[i].u_b.thetaA,
+                 idef->iparams[i].u_b.kthetaA);
          break;
        case F_QUARTIC_ANGLES:
          sprintf(buf,"Q_th=%.1f_%.2f_%.2f",idef->iparams[i].qangle.theta,