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,
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
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
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
}
/*
- *
+ *
* 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
*/
* 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.
* 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.
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
+++ /dev/null
-/*
- *
- * 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 */
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);
* 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);
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);
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,
t_mdatoms *md,
t_commrec *cr,
t_nrnb *nrnb,
- real lambda,
+ real *lambda,
real *dvdlambda,
gmx_grppairener_t *grppener,
gmx_bool bFillGrid,
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],
gmx_bool bTricl;
gmx_bool bDynBox;
gmx_bool bNHC_trotter;
+ gmx_bool bPrintNHChains;
gmx_bool bMTTK;
gmx_bool bDiagPres;
gmx_bool bVir;
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,
/* 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 */
const char *fn_cpt;
gmx_bool bKeepAndNumCPT;
int eIntegrator;
+ gmx_bool bExpanded;
+ int elamstats;
int simulation_part;
FILE *fp_dhdl;
FILE *fp_field;
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,
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,
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
{
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 */
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[],
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];
#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)
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).
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);
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,
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);
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;
/*
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);
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);
};
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 */
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 */
/* Implicit solvent algorithms */
enum {
- eisNO, eisGBSA, eisNR
+ eisNO, eisGBSA, eisNR
};
/* Algorithms for calculating GB radii */
t_disresdata disres;
t_oriresdata orires;
- real dihre_fc;
} t_fcdata;
#ifdef __cplusplus
*/
#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 };
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
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;
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.
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;
* 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;
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 */
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 */
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 */
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 */
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 */
#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
}
/* 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
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 */
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 */
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 */
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;
/* 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 */
*
*/
+
void
init_ekinstate(ekinstate_t *ekinstate,const t_inputrec *ir);
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);
--- /dev/null
+======== 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
+
+
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>
<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>
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)
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>
</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>
<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>
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
<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>
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;
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 */
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);
fshift[ki][m]+=fij;
fshift[CENTRAL][m]-=fij;
}
- } /* 58 TOTAL */
+ } /* 83 TOTAL */
return vtot;
}
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 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 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 */
}
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;
{
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++];
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;
rvec_inc(fshift[CENTRAL],f_j);
rvec_inc(fshift[t2],f_k);
} /* 57 TOTAL */
- *dvdlambda = dvdl;
return vtot;
}
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;
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) {
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;
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 */
}
/* 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;
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 */
}
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,
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,
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++];
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",
#endif
}
- *dvdlambda += dvdl;
+ *dvdlambda += dvdl_term;
return vtot;
}
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);
{
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;
+ }
}
}
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;
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;
}
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); ) {
/* Calculate the derivative */
v = parm[0];
- dvdl += (parmB[0]-parmA[0]);
+ dvdl_term += (parmB[0]-parmA[0]);
ddphi = c0;
cosfac = c1;
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 */
f,fshift,pbc,g,x,t1,t2,t3); /* 112 */
vtot += v;
}
- *dvdlambda += dvdl;
+ *dvdlambda += dvdl_term;
return vtot;
}
ivec jt2,dt2_ij,dt2_kj,dt2_lj;
const real *cmapd;
-
+
int loop_index[4][4] = {
{0,4,8,12},
{1,5,9,13},
/* Which CMAP type is this */
cmapA = forceparams[type].cmap.cmapA;
cmapd = cmap_grid->cmapdata[cmapA].cmap;
-
+
/* First torsion */
a1i = ai;
a1j = aj;
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];
{
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;
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 */
}
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
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));
{
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;
*F = -k*FF*tabscale;
*V = k*VV;
- dvdl = (kB - kA)*VV;
+ dvdlambda = (kB - kA)*VV;
- return dvdl;
+ return dvdlambda;
/* That was 22 flops */
}
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;
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 */
/* 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,
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);
}
#include "statutil.h"
#include "txtdump.h"
#include "vec.h"
+#include "mdrun.h"
#include "network.h"
#include "gmx_random.h"
#include "checkpoint.h"
#define CPT_MAGIC1 171817
#define CPT_MAGIC2 171819
+#define CPTSTRLEN 1024
#ifdef GMX_DOUBLE
#define GMX_CPT_BUILD_DP 1
"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 };
"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
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;
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)
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)
{
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;
{
*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)
{
(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)
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++)
{
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);
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);
{
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);
}
}
}
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)
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;
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))
}
}
-
+ 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);
&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);
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))
{
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)
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;
&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)
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 */
}
}
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();
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)
{
/* 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)) {
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;
&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)
{
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,
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);
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)
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)
{
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);
}
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);
+++ /dev/null
-/*
- *
- * 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;
-}
}
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 */
#include "typedefs.h"
#include "bondf.h"
#include "disre.h"
-#include "dihre.h"
#include "orires.h"
#include "genborn.h"
{
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 ),
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 ),
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 ),
*/
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" )
};
n = nstmin_harmonic;
break;
case etcANDERSEN:
- case etcANDERSENINTERVAL:
+ case etcANDERSENMASSIVE:
n = 1;
break;
default:
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)
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;
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);
};
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] = {
"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
};
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;
ntiA = 2*ntype*typeA[ii];
ntiB = 2*ntype*typeB[ii];
vctot = 0;
- Vvdwtot = 0;
+ vvtot = 0;
fix = 0;
fiy = 0;
fiz = 0;
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;
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;
f[j3+2] = f[j3+2] - tz;
}
}
-
+
if (bDoForces)
{
f[ii3] = f[ii3] + fix;
}
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;
}
real facel,
real krf,
real crf,
- real ewc,
+ real ewc,
real * Vc,
int * typeA,
int * typeB,
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);
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;
if(nlist->free_energy)
{
- if(nlist->ivdw==2)
+ if(nlist->ivdw==enbvdwBHAM)
{
gmx_fatal(FARGS,"Cannot do free energy Buckingham interactions.");
}
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,
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)
/* 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;
}
* 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.");
}
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,
{ "Pos. Restr.", 50 },
{ "Angle Restr.", 191 },
{ "Angle Restr. Z", 164 },
- { "Morse Potent.", 58 },
+ { "Morse Potent.", 83 },
{ "Cubic Bonds", 54 },
{ "Walls", 31 },
{ "Polarization", 59 },
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 ||
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 ||
}
}
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;
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
{ 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 },
{ 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)
}
}
+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;
* 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);
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);
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);
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);
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);
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);
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);
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);
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);
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;
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);
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);
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 */
}
}
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)) {
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;
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));
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);
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));
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);
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",
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",
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)
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;
}
}
-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;
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);
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;
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];
+ }
+ }
+}
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);
/* 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);
}
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];
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];
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];
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++) {
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;
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);
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);
}
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)
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;
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);
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,
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);
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");
/* 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);
}
}
+ /* 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);
#include "ionize.h"
#include "disre.h"
#include "orires.h"
-#include "dihre.h"
#include "pme.h"
#include "mdatoms.h"
#include "repl_ex.h"
#include "checkpoint.h"
#include "mtop_util.h"
#include "sighandler.h"
+#include "txtdump.h"
#include "string2.h"
#include "membed.h"
#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,
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,
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;
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;
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;
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;
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)
{
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);
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;
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);
nrnb,wcycle,FALSE);
}
- update_mdatoms(mdatoms,state->lambda);
+ update_mdatoms(mdatoms,state->lambda[efptMASS]);
if (opt2bSet("-cpi",nfile,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))
* 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)))
}
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)
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
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)
/* 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);
}
}
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)
/* 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 ||
(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)
* 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,
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
* 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,
}
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) {
{
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
{
get_stochd_state(upd,state);
}
+ if (state->flags & (1<<estMC_RNG))
+ {
+ get_mc_state(mcrng,state);
+ }
if (MASTER(cr))
{
if (bSumEkinhOld)
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,
}
/* ################## 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
{
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);
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 */
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);
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)
{
{
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,
| (!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)
{
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);
}
/* ######### 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)
{
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);
}
}
}
}
-
-
+ 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() ))
{
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))
#include "ionize.h"
#include "disre.h"
#include "orires.h"
-#include "dihre.h"
#include "pme.h"
#include "mdatoms.h"
#include "qmmm.h"
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,
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);
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 */
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')
{
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);
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,
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,
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;
"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},
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);
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();
#define MAXPTR 254
#define NOGID 255
+#define MAXLAMBDAS 1024
/* Resource parameters
* Do not change any of these until you read the instruction
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],
{
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)
*/
#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);
{
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;
{
/* nstdhdl should be a multiple of nstcalcenergy */
check_nst("nstcalcenergy",ir->nstcalcenergy,
- "nstdhdl",&ir->nstdhdl,wi);
+ "nstdhdl",&ir->fepvals->nstdhdl,wi);
}
}
}
/* 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);
}
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);
"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) {
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) {
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;
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.",
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 "
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));
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.");
}
}
}
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)
{
}
+/* 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;
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;
}
}
+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)
}
}
+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)
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");
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)");
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);
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);
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)");
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];
}
}
- 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]);
}
{
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;
}
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);
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'))
}
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));
}
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");
}
real tempi;
int seed;
gmx_bool bOrire;
- gmx_bool bDihre;
gmx_bool bMorse;
char *wall_atomtype[2];
gmx_bool pull_start;
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)
#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");
re->repl = ms->sim;
re->nrepl = ms->nsim;
+ snew(re->q,ereENDSINGLE);
fprintf(fplog,"Repl There are %d replicas:\n",re->nrepl);
"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++)
}
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)
{
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);
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");
{
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)
{
{
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;
}
}
}
+
+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;
}
}
-#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)
{
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)
}
}
+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;
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;
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
cr->mpi_comm_mygroup);
#endif
}
-
if (bExchanged)
{
/* Exchange the states */
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 */
}
}
}
-
return bExchanged;
}
{
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);
}
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.
#include "names.h"
#include "disre.h"
#include "orires.h"
-#include "dihre.h"
#include "pme.h"
#include "mdatoms.h"
#include "repl_ex.h"
int resetstep;
int nmultisim;
int repl_ex_nst;
+ int repl_ex_nex;
int repl_ex_seed;
real pforce;
real cpt_period;
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);
}
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;
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;
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)
{
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
/* 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) &&
}
}
- /* 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,
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);
}
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,
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
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);
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);
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]);
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;
/* 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},
{ "-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;
/* 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);
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;
}
/* 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)
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));
}
}
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;
+}
for (i=0; i<nvar; i++)
{
-
+
/* make it easier to iterate by selecting
out the sub-array that corresponds to this T group */
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 {
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;
}
{
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)
{
/* 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);
}
}
-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;
/* 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];
}
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;
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))
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]); */
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);
/* 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;
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:
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;
}
}
- 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++) {
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];
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);
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);
}
}
}
- 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);
#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|... */
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))
{
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
--- /dev/null
+/* -*- 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;
+}
+
+
/* -*- 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
*/
t_mdatoms *md,
t_commrec *cr,
t_nrnb *nrnb,
- real lambda,
+ real *lambda,
real *dvdlambda,
gmx_grppairener_t *grppener,
gmx_bool bFillGrid,
{
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,
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,
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
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 ?
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];
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);
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)
{
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.
*/
set_pbc_dd(&pbc,fr->ePBC,cr->dd,TRUE,box);
}
debug_gmx();
-
+
if (flags & GMX_FORCE_BONDED)
{
GMX_MPE_LOG(ev_calc_bonds_start);
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];
}
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,
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
{
Vcorr = 0;
}
}
-
- dvdlambda = 0;
+
+ dvdlambda[efptCOUL] = 0;
status = 0;
switch (fr->eeltype)
{
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);
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 */
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;
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)
{
{
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)
{
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)
{
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
{
real t;
int i;
-
+
t = 0.0;
for(i=0; (i<n); i++)
t = t + v[i];
-
+
return t;
}
gmx_grppairener_t *grpp;
real *epot;
int i;
-
+
grpp = &enerd->grpp;
epot = enerd->term;
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
*/
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]);
+ }
+ }
}
}
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;
+ }
+ }
}
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);
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)
{
/* -*- 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;
* 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)) {
} 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;
+ }
}
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);
}
{
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 ############## */
*pcurr = enerd->term[F_PRES];
/* calculate temperature using virial */
enerd->term[F_VTEMP] = calc_temp(trace(total_vir),ir->opts.nrdf[0]);
-
+
}
}
}
}
+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,
if (ir->efep != efepNO)
{
check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
- "nstdhdl",&ir->nstdhdl);
+ "nstdhdl",&ir->fepvals->nstdhdl);
}
}
}
/* -*- 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
*/
#include "mtop_util.h"
#include "xvgr.h"
#include "gmxfio.h"
-
+#include "mdrun.h"
#include "mdebin_bar.h"
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" };
#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,
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;
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);
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
}
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);
}
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;
}
{
md->mdeb_n = 2*md->nNHC*md->nTCP;
}
- } else {
+ } else {
md->mde_n = md->nTC;
md->mdeb_n = 0;
}
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);
}
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);
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]);
}
}
}
- 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++)
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);
{
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]);
}
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,
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
}
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);
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);
/* 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)
{
}
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++)
{
}
}
}
- 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++)
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)
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,
real *block[enxNR];
/* temporary arrays for the lambda values to write out */
- double enxlambda_data[2];
+ double enxlambda_data[2];
t_enxframe fr;
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])
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;
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));
/* 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;
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)
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)
(enerhist->nsum_sim > 0 ? enerhist->ener_sum_sim[i] : 0);
}
if (mdebin->dhc)
- {
+ {
mde_delta_h_coll_restore_energyhistory(mdebin->dhc, enerhist);
}
}
/* -*- 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
*/
}
/* 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++)
{
}
snew(dh->dh, dh->ndhmax);
+ snew(dh->dhf,dh->ndhmax);
+
if ( nbins <= 0 || dx<GMX_REAL_EPS*10 )
{
dh->nhist=0;
{
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++)
/* 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;
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;
if (f*dh->dh[i] > max_dh)
max_dh=f*dh->dh[i];
}
-
+
/* reset the histogram */
for(i=0;i<dh->nbins;i++)
{
}
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;
{
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 ) )
{
}
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;
}
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)
/* 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);
/* 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;
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
{
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++;
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;
/* 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];
/* 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)
{
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;
-/*
- *
+/* -*- 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 */
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);
/* -*- 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
*/
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;
}
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
}
{
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,
fr,vsite,NULL,constr,
nrnb,NULL,FALSE);
dd_store_state(cr->dd,&ems->s);
-
+
if (ir->nstfout)
{
snew(*f_global,top_global->natoms);
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
*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);
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 &&
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);
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);
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))
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;
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);
}
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,
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;
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
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)
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;
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 {
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))
{
* 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;
i++;
}
}
-
+
sfree(fmg);
return partsum;
* 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)) {
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 */
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,
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;
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;
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;
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));
}
/* 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);
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.
*/
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]) {
}
}
}
-
+
/* 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.
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
* 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,
/* 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,
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 */
*/
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
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,
/* 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,
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.
*/
/* 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 */
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.
continue;
}
}
-
+
/* Select min energy state of A & C, put the best in B.
*/
if (s_c->epot < s_a->epot) {
gpb = gpa;
b = a;
}
-
+
} else {
if (debug)
fprintf(debug,"CGE: Found a lower energy %f, moving C to B\n",
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
/* 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)
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))
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 */
/* 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;
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,
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;
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...
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,
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;
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
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);
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])
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]);
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
* 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 {
/* 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;
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 */
/* 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.
*/
*/
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
*/
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;
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 */
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;
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) {
continue;
}
}
-
+
/* Select min energy state of A & C, put the best in xx/ff/Epot
*/
if(EpotC<EpotA) {
}
stepsize=a;
}
-
+
} else {
/* found lower */
Epot = EpotC;
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++;
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];
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)
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))
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 */
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;
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;
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
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) {
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),
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)
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;
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)
}
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);
}
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 */
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,
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;
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))
{
" 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)
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)
{
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,
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. ");
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,
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,
/* 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);
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)
}
}
}
-
+
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);
finish_em(fplog,cr,outf,runtime,wcycle);
runtime->nsteps_done = natoms*2;
-
+
return 0;
}
+
/* 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);
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
{
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,
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[],
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,
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)) {
}
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;
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];
}
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;
}
}
/* 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");
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;
}
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++) {
/* 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,
/* -*- 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
*/
#include "xtcio.h"
#include "copyrite.h"
#include "pull_rotation.h"
+#include "gmx_random.h"
#include "mpelogging.h"
#include "domdec.h"
#include "partdec.h"
#if 0
typedef struct gmx_timeprint {
-
+
} t_gmx_timeprint;
#endif
#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
}
#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
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);
fflush(out);
}
-#ifdef NO_CLOCK
+#ifdef NO_CLOCK
#define clock() -1
#endif
prev = runtime->proc;
runtime->proc = dclock();
-
+
diff = runtime->proc - prev;
#else
clock_t prev;
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;
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);
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.
*
rvec Ext;
real t0;
int i,m;
-
+
for(m=0; (m<DIM); m++)
{
if (Et[m].n > 0)
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);
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,
{
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;
}
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));
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);
* 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);
}
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);
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];
}
}
if (bNS)
{
wallcycle_start(wcycle,ewcNS);
-
+
if (graph && bStateChanged)
{
/* Calculate intramolecular shift vectors to make molecules whole */
/* 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))
dd_force_flop_start(cr->dd,nrnb);
}
}
-
+
if (inputrec->bRot)
{
/* Enforced rotation has its own cycle counter that starts after the collective
{
/* 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)
{
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);
dd_cycles_add(cr->dd,cycles_force-cycles_pme,ddCyclF);
}
}
-
+
if (bDoForces)
{
if (IR_ELEC_FIELD(*inputrec))
adress_thermo_force(start,homenr,&(top->cgs),x,fr->f_novirsum,fr,mdatoms,
inputrec->ePBC==epbcNONE ? NULL : &pbc);
}
-
+
/* Communicate the forces */
if (PAR(cr))
{
wallcycle_stop(wcycle,ewcVSITESPREAD);
}
}
-
+
if (flags & GMX_FORCE_VIRIAL)
{
/* Calculation of the virial must be done after vsites! */
* 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)
{
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);
{
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.
*/
}
}
}
-
+
/* 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);
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);
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 */
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];
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)
{
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 */
}
}
}
-
sfree(savex);
}
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;
*/
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;
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)
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;
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;
}
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,
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)
}
/* 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)
{
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",
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;
}
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;
/* 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);
#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) {
cr->mpi_comm_mysim);
}
}
-#endif
+#endif
if (SIMMASTER(cr)) {
wallcycle_print(fplog,cr->nnodes,cr->npmenodes,runtime->realtime,
} else {
delta_t = 0;
}
-
+
if (fplog) {
print_perf(fplog,runtime->proctime,runtime->realtime,
cr->nnodes-cr->npmenodes,
}
}
+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[],
{
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++)
{
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)
please_cite(fplog,"Bussi2007a");
}
}
-
+
init_nrnb(nrnb);
-
+
if (nfile != -1)
{
*outf = init_mdoutf(nfile,fnm,Flags,cr,ir,oenv);
*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();
}
+
+
+
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);
}
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);
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); */
}
}
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))
}
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)
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,
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++)
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,
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 */
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));
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;
/* -*- 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
*/
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;
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];
}
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];
}
{
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];
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)
{
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;
}
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)
{
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];
}
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];
gmx_sd_const_t *sdc;
int ngtc,n;
real y;
-
+
snew(sd,1);
/* Initiate random number generator for langevin type dynamics,
{
snew(sd->sdc,ngtc);
snew(sd->sdsig,ngtc);
-
+
sdc = sd->sdc;
for(n=0; n<ngtc; n++)
{
}
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;
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;
}
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;
}
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];
}
{
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];
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);
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 */
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];
}
{
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];
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];
}
{
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
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];
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);
}
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;
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.
*/
* 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 {
}
}
ekind->dekindl_old = ekind->dekindl;
-
+
dekindl = 0;
- for(n=start; (n<start+homenr); n++)
+ for(n=start; (n<start+homenr); n++)
{
if (md->cACC)
{
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);
}
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);
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);
}
}
}
-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);
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;
copy_mat(ekind->ekin,ekinstate->ekin_total);
ekinstate->dekindl = ekind->dekindl;
ekinstate->mvcos = ekind->cosacc.mvcos;
-
+
}
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);
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);
{
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++)
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];
*/
/* 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.
*/
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;
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++)
void update_pcouple(FILE *fplog,
gmx_large_int_t step,
- t_inputrec *inputrec,
+ t_inputrec *inputrec,
t_state *state,
matrix pcoupl_mu,
matrix M,
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
case (epcNO):
break;
case (epcBERENDSEN):
- if (!bInitStep)
+ if (!bInitStep)
{
berendsen_pcoupl(fplog,step,inputrec,dtpc,state->pres_prev,state->box,
pcoupl_mu);
break;
default:
break;
- }
- }
+ }
+ }
}
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,
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);
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))
{
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);
}
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 */
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.
}
}
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
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:
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.
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);
}
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;
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) &&
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
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) {
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,
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,
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,
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;
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:
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]);
}
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;
+}
{
fr->vir_wall_z[i] = -0.5*xf_z[i];
}
-
+
return dvdlambda;
}
/*
- *
+ *
* 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
*/
{
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;
}
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--;
}
at++;
}
-
+
return at;
}
{
int i;
real rmax;
-
+
rmax = 0;
if (n > 0) {
rmax = radius[0];
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]);
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);
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;
snew(ffp->iparams,1);
ffp->iparams[0].lj.c6 = 1;
ffp->iparams[0].lj.c12 = 1;
-
+
/* inputrec structure */
snew(ir,1);
ir->coulombtype = eelCUT;
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");
}
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.
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;
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);
/* 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);
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 */
) &&
(atoms_solvt->atom[is1].resind != /* Not the same residue */
atoms_solvt->atom[is2].resind))) {
-
+
ntest++;
rvec_sub(xi,xj,dx);
n2 = norm2(dx);
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);
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);
}
}
} 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++;
}
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;
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++;
}
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);
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;
/* 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++)
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;
}
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);
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;
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 */
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);
fpb = xvgropen_type(opt2fn("-o",NFILE,fnm),"Free energy differences",
"\\lambda",buf,exvggtXYDY,oenv);
}
-
+
fpi = NULL;
if (opt2bSet("-oi",NFILE,fnm))
{
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,
/* -*- 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
*/
#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;
{
if (x > 0)
return pow(x,y);
- else
+ else
return 0.0;
}
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");
}
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--;
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++) {
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) {
} 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;
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);
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++) {
}
}
*bounds = b;
-
+
/* Fill the index array */
label1 = -1;
disres = &(top->idef.il[F_DISRES]);
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++;
*index = ind;
*dr_pair = pair;
-
+
return nb;
}
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++) {
}
rsum = max(0.0,mypow(rsum,-sixth)-bounds[i]);
rav = max(0.0,mypow(rav, -sixth)-bounds[i]);
-
+
sumt += rsum;
sumaver += rav;
}
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;
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;
static void add_ee_av(ee_sum_t *ees)
{
double av;
-
+
av = ees->sum/ees->np;
ees->sav += av;
ees->sav2 += av*av;
for(i=0; i<nset; i++)
{
ed = &edat->s[i];
-
+
sum = 0;
sum2 = 0;
np = 0;
sump = ed->ener[f];
sum2 += dsqr(sump);
}
-
+
/* sum has to be increased after sum2 */
np += p;
sum += sump;
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++)
}
s->slope += edat->s[i].slope;
}
-
+
for(f=0; f<edat->nframes; f++)
{
sum = 0;
s->es[f].sum = sum;
s->es[f].sum2 = 0;
}
-
+
calc_averages(1,esum,nbmin,nbmax);
return esum;
{
char tmp[100];
double rnd;
-
+
if (ee < 0)
{
sprintf(buf,"%s","--");
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;
enum { eVol, eEnth, eTemp, eEtot, eNR };
const char *my_ener[] = { "Volume", "Enthalpy", "Temperature", "Total Energy" };
int ii[eNR];
-
+
NANO3 = NANO*NANO*NANO;
if (!bDriftCorr)
{
{
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)
*/ }
/* Compute it all! */
vvhh = alpha = kappa = cp = dcp = cv = NOTSET;
-
+
/* Temperature */
tt = NOTSET;
if (ii[eTemp] < nset)
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);
dcp);
please_cite(fp,"Allen1987a");
}
- else
+ else
{
fprintf(fp,"You should select the temperature in order to obtain fluctuation properties.\n");
}
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);
}
}
}
}
-
+
if (nnotexact == 0) {
fprintf(stdout,"All statistics are over %s points\n",
gmx_step_str(edat->npoints,buf));
else
fprintf(stdout,"\n");
fprintf(stdout,"-------------------------------------------------------------------------------\n");
-
+
/* Initiate locals, only used with -sum */
expEtot=0;
if (bFee) {
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) {
Vaver= aver;
} else if (strstr(leg[i],"essure") != NULL) {
Pres = aver;
- }
+ }
if (bIsEner[i]) {
pr_aver = aver/nmol-ezero;
pr_stddev = stddev/nmol;
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) {
"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)
{
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);
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;
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;
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) {
}
}
} 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) {
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);
}
-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];
{
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)
{
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;
}
}
}
}
-
(*samples) += (int)(sum/nblock_hist);
}
else
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
}
}
}
-
-
- 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]);
{
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");
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",
"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]",
" [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;
"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" },
"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;
#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);
do_enxnms(fp,&nre,&enm);
Vaver = -1;
-
+
bVisco = opt2bSet("-vis",NFILE,fnm);
-
- if (!bDisRe && !bDHDL)
+
+ if ((!bDisRe) && (!bDHDL))
{
if (bVisco) {
nset=asize(setnm);
}
}
}
- else
+ else
{
set=select_by_name(nre,enm,&nset);
}
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)
{
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)
{
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++)
}
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))
teller++;
}
} while (bCont && (timecheck == 0));
-
+
fprintf(stderr,"\n");
close_enx(fp);
- if (out)
+ if (out)
ffclose(out);
if (bDRAll)
ffclose(fort);
if (bODT)
ffclose(fodt);
- if (bORA)
+ if (bORA)
{
out = xvgropen(opt2fn("-ora",NFILE,fnm),
"Average calculated orientations",
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)
{
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);
}
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,