| version 1.1324 | version 1.1325 |
|---|
| |
| /***************************************************************************** | /***************************************************************************** |
| * $Source: /home/cvs/namd/cvsroot/namd2/src/Controller.C,v $ | * $Source: /home/cvs/namd/cvsroot/namd2/src/Controller.C,v $ |
| * $Author: jim $ | * $Author: jim $ |
| * $Date: 2016/10/14 16:12:12 $ | * $Date: 2017/02/03 21:39:23 $ |
| * $Revision: 1.1324 $ | * $Revision: 1.1325 $ |
| *****************************************************************************/ | *****************************************************************************/ |
| | |
| #include "InfoStream.h" | #include "InfoStream.h" |
| |
| } | } |
| } | } |
| | |
| | inline void Controller :: calc_accelMDG_mean_std |
| | (BigReal testV, int n, |
| | BigReal *Vmax, BigReal *Vmin, BigReal *Vavg, BigReal *M2, BigReal *sigmaV){ |
| | BigReal delta; |
| | |
| | if(testV > *Vmax){ |
| | *Vmax = testV; |
| | } |
| | else if(testV < *Vmin){ |
| | *Vmin = testV; |
| | } |
| | |
| | //mean and std calculated by Online Algorithm |
| | delta = testV - *Vavg; |
| | *Vavg += delta / (BigReal)n; |
| | *M2 += delta * (testV - (*Vavg)); |
| | |
| | *sigmaV = sqrt(*M2/n); |
| | } |
| | |
| | inline void Controller :: calc_accelMDG_E_k |
| | (int iE, int step, BigReal sigma0, BigReal Vmax, BigReal Vmin, BigReal Vavg, BigReal sigmaV, |
| | BigReal* k0, BigReal* k, BigReal* E, int *iEused, char *warn){ |
| | switch(iE){ |
| | case 2: |
| | *k0 = (1-sigma0/sigmaV) * (Vmax-Vmin) / (Vavg-Vmin); |
| | // if k0 <=0 OR k0 > 1, switch to iE=1 mode |
| | if(*k0 > 1.) |
| | *warn |= 1; |
| | else if(*k0 <= 0.) |
| | *warn |= 2; |
| | //else stay in iE=2 mode |
| | else{ |
| | *E = Vmin + (Vmax-Vmin)/(*k0); |
| | *iEused = 2; |
| | break; |
| | } |
| | case 1: |
| | *E = Vmax; |
| | *k0 = (sigma0 / sigmaV) * (Vmax-Vmin) / (Vmax-Vavg); |
| | if(*k0 > 1.) |
| | *k0 = 1.; |
| | *iEused = 1; |
| | break; |
| | } |
| | |
| | *k = *k0 / (Vmax - Vmin); |
| | } |
| | |
| | inline void Controller :: calc_accelMDG_force_factor |
| | (BigReal k, BigReal E, BigReal testV, Tensor vir_orig, |
| | BigReal *dV, BigReal *factor, Tensor *vir){ |
| | BigReal VE = testV - E; |
| | //if V < E, apply boost |
| | if(VE < 0){ |
| | *factor = k * VE; |
| | *vir += vir_orig * (*factor); |
| | *dV += (*factor) * VE/2.; |
| | *factor += 1.; |
| | } |
| | else{ |
| | *factor = 1.; |
| | } |
| | } |
| | |
| | void Controller :: write_accelMDG_rest_file |
| | (int step_n, char type, int V_n, BigReal Vmax, BigReal Vmin, BigReal Vavg, BigReal sigmaV, BigReal M2, BigReal E, BigReal k, bool write_topic, bool lasttime){ |
| | FILE *rest; |
| | char timestepstr[20]; |
| | char *filename; |
| | int baselen; |
| | char *restart_name; |
| | const char *bsuffix; |
| | |
| | if(lasttime || simParams->restartFrequency == 0){ |
| | filename = simParams->outputFilename; |
| | bsuffix = ".BAK"; |
| | } |
| | else{ |
| | filename = simParams->restartFilename; |
| | bsuffix = ".old"; |
| | } |
| | |
| | baselen = strlen(filename); |
| | restart_name = new char[baselen+26]; |
| | |
| | strcpy(restart_name, filename); |
| | if ( simParams->restartSave && !lasttime) { |
| | sprintf(timestepstr,".%d",step_n); |
| | strcat(restart_name, timestepstr); |
| | bsuffix = ".BAK"; |
| | } |
| | strcat(restart_name, ".gamd"); |
| | |
| | if(write_topic){ |
| | NAMD_backup_file(restart_name,bsuffix); |
| | |
| | rest = fopen(restart_name, "w"); |
| | if(rest){ |
| | fprintf(rest, "# NAMD accelMDG restart file\n" |
| | "# D/T Vn Vmax Vmin Vavg sigmaV M2 E k\n" |
| | "%c %d %.17lg %.17lg %.17lg %.17lg %.17le %.17lg %.17lg\n", |
| | type, V_n-1, Vmax, Vmin, Vavg, sigmaV, M2, E, k); |
| | fclose(rest); |
| | iout << "GAUSSIAN ACCELERATED MD RESTART DATA WRITTEN TO " << restart_name << "\n" << endi; |
| | } |
| | else |
| | iout << iWARN << "Cannot write accelMDG restart file\n" << endi; |
| | } |
| | else{ |
| | rest = fopen(restart_name, "a"); |
| | if(rest){ |
| | fprintf(rest, "%c %d %.17lg %.17lg %.17lg %.17lg %.17le %.17lg %.17lg\n", |
| | type, V_n-1, Vmax, Vmin, Vavg, sigmaV, M2, E, k); |
| | fclose(rest); |
| | } |
| | else |
| | iout << iWARN << "Cannot write accelMDG restart file\n" << endi; |
| | } |
| | |
| | delete[] restart_name; |
| | } |
| | |
| | |
| void Controller::rescaleaccelMD(int step, int minimize) | void Controller::rescaleaccelMD(int step, int minimize) |
| { | { |
| if ( !simParams->accelMDOn ) return; | if ( !simParams->accelMDOn ) return; |
| |
| const BigReal accelMDTalpha = simParams->accelMDTalpha; | const BigReal accelMDTalpha = simParams->accelMDTalpha; |
| const int accelMDOutFreq = simParams->accelMDOutFreq; | const int accelMDOutFreq = simParams->accelMDOutFreq; |
| | |
| | //GaMD |
| | static BigReal VmaxP, VminP, VavgP, M2P=0, sigmaVP; |
| | static BigReal VmaxD, VminD, VavgD, M2D=0, sigmaVD; |
| | static BigReal k0P, kP, EP; |
| | static BigReal k0D, kD, ED; |
| | static int V_n = 1, iEusedD, iEusedP; |
| | static char warnD, warnP; |
| | static int restfreq; |
| | |
| | const int ntcmdprep = simParams->accelMDGcMDPrepSteps; |
| | const int ntcmd = simParams->accelMDGcMDSteps; |
| | const int ntebprep = ntcmd + simParams->accelMDGEquiPrepSteps; |
| | const int nteb = ntcmd + simParams->accelMDGEquiSteps; |
| | |
| | BigReal volume; |
| BigReal bondEnergy; | BigReal bondEnergy; |
| BigReal angleEnergy; | BigReal angleEnergy; |
| BigReal dihedralEnergy; | BigReal dihedralEnergy; |
| |
| BigReal miscEnergy; | BigReal miscEnergy; |
| BigReal amd_electEnergy; | BigReal amd_electEnergy; |
| BigReal amd_ljEnergy; | BigReal amd_ljEnergy; |
| | BigReal amd_ljEnergy_Corr = 0.; |
| BigReal amd_electEnergySlow; | BigReal amd_electEnergySlow; |
| BigReal amd_groLJEnergy; | BigReal amd_groLJEnergy; |
| BigReal amd_groGaussEnergy; | BigReal amd_groGaussEnergy; |
| |
| BigReal factor_dihe = 1; | BigReal factor_dihe = 1; |
| BigReal factor_tot = 1; | BigReal factor_tot = 1; |
| BigReal testV; | BigReal testV; |
| BigReal dV = 0; | BigReal dV = 0.; |
| Vector accelMDfactor; | Vector accelMDfactor; |
| Tensor vir; | Tensor vir; //auto initialized to 0 |
| Tensor vir_dihe; | Tensor vir_dihe; |
| Tensor vir_normal; | Tensor vir_normal; |
| Tensor vir_nbond; | Tensor vir_nbond; |
| Tensor vir_slow; | Tensor vir_slow; |
| | |
| | volume = lattice.volume(); |
| | |
| bondEnergy = amd_reduction->item(REDUCTION_BOND_ENERGY); | bondEnergy = amd_reduction->item(REDUCTION_BOND_ENERGY); |
| angleEnergy = amd_reduction->item(REDUCTION_ANGLE_ENERGY); | angleEnergy = amd_reduction->item(REDUCTION_ANGLE_ENERGY); |
| dihedralEnergy = amd_reduction->item(REDUCTION_DIHEDRAL_ENERGY); | dihedralEnergy = amd_reduction->item(REDUCTION_DIHEDRAL_ENERGY); |
| |
| amd_goTotalEnergy = goTotalEnergy; | amd_goTotalEnergy = goTotalEnergy; |
| } | } |
| | |
| | if( simParams->LJcorrection && volume ) { |
| | // Obtain tail correction (copied from printEnergies()) |
| | // This value is only printed for sanity check |
| | // accelMD currently does not 'boost' tail correction |
| | amd_ljEnergy_Corr = molecule->tail_corr_ener / volume; |
| | } |
| | |
| if ( !( step % slowFreq ) ) { | if ( !( step % slowFreq ) ) { |
| amd_electEnergySlow = amd_reduction->item(REDUCTION_ELECT_ENERGY_SLOW); | amd_electEnergySlow = amd_reduction->item(REDUCTION_ELECT_ENERGY_SLOW); |
| } else { | } else { |
| |
| crosstermEnergy + boundaryEnergy + miscEnergy + | crosstermEnergy + boundaryEnergy + miscEnergy + |
| amd_goTotalEnergy + amd_groLJEnergy + amd_groGaussEnergy; | amd_goTotalEnergy + amd_groLJEnergy + amd_groGaussEnergy; |
| | |
| | //GaMD |
| | if(simParams->accelMDG){ |
| | //fix step when there is accelMDFirstStep |
| | step -= simParams->accelMDFirstStep; |
| | |
| | if(step == simParams->firstTimestep) { |
| | iEusedD = iEusedP = simParams->accelMDGiE; |
| | warnD = warnP = '\0'; |
| | |
| | //restart file reading |
| | if(simParams->accelMDGRestart){ |
| | FILE *rest = fopen(simParams->accelMDGRestartFile, "r"); |
| | char line[256]; |
| | int dihe_n=0, tot_n=0; |
| | if(!rest){ |
| | sprintf(line, "Cannot open accelMDG restart file: %s", simParams->accelMDGRestartFile); |
| | NAMD_die(line); |
| | } |
| | |
| | while(fgets(line, 256, rest)){ |
| | if(line[0] == 'D'){ |
| | dihe_n = sscanf(line+1, " %d %la %la %la %la %la %la %la", |
| | &V_n, &VmaxD, &VminD, &VavgD, &sigmaVD, &M2D, &ED, &kD); |
| | } |
| | else if(line[0] == 'T'){ |
| | tot_n = sscanf(line+1, " %d %la %la %la %la %la %la %la", |
| | &V_n, &VmaxP, &VminP, &VavgP, &sigmaVP, &M2P, &EP, &kP); |
| | } |
| | } |
| | |
| | fclose(rest); |
| | |
| | V_n++; |
| | |
| | //check dihe settings |
| | if(simParams->accelMDdihe || simParams->accelMDdual){ |
| | if(dihe_n !=8) |
| | NAMD_die("Invalid dihedral potential energy format in accelMDG restart file"); |
| | k0D = kD * (VmaxD - VminD); |
| | iout << "GAUSSIAN ACCELERATED MD READ FROM RESTART FILE: DIHED" |
| | << " Vmax " << VmaxD << " Vmin " << VminD |
| | << " Vavg " << VavgD << " sigmaV " << sigmaVD |
| | << " E " << ED << " k " << kD |
| | << "\n" << endi; |
| | } |
| | |
| | //check tot settings |
| | if(!simParams->accelMDdihe || simParams->accelMDdual){ |
| | if(tot_n !=8) |
| | NAMD_die("Invalid total potential energy format in accelMDG restart file"); |
| | k0P = kP * (VmaxP - VminP); |
| | iout << "GAUSSIAN ACCELERATED MD READ FROM RESTART FILE: TOTAL" |
| | << " Vmax " << VmaxP << " Vmin " << VminP |
| | << " Vavg " << VavgP << " sigmaV " << sigmaVP |
| | << " E " << EP << " k " << kP |
| | << "\n" << endi; |
| | } |
| | |
| | iEusedD = (ED == VmaxD) ? 1 : 2; |
| | iEusedP = (EP == VmaxP) ? 1 : 2; |
| | } |
| | //local restfreq follows NAMD restartfreq (default: 500) |
| | restfreq = simParams->restartFrequency ? simParams->restartFrequency : 500; |
| | } |
| | |
| | //for dihedral potential |
| | if(simParams->accelMDdihe || simParams->accelMDdual){ |
| | testV = dihedralEnergy + crosstermEnergy; |
| | |
| | //write restart file every restartfreq steps |
| | if(step > simParams->firstTimestep - simParams->accelMDFirstStep && step % restfreq == 0) |
| | write_accelMDG_rest_file(step, 'D', V_n, VmaxD, VminD, VavgD, sigmaVD, M2D, ED, kD, |
| | true, false); |
| | //write restart file at the end of the simulation |
| | if( simParams->accelMDLastStep > 0 ){ |
| | if( step == simParams->accelMDLastStep ) |
| | write_accelMDG_rest_file(step, 'D', V_n, VmaxD, VminD, VavgD, sigmaVD, M2D, ED, kD, |
| | true, true); |
| | } |
| | else if(step == simParams->N - simParams->accelMDFirstStep) |
| | write_accelMDG_rest_file(step, 'D', V_n, VmaxD, VminD, VavgD, sigmaVD, M2D, ED, kD, |
| | true, true); |
| | |
| | //conventional MD |
| | if(step < ntcmd){ |
| | //very first step |
| | if(step == 0 && !simParams->accelMDGRestart){ |
| | //initialize stat |
| | VmaxD = VminD = VavgD = testV; |
| | M2D = sigmaVD = 0.; |
| | } |
| | //first step after cmdprep |
| | else if(step == ntcmdprep && ntcmdprep != 0){ |
| | //reset stat |
| | VmaxD = VminD = VavgD = testV; |
| | M2D = sigmaVD = 0.; |
| | iout << "GAUSSIAN ACCELERATED MD: RESET DIHEDRAL POTENTIAL STATISTICS\n" << endi; |
| | } |
| | //normal steps |
| | else |
| | calc_accelMDG_mean_std(testV, V_n, |
| | &VmaxD, &VminD, &VavgD, &M2D, &sigmaVD) ; |
| | |
| | //last cmd step |
| | if(step == ntcmd - 1){ |
| | calc_accelMDG_E_k(simParams->accelMDGiE, step, simParams->accelMDGSigma0D, |
| | VmaxD, VminD, VavgD, sigmaVD, &k0D, &kD, &ED, &iEusedD, &warnD); |
| | } |
| | } |
| | //equilibration |
| | else if(step < nteb){ |
| | calc_accelMDG_force_factor(kD, ED, testV, vir_dihe, |
| | &dV, &factor_dihe, &vir); |
| | |
| | //first step after cmd |
| | if(step == ntcmd && simParams->accelMDGresetVaftercmd){ |
| | //reset stat |
| | VmaxD = VminD = VavgD = testV; |
| | M2D = sigmaVD = 0.; |
| | iout << "GAUSSIAN ACCELERATED MD: RESET DIHEDRAL POTENTIAL STATISTICS\n" << endi; |
| | } |
| | else |
| | calc_accelMDG_mean_std(testV, V_n, |
| | &VmaxD, &VminD, &VavgD, &M2D, &sigmaVD) ; |
| | |
| | //steps after ebprep |
| | if(step >= ntebprep) |
| | calc_accelMDG_E_k(simParams->accelMDGiE, step, simParams->accelMDGSigma0D, |
| | VmaxD, VminD, VavgD, sigmaVD, &k0D, &kD, &ED, &iEusedD, &warnD); |
| | } |
| | //production |
| | else{ |
| | calc_accelMDG_force_factor(kD, ED, testV, vir_dihe, |
| | &dV, &factor_dihe, &vir); |
| | } |
| | |
| | } |
| | //for total potential |
| | if(!simParams->accelMDdihe || simParams->accelMDdual){ |
| | Tensor vir_tot = vir_normal + vir_nbond + vir_slow; |
| | testV = potentialEnergy; |
| | if(simParams->accelMDdual){ |
| | testV -= dihedralEnergy + crosstermEnergy; |
| | vir_tot -= vir_dihe; |
| | } |
| | |
| | //write restart file every restartfreq steps |
| | if(step > simParams->firstTimestep - simParams->accelMDFirstStep && step % restfreq == 0) |
| | write_accelMDG_rest_file(step, 'T', V_n, VmaxP, VminP, VavgP, sigmaVP, M2P, EP, kP, |
| | !simParams->accelMDdual, false); |
| | //write restart file at the end of simulation |
| | if( simParams->accelMDLastStep > 0 ){ |
| | if( step == simParams->accelMDLastStep ) |
| | write_accelMDG_rest_file(step, 'T', V_n, VmaxP, VminP, VavgP, sigmaVP, M2P, EP, kP, |
| | !simParams->accelMDdual, true); |
| | } |
| | else if(step == simParams->N - simParams->accelMDFirstStep) |
| | write_accelMDG_rest_file(step, 'T', V_n, VmaxP, VminP, VavgP, sigmaVP, M2P, EP, kP, |
| | !simParams->accelMDdual, true); |
| | |
| | //conventional MD |
| | if(step < ntcmd){ |
| | //very first step |
| | if(step == 0 && !simParams->accelMDGRestart){ |
| | //initialize stat |
| | VmaxP = VminP = VavgP = testV; |
| | M2P = sigmaVP = 0.; |
| | } |
| | //first step after cmdprep |
| | else if(step == ntcmdprep && ntcmdprep != 0){ |
| | //reset stat |
| | VmaxP = VminP = VavgP = testV; |
| | M2P = sigmaVP = 0.; |
| | iout << "GAUSSIAN ACCELERATED MD: RESET TOTAL POTENTIAL STATISTICS\n" << endi; |
| | } |
| | //normal steps |
| | else |
| | calc_accelMDG_mean_std(testV, V_n, |
| | &VmaxP, &VminP, &VavgP, &M2P, &sigmaVP); |
| | //last cmd step |
| | if(step == ntcmd - 1){ |
| | calc_accelMDG_E_k(simParams->accelMDGiE, step, simParams->accelMDGSigma0P, |
| | VmaxP, VminP, VavgP, sigmaVP, &k0P, &kP, &EP, &iEusedP, &warnP); |
| | } |
| | } |
| | //equilibration |
| | else if(step < nteb){ |
| | calc_accelMDG_force_factor(kP, EP, testV, vir_tot, |
| | &dV, &factor_tot, &vir); |
| | |
| | //first step after cmd |
| | if(step == ntcmd && simParams->accelMDGresetVaftercmd){ |
| | //reset stat |
| | VmaxP = VminP = VavgP = testV; |
| | M2P = sigmaVP = 0.; |
| | iout << "GAUSSIAN ACCELERATED MD: RESET TOTAL POTENTIAL STATISTICS\n" << endi; |
| | } |
| | else |
| | calc_accelMDG_mean_std(testV, V_n, |
| | &VmaxP, &VminP, &VavgP, &M2P, &sigmaVP); |
| | |
| | //steps after ebprep |
| | if(step >= ntebprep) |
| | calc_accelMDG_E_k(simParams->accelMDGiE, step, simParams->accelMDGSigma0P, |
| | VmaxP, VminP, VavgP, sigmaVP, &k0P, &kP, &EP, &iEusedP, &warnP); |
| | } |
| | //production |
| | else{ |
| | calc_accelMDG_force_factor(kP, EP, testV, vir_tot, |
| | &dV, &factor_tot, &vir); |
| | } |
| | |
| | } |
| | accelMDdVAverage += dV; |
| | |
| | //first step after ntcmdprep |
| | if((ntcmdprep > 0 && step == ntcmdprep) || |
| | (simParams->accelMDGresetVaftercmd && step == ntcmd)){ |
| | V_n = 1; |
| | } |
| | |
| | if(step < nteb) |
| | V_n++; |
| | |
| | // restore step |
| | step += simParams->accelMDFirstStep; |
| | } |
| | //aMD |
| | else{ |
| if (simParams->accelMDdihe) { | if (simParams->accelMDdihe) { |
| | |
| testV = dihedralEnergy + crosstermEnergy; | testV = dihedralEnergy + crosstermEnergy; |
| |
| accelMDdVAverage += dV; | accelMDdVAverage += dV; |
| } | } |
| } | } |
| | } |
| | |
| accelMDfactor[0]=factor_dihe; | accelMDfactor[0]=factor_dihe; |
| accelMDfactor[1]=factor_tot; | accelMDfactor[1]=factor_tot; |
| |
| << " IMPRP " << improperEnergy | << " IMPRP " << improperEnergy |
| << " ELECT " << amd_electEnergy+amd_electEnergySlow | << " ELECT " << amd_electEnergy+amd_electEnergySlow |
| << " VDW " << amd_ljEnergy | << " VDW " << amd_ljEnergy |
| << " POTENTIAL " << potentialEnergy << "\n" | << " POTENTIAL " << potentialEnergy; |
| << endi; | if(amd_ljEnergy_Corr) |
| | iout << " LJcorr " << amd_ljEnergy_Corr; |
| | iout << "\n" << endi; |
| | if(simParams->accelMDG){ |
| | if(simParams->accelMDdihe || simParams->accelMDdual) |
| | iout << "GAUSSIAN ACCELERATED MD: DIHED iE " << iEusedD |
| | << " Vmax " << VmaxD << " Vmin " << VminD |
| | << " Vavg " << VavgD << " sigmaV " << sigmaVD |
| | << " E " << ED << " k0 " << k0D << " k " << kD |
| | << "\n" << endi; |
| | if(warnD & 1) |
| | iout << "GAUSSIAN ACCELERATED MD: DIHED !!! WARNING: k0 > 1, " |
| | << "SWITCHED TO iE = 1 MODE !!!\n" << endi; |
| | if(warnD & 2) |
| | iout << "GAUSSIAN ACCELERATED MD: DIHED !!! WARNING: k0 <= 0, " |
| | << "SWITCHED TO iE = 1 MODE !!!\n" << endi; |
| | if(!simParams->accelMDdihe || simParams->accelMDdual) |
| | iout << "GAUSSIAN ACCELERATED MD: TOTAL iE " << iEusedP |
| | << " Vmax " << VmaxP << " Vmin " << VminP |
| | << " Vavg " << VavgP << " sigmaV " << sigmaVP |
| | << " E " << EP << " k0 " << k0P << " k " << kP |
| | << "\n" << endi; |
| | if(warnP & 1) |
| | iout << "GAUSSIAN ACCELERATED MD: TOTAL !!! WARNING: k0 > 1, " |
| | << "SWITCHED TO iE = 1 MODE !!!\n" << endi; |
| | if(warnP & 2) |
| | iout << "GAUSSIAN ACCELERATED MD: TOTAL !!! WARNING: k0 <= 0, " |
| | << "SWITCHED TO iE = 1 MODE !!!\n" << endi; |
| | warnD = warnP = '\0'; |
| | } |
| | |
| accelMDdVAverage = 0; | accelMDdVAverage = 0; |
| | |
| if (simParams->accelMDDebugOn) { | if (simParams->accelMDDebugOn) { |
| BigReal volume; | |
| Tensor p_normal; | Tensor p_normal; |
| Tensor p_nbond; | Tensor p_nbond; |
| Tensor p_slow; | Tensor p_slow; |
| Tensor p; | Tensor p; |
| if ( (volume=lattice.volume()) != 0. ) { | if ( volume != 0. ) { |
| p_normal = vir_normal/volume; | p_normal = vir_normal/volume; |
| p_nbond = vir_nbond/volume; | p_nbond = vir_nbond/volume; |
| p_slow = vir_slow/volume; | p_slow = vir_slow/volume; |