示例#1
0
    def __init__(self, input_mdp_file):

        self.IO = mdFileIO()
        self.p = self.IO.readParamFile(input_mdp_file)  # p for md parameters
        self.binw = 2 * self.p["half_boxboundary"] / self.p["binNum"]
        self.bins = np.linspace(-self.p["half_boxboundary"],
                                self.p["half_boxboundary"],
                                self.p["binNum"] + 1,
                                dtype=np.float64)
        self.colvars_coord = np.linspace(-self.p["half_boxboundary"],
                                         self.p["half_boxboundary"],
                                         self.p["binNum"] + 1,
                                         dtype=np.float64)

        self.mdInitializer   = mdEngine(self.p["nparticle"], self.p["box"], self.p["kb"],\
                                        self.p["time_step"], self.p["temperature"], self.p["ndims"],\
                                        self.p["mass"], self.p["thermoStatFlag"], self.getCurrentForce, self.p["frictCoeff"])

        self.initializeForce = Force(self.p["kb"], self.p["time_step"],
                                     self.p["temperature"], self.p["ndims"],
                                     self.p["mass"], self.p["thermoStatFlag"],
                                     self.p["frictCoeff"])

        # init coord and vel
        self.current_coord = np.zeros((self.p["nparticle"], self.p["ndims"]),
                                      dtype=np.float64)
        self.current_vel = self.mdInitializer.genVelocity()
        # init coord and vel

        if self.p["ndims"] == 1:
            self.colvars_force = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_FreeE = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_FreeE_NN = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_count = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_hist = np.zeros(len(self.bins), dtype=np.float64)
            self.temp = np.zeros(len(self.bins), dtype=np.float64)
            self.biasingPotentialConv = np.zeros(len(self.bins),
                                                 dtype=np.float64)
            self.biasingPotentialFromNN = np.zeros(len(self.bins),
                                                   dtype=np.float64)

        if self.p["ndims"] == 2:
            self.colvars_force = np.zeros(
                (self.p["ndims"], len(self.bins), len(self.bins)),
                dtype=np.float64)
            self.colvars_FreeE = np.zeros((len(self.bins), len(self.bins)),
                                          dtype=np.float64)
            self.colvars_FreeE_NN = np.zeros((len(self.bins), len(self.bins)),
                                             dtype=np.float64)
            self.colvars_count = np.zeros(
                (self.p["ndims"], len(self.bins), len(self.bins)),
                dtype=np.float64)
            self.colvars_hist = np.zeros((len(self.bins), len(self.bins)),
                                         dtype=np.float64)
            self.temp = np.zeros((len(self.bins), len(self.bins)),
                                 dtype=np.float64)
            self.biasingPotentialConv = np.zeros(
                (len(self.bins), len(self.bins)), dtype=np.float64)
            self.biasingPotentialFromNN = np.zeros(
                (len(self.bins), len(self.bins)), dtype=np.float64)
示例#2
0
class ABF(object):
    def __init__(self, input_mdp_file):

        self.IO = mdFileIO()
        self.p = self.IO.readParamFile(input_mdp_file)  # p for md parameters
        self.bins = np.linspace(-self.p["half_boxboundary"],
                                self.p["half_boxboundary"],
                                self.p["binNum"] + 1,
                                dtype=np.float64)
        self.colvars_coord = np.linspace(-self.p["half_boxboundary"],
                                         self.p["half_boxboundary"],
                                         self.p["binNum"] + 1,
                                         dtype=np.float64)

        self.mdInitializer   = mdEngine(self.p["nparticle"], self.p["box"], self.p["kb"],\
                                        self.p["time_step"], self.p["temperature"], self.p["ndims"],\
                                        self.p["mass"], self.p["thermoStatFlag"], self.getCurrentForce, self.p["frictCoeff"])

        self.initializeForce = Force(self.p["kb"], self.p["time_step"],
                                     self.p["temperature"], self.p["ndims"],
                                     self.p["mass"], self.p["thermoStatFlag"],
                                     self.p["frictCoeff"])

        # init coord and vel
        self.current_coord = np.zeros((self.p["nparticle"], self.p["ndims"]),
                                      dtype=np.float64)
        self.current_vel = self.mdInitializer.genVelocity()
        # init coord and vel

        self.criteriaCounter = 0
        self.criteriaFEBool = 0

        if self.p["ndims"] == 1:
            self.colvars_force = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_force_tmp = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_force_NN = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_count = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_hist = np.zeros(len(self.bins), dtype=np.float64)
            self.criteria_hist = np.zeros(len(self.bins), dtype=np.float64)
            self.criteria_prev = np.zeros(len(self.bins), dtype=np.float64)
            self.criteria_curr = np.zeros(len(self.bins), dtype=np.float64)
            self.criteria_FreeE = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_FreeE = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_FreeE_prev = np.zeros(len(self.bins),
                                               dtype=np.float64)
            self.colvars_FreeE_curr = np.zeros(len(self.bins),
                                               dtype=np.float64)

        if self.p["ndims"] == 2:
            self.colvars_force = np.zeros(
                (self.p["ndims"], len(self.bins), len(self.bins)),
                dtype=np.float64)
            self.colvars_force_tmp = np.zeros(
                (self.p["ndims"], len(self.bins), len(self.bins)),
                dtype=np.float64)
            self.colvars_force_NN = np.zeros(
                (self.p["ndims"], len(self.bins), len(self.bins)),
                dtype=np.float64)
            self.colvars_count = np.zeros(
                (self.p["ndims"], len(self.bins), len(self.bins)),
                dtype=np.float64)
            self.colvars_hist = np.zeros((len(self.bins), len(self.bins)),
                                         dtype=np.float64)
            self.criteria_hist = np.zeros((len(self.bins), len(self.bins)),
                                          dtype=np.float64)
            self.criteria_prev = np.zeros((len(self.bins), len(self.bins)),
                                          dtype=np.float64)
            self.criteria_curr = np.zeros((len(self.bins), len(self.bins)),
                                          dtype=np.float64)
            self.criteria_FreeE = np.zeros((len(self.bins), len(self.bins)),
                                           dtype=np.float64)
            self.colvars_FreeE = np.zeros((len(self.bins), len(self.bins)),
                                          dtype=np.float64)
            self.colvars_FreeE_prev = np.zeros(
                (len(self.bins), len(self.bins)), dtype=np.float64)
            self.colvars_FreeE_curr = np.zeros(
                (len(self.bins), len(self.bins)), dtype=np.float64)

    def _forceHistDistrRecord(self, coord_x, coord_y, d):

        if self.p["ndims"] == 1:
            self.colvars_count[getIndices(coord_x, self.bins)] += 1

        if self.p["ndims"] == 2:
            self.colvars_count[d][getIndices(coord_x, self.bins)][getIndices(
                coord_y, self.bins)] += 1

    def _forceDistrRecord(self, coord_x, updated_Fsys, coord_y, d):

        if self.p["ndims"] == 1:
            self.colvars_force[getIndices(coord_x, self.bins)] += updated_Fsys

        if self.p["ndims"] == 2:
            self.colvars_force[d][getIndices(coord_x, self.bins)][getIndices(
                coord_y, self.bins)] += updated_Fsys

    def _inverseGradient(self):
        """ cv == cartesian so return 1"""
        return 1

    def _Jacobian(self):
        """ cv == cartesian -> ln|J| = 0 so return 0"""
        return 0

    def _entropicCorrection(self):
        return self.p["kb"] * self.p["temperature"] * self._Jacobian()

    def _calBiasingForce(self, coord_x, coord_y, d):

        if (self.p["abfCheckFlag"] == "yes" and self.p["nnCheckFlag"]
                == "no") or (self.p["abfCheckFlag"] == "yes"
                             and self.p["nnCheckFlag"] == "yes"
                             and self.criteriaFEBool == 0):
            if self.p["ndims"] == 1:
                if self.colvars_count[getIndices(coord_x, self.bins)] == 0:
                    return 0
                else:
                    return -(
                        (self.colvars_force[getIndices(coord_x, self.bins)] /
                         self.colvars_count[getIndices(coord_x, self.bins)] +
                         self._entropicCorrection()) * self._inverseGradient())

            if self.p["ndims"] == 2:
                if self.colvars_count[d][getIndices(coord_x,
                                                    self.bins)][getIndices(
                                                        coord_y,
                                                        self.bins)] == 0:
                    return 0
                else:
                    return -((self.colvars_force[d][getIndices(coord_x, self.bins)][getIndices(coord_y, self.bins)] / self.colvars_count[d][getIndices(coord_x, self.bins)][getIndices(coord_y, self.bins)] +\
                            self._entropicCorrection()) * self._inverseGradient())

        if (self.p["abfCheckFlag"] == "yes" and self.p["nnCheckFlag"]
                == "yes") and self.criteriaFEBool > 0:
            if self.p["ndims"] == 1:
                return -self.colvars_force_NN[getIndices(coord_x, self.bins)]
            if self.p["ndims"] == 2:
                return -self.colvars_force_NN[d][getIndices(
                    coord_x, self.bins)][getIndices(coord_y, self.bins)]

    def _abfDecorator(func):
        def _wrapper(self, coord_x, d, vel, coord_y):
            Fabf = func(self, coord_x, d, vel, coord_y)
            currentFsys = self.initializeForce.getForce(
                coord_x, d, vel, coord_y)
            self._forceDistrRecord(coord_x, currentFsys, coord_y, d)
            self._forceHistDistrRecord(coord_x, coord_y, d)
            return Fabf + currentFsys

        return _wrapper

    @_abfDecorator
    def getCurrentForce(self, coord_x, d, vel, coord_y):

        if self.p["abfCheckFlag"] == "no" and self.p["nnCheckFlag"] == "no":
            Fabf = 0
        else:
            Fabf = self._calBiasingForce(coord_x, coord_y, d)
        return Fabf

    def _criteriaModCurr(self):
        if self.criteriaCounter <= 1:
            self.criteria_prev = copy.deepcopy(
                self.colvars_hist / np.sum(self.colvars_hist))  # w/o unbiasing
        else:
            self.criteria_curr = copy.deepcopy(
                self.colvars_hist / np.sum(self.colvars_hist))  # w/o unbiasing

    def _criteriaModPrev(self):
        self.criteria_prev = copy.deepcopy(self.criteria_curr)

    def _criteriaCheck(self, holder, prev, curr, msERROR):
        if self.criteriaCounter >= 2:
            holder = ((prev - curr) / curr)**2
            holder[np.isnan(holder)] = 0.0
            holder[np.isinf(holder)] = 0.0
            holder[np.isneginf(holder)] = 0.0
            holder = holder[holder > msERROR]
            return not holder.size
        return False

    def _accumulateColvarsHist(self):
        for n in range(self.p["nparticle"]):
            if self.p["ndims"] == 1:
                self.colvars_hist[getIndices(self.current_coord[n][0],
                                             self.bins)] += 1
            elif self.p["ndims"] == 2:
                self.colvars_hist[getIndices(self.current_coord[n][0],
                                             self.bins)][getIndices(
                                                 self.current_coord[n][1],
                                                 self.bins)] += 1

    def getCurrentFreeEnergy(self):

        if self.p["nnCheckFlag"] == "no":
            self.colvars_force_tmp = copy.deepcopy(self.colvars_force /
                                                   self.colvars_count)
            self.colvars_force_tmp[np.isnan(self.colvars_force_tmp)] = 0
            self.colvars_force_tmp = paddingRightMostBin(
                self.colvars_force_tmp)
        else:
            self.colvars_force_tmp = copy.deepcopy(self.colvars_force_NN)
            self.colvars_force_tmp[np.isnan(self.colvars_force_tmp)] = 0
            self.colvars_force_tmp = paddingRightMostBin(
                self.colvars_force_tmp)

        self.colvars_FreeE = integrator(self.p["ndims"], self.colvars_coord,
                                        self.colvars_force_tmp,
                                        self.p["half_boxboundary"],
                                        self.p["init_frame"],
                                        self.p["shiftConst"], "tempFreeE.dat")

    def _learningProxy(self):
        if self.p["nnCheckFlag"] == "yes":
            output = trainingANN("loss.dat", "hyperparam.dat", self.p["ndims"],
                                 len(self.bins))

            self.colvars_force = (self.colvars_force / self.colvars_count)
            self.colvars_force[np.isnan(
                self.colvars_force)] = 0  # 0/0 = nan n/0 = inf
            self.colvars_force = paddingRightMostBin(self.colvars_force)

            if self.p["init_frame"] < self.p["earlyStopCheck"] * self.p[
                    "switchSteps"]:
                self.colvars_force_NN = \
                output.training(self.colvars_coord, self.colvars_force, self.p["earlyLearningRate"], self.p["earlyRegularCoeff"], self.p["earlyEpoch"], self.p["nnOutputFreq"])
            else:
                self.colvars_force_NN = \
                output.training(self.colvars_coord, self.colvars_force, self.p["lateLearningRate"], self.p["lateRegularCoeff"], self.p["lateEpoch"], self.p["nnOutputFreq"])

            self.colvars_force = (self.colvars_force * self.colvars_count)

    def mdrun(self):

        init_real_world_time = time.time()

        # PRE-PROCESSING
        lammpstrj = open(
            "m%.1f_T%.3f_gamma%.4f_len_%d_%s_%s.lammpstrj" %
            (self.p["mass"], self.p["temperature"], self.p["frictCoeff"],
             self.p["total_frame"], self.p["abfCheckFlag"],
             self.p["nnCheckFlag"]), "w")
        forceOnCVs = open(
            "Force_m%.1fT%.3f_gamma%.4f_len_%d_%s_%s.dat" %
            (self.p["mass"], self.p["temperature"], self.p["frictCoeff"],
             self.p["total_frame"], self.p["abfCheckFlag"],
             self.p["nnCheckFlag"]), "w")
        histogramOnCVs = open(
            "Hist_m%.1fT%.3f_gamma%.4f_len_%d_%s_%s.dat" %
            (self.p["mass"], self.p["temperature"], self.p["frictCoeff"],
             self.p["total_frame"], self.p["abfCheckFlag"],
             self.p["nnCheckFlag"]), "w")

        withANN = open("instantForceWANN_" + str(self.p["ndims"]) + "D.dat",
                       "a")
        woANN = open("instantForceWOANN_" + str(self.p["ndims"]) + "D.dat",
                     "a")
        earlyFreeE = open("earlyFreeE.dat", "a")
        FinalFE = open("FreeE.dat", "w")

        # START of the simulation
        self.IO.writeParams(self.p)
        self.IO.lammpsFormatColvarsOutput(self.p["ndims"], self.p["nparticle"],
                                          self.p["half_boxboundary"],
                                          self.p["init_frame"],
                                          self.current_coord, lammpstrj,
                                          self.p["writeFreq"])
        self.IO.printCurrentStatus(self.p["init_frame"], init_real_world_time)

        while self.p["init_frame"] < self.p["total_frame"]:

            self.p["init_frame"] += 1
            self.IO.printCurrentStatus(self.p["init_frame"],
                                       init_real_world_time)
            self.mdInitializer.checkTargetTemperature(self.current_vel,
                                                      self.p["init_frame"],
                                                      self.p["total_frame"])

            if self.p["init_frame"] % self.p["earlyStopCheck"] == 0 and self.p[
                    "init_frame"] != 0 and self.p["abfCheckFlag"] == "yes":
                self.criteriaCounter += 1
                self._criteriaModCurr()

                if self._criteriaCheck(self.criteria_hist, self.criteria_prev,
                                       self.criteria_curr,
                                       self.p["trainingCriteria"]):

                    if self.p["nnCheckFlag"] == "no":
                        self.getCurrentFreeEnergy()
                        self.IO.certainFrequencyOutput(self.colvars_coord,
                                                       self.colvars_FreeE,
                                                       self.colvars_hist,
                                                       self.p["init_frame"],
                                                       earlyFreeE)
                        self.temp = paddingRightMostBin(self.colvars_force /
                                                        self.colvars_count)
                        self.IO.certainFrequencyOutput(self.colvars_coord,
                                                       self.temp,
                                                       self.colvars_count,
                                                       self.p["init_frame"],
                                                       woANN)

                    else:
                        self._learningProxy()
                        self.getCurrentFreeEnergy()
                        self.IO.certainFrequencyOutput(self.colvars_coord,
                                                       self.colvars_FreeE,
                                                       self.colvars_hist,
                                                       self.p["init_frame"],
                                                       earlyFreeE)
                        self.IO.certainFrequencyOutput(self.colvars_coord,
                                                       self.colvars_force_NN,
                                                       self.colvars_count,
                                                       self.p["init_frame"],
                                                       withANN)

                    # retrieve FE
                    if self.criteriaFEBool % 2 == 0:
                        self.colvars_FreeE_prev = copy.deepcopy(
                            self.colvars_FreeE)
                    else:
                        self.colvars_FreeE_curr = copy.deepcopy(
                            self.colvars_FreeE)

                    self.criteriaFEBool += 1

                    # To clean invalid data (inf, nan), we let some data == 0, this would cause issues when evaluating criteria, so we should at least do twice
                    if self._criteriaCheck(
                            self.criteria_FreeE, self.colvars_FreeE_prev,
                            self.colvars_FreeE_curr, self.p["simlEndCriteria"]
                    ) and self.criteriaFEBool >= 2:
                        break
                    # retrieve FE
                if self.criteriaCounter > 1:
                    self._criteriaModPrev()
            self.mdInitializer.velocityVerletSimple(self.current_coord,
                                                    self.current_vel)
            self._accumulateColvarsHist()

            self.IO.lammpsFormatColvarsOutput(self.p["ndims"],
                                              self.p["nparticle"],
                                              self.p["half_boxboundary"],
                                              self.p["init_frame"],
                                              self.current_coord, lammpstrj,
                                              self.p["writeFreq"])
        # END of the simulation

        # POST-PROCESSING
        probability = copy.deepcopy(
            (self.colvars_hist / np.sum(self.colvars_hist)))
        probability = paddingRightMostBin(probability)
        self.IO.propertyOnColvarsOutput(self.bins, probability,
                                        self.colvars_hist, histogramOnCVs)
        self.IO.propertyOnColvarsOutput(self.bins, self.colvars_FreeE,
                                        self.colvars_hist, FinalFE)

        if self.p["nnCheckFlag"] == "yes":
            self.IO.propertyOnColvarsOutput(self.bins, self.colvars_force_NN,
                                            self.colvars_count, forceOnCVs)

        else:
            self.colvars_force = (self.colvars_force / self.colvars_count)
            self.colvars_force[np.isnan(self.colvars_force)] = 0
            self.colvars_force = paddingRightMostBin(self.colvars_force)
            self.IO.propertyOnColvarsOutput(self.bins, self.colvars_force,
                                            self.colvars_count, forceOnCVs)

        # ndims >= 2 -> plot using matplotlib
        if self.p["ndims"] == 2:
            s = rendering(self.p["ndims"], self.p["half_boxboundary"],
                          self.p["binNum"], self.p["temperature"])
            s.render(
                probability,
                name=str(self.p["abfCheckFlag"] + "_" + self.p["nnCheckFlag"] +
                         "_" + "boltzDist" + str(self.p["ndims"]) + "D"))
            s.render(
                self.colvars_FreeE,
                name=str(self.p["abfCheckFlag"] + "_" + self.p["nnCheckFlag"] +
                         "_" + "FEsurface" + str(self.p["ndims"]) + "D"))
            if self.p["nnCheckFlag"] == "yes":
                try:
                    s.render(self.colvars_force_NN[0],
                             name=str(self.p["abfCheckFlag"] + "_" +
                                      self.p["nnCheckFlag"] + "_" + "forcex" +
                                      str(self.p["ndims"]) + "D"))
                    s.render(self.colvars_force_NN[1],
                             name=str(self.p["abfCheckFlag"] + "_" +
                                      self.p["nnCheckFlag"] + "_" + "forcey" +
                                      str(self.p["ndims"]) + "D"))
                except:  # no chance to train
                    pass
            else:
                s.render(self.colvars_force[0],
                         name=str(self.p["abfCheckFlag"] + "_" +
                                  self.p["nnCheckFlag"] + "_" + "forcex" +
                                  str(self.p["ndims"]) + "D"))
                s.render(self.colvars_force[1],
                         name=str(self.p["abfCheckFlag"] + "_" +
                                  self.p["nnCheckFlag"] + "_" + "forcey" +
                                  str(self.p["ndims"]) + "D"))

        # Close files, mkdir and mv files
        self.IO.closeAllFiles(lammpstrj, forceOnCVs, histogramOnCVs, withANN,
                              woANN, earlyFreeE, FinalFE)
        self.IO.makeDirAndMoveFiles(self.p["ndims"], self.p["mass"], self.p["temperature"], self.p["frictCoeff"], self.p["total_frame"],\
                                    self.p["abfCheckFlag"], self.p["nnCheckFlag"], __class__.__name__)
示例#3
0
class ABP(object):
    def __init__(self, input_mdp_file):

        self.IO = mdFileIO()
        self.p = self.IO.readParamFile(input_mdp_file)  # p for md parameters
        self.binw = 2 * self.p["half_boxboundary"] / self.p["binNum"]
        self.bins = np.linspace(-self.p["half_boxboundary"],
                                self.p["half_boxboundary"],
                                self.p["binNum"] + 1,
                                dtype=np.float64)
        self.colvars_coord = np.linspace(-self.p["half_boxboundary"],
                                         self.p["half_boxboundary"],
                                         self.p["binNum"] + 1,
                                         dtype=np.float64)

        self.mdInitializer   = mdEngine(self.p["nparticle"], self.p["box"], self.p["kb"],\
                                        self.p["time_step"], self.p["temperature"], self.p["ndims"],\
                                        self.p["mass"], self.p["thermoStatFlag"], self.getCurrentForce, self.p["frictCoeff"])

        self.initializeForce = Force(self.p["kb"], self.p["time_step"],
                                     self.p["temperature"], self.p["ndims"],
                                     self.p["mass"], self.p["thermoStatFlag"],
                                     self.p["frictCoeff"])

        # init coord and vel
        self.current_coord = np.zeros((self.p["nparticle"], self.p["ndims"]),
                                      dtype=np.float64)
        self.current_vel = self.mdInitializer.genVelocity()

        self.criteriaCounter = 0
        self.criteriaFEBool = 0

        if self.p["ndims"] == 1:
            self.colvars_force = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_FreeE = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_FreeE_NN = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_FreeE_prev = np.zeros(len(self.bins),
                                               dtype=np.float64)
            self.colvars_FreeE_curr = np.zeros(len(self.bins),
                                               dtype=np.float64)
            self.colvars_count = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_hist = np.zeros(len(self.bins), dtype=np.float64)
            self.criteria_hist = np.zeros(len(self.bins), dtype=np.float64)
            self.criteria_FreeE = np.zeros(len(self.bins), dtype=np.float64)
            self.criteria_prev = np.zeros(len(self.bins), dtype=np.float64)
            self.criteria_curr = np.zeros(len(self.bins), dtype=np.float64)
            self.biasingPotentialConv = np.zeros(len(self.bins),
                                                 dtype=np.float64)
            self.biasingPotentialFromNN = np.zeros(len(self.bins),
                                                   dtype=np.float64)

        if self.p["ndims"] == 2:
            self.colvars_force = np.zeros(
                (self.p["ndims"], len(self.bins), len(self.bins)),
                dtype=np.float64)
            self.colvars_FreeE = np.zeros((len(self.bins), len(self.bins)),
                                          dtype=np.float64)
            self.colvars_FreeE_NN = np.zeros((len(self.bins), len(self.bins)),
                                             dtype=np.float64)
            self.colvars_FreeE_prev = np.zeros(
                (len(self.bins), len(self.bins)), dtype=np.float64)
            self.colvars_FreeE_curr = np.zeros(
                (len(self.bins), len(self.bins)), dtype=np.float64)
            self.colvars_count = np.zeros(
                (self.p["ndims"], len(self.bins), len(self.bins)),
                dtype=np.float64)
            self.colvars_hist = np.zeros((len(self.bins), len(self.bins)),
                                         dtype=np.float64)
            self.criteria_hist = np.zeros((len(self.bins), len(self.bins)),
                                          dtype=np.float64)
            self.criteria_FreeE = np.zeros((len(self.bins), len(self.bins)),
                                           dtype=np.float64)
            self.criteria_prev = np.zeros((len(self.bins), len(self.bins)),
                                          dtype=np.float64)
            self.criteria_curr = np.zeros((len(self.bins), len(self.bins)),
                                          dtype=np.float64)
            self.biasingPotentialConv = np.zeros(
                (len(self.bins), len(self.bins)), dtype=np.float64)
            self.biasingPotentialFromNN = np.zeros(
                (len(self.bins), len(self.bins)), dtype=np.float64)

    def _forceHistDistrRecord(self, coord_x, coord_y, d):

        if self.p["ndims"] == 1:
            self.colvars_count[getIndices(coord_x, self.bins)] += 1

        if self.p["ndims"] == 2:
            self.colvars_count[d][getIndices(coord_x, self.bins)][getIndices(
                coord_y, self.bins)] += 1

    def _forceDistrRecord(self, coord_x, updated_Fsys, coord_y, d):

        if self.p["ndims"] == 1:
            self.colvars_force[getIndices(coord_x, self.bins)] += updated_Fsys

        if self.p["ndims"] == 2:
            self.colvars_force[d][getIndices(coord_x, self.bins)][getIndices(
                coord_y, self.bins)] += updated_Fsys

    def _biasingPotential(self, coord_x, coord_y=None):

        if self.p["abfCheckFlag"] == "yes" and self.p["nnCheckFlag"] == "yes":

            if self.p["ndims"] == 1:
                if self.p["init_frame"] <= self.p[
                        "earlyStopCheck"]:  # initial sweep
                    return 0
                else:
                    return self.biasingPotentialFromNN[getIndices(
                        coord_x, self.bins)]

            if self.p["ndims"] == 2:
                if self.p["init_frame"] <= self.p[
                        "earlyStopCheck"]:  # initial sweep
                    return 0
                else:
                    return self.biasingPotentialFromNN[getIndices(
                        coord_x, self.bins)][getIndices(coord_y, self.bins)]

        elif self.p["abfCheckFlag"] == "yes" and self.p["nnCheckFlag"] == "no":

            if self.p["ndims"] == 1:
                if self.p["init_frame"] <= self.p["earlyStopCheck"]:
                    return 0
                else:
                    return self.biasingPotentialConv[getIndices(
                        coord_x, self.bins)]

            if self.p["ndims"] == 2:
                if self.p["init_frame"] <= self.p["earlyStopCheck"]:
                    return 0
                else:
                    return self.biasingPotentialConv[getIndices(
                        coord_x, self.bins)][getIndices(coord_y, self.bins)]

        else:
            return 0

    def _calBiasingForce(self, coord_x, coord_y, d):

        if (self.p["abfCheckFlag"] == "yes" and self.p["nnCheckFlag"]
                == "no") or (self.p["abfCheckFlag"] == "yes"
                             and self.p["nnCheckFlag"] == "yes" and
                             self.p["init_frame"] <= self.p["earlyStopCheck"]):
            bsForce = copy.deepcopy(self.colvars_FreeE)

        elif (self.p["abfCheckFlag"] == "yes" and self.p["nnCheckFlag"]
              == "yes") and self.p["init_frame"] > self.p["earlyStopCheck"]:
            bsForce = copy.deepcopy(self.colvars_FreeE_NN)

        elif self.p["abfCheckFlag"] == "no" and self.p["nnCheckFlag"] == "no":
            return 0

        if self.p["ndims"] == 1:
            bsForce = np.diff(bsForce)
            bsForce = np.append(bsForce,
                                bsForce[-1])  # padding to the right legnth
            bsForce = (bsForce / self.binw)
            return bsForce[getIndices(coord_x, self.bins)]

        if self.p["ndims"] == 2:

            if d == 0:
                bsForce = np.diff(bsForce,
                                  axis=0)  # axis=0 for x; axis=1 for y
                bsForce = np.append(bsForce, [bsForce[-1, :]],
                                    axis=0)  # padding to the right length
                bsForce = (bsForce / self.binw)

            elif d == 1:
                bsForce = np.diff(bsForce, axis=1)
                bsForce = np.append(bsForce,
                                    bsForce[:, -1][:, np.newaxis],
                                    axis=1)  # padding to the right length
                bsForce = (bsForce / self.binw)

            return bsForce[getIndices(coord_x, self.bins)][getIndices(
                coord_y, self.bins)]

    def _abpDecorator(func):
        def _wrapper(self, coord_x, d, vel, coord_y):
            Fabf = func(self, coord_x, d, vel, coord_y)
            currentFsys = self.initializeForce.getForce(
                coord_x, d, vel, coord_y)
            self._forceDistrRecord(coord_x, currentFsys, coord_y, d)
            self._forceHistDistrRecord(coord_x, coord_y, d)
            return Fabf + currentFsys

        return _wrapper

    @_abpDecorator
    def getCurrentForce(self, coord_x, d, vel, coord_y):
        Fabf = self._calBiasingForce(coord_x, coord_y, d)
        return Fabf

    def _probability(self):
        """ 1. unbias the historgram
        2. calculate the partition function
        3. calculate the probability and return it """

        if self.p["abfCheckFlag"] == "yes" and self.p["nnCheckFlag"] == "yes":
            maxValueOfBiasingPotential = np.amax(self.biasingPotentialFromNN)

        elif self.p["abfCheckFlag"] == "yes" and self.p["nnCheckFlag"] == "no":
            maxValueOfBiasingPotential = np.amax(self.biasingPotentialConv)

        else:
            maxValueOfBiasingPotential = 0

        if self.p["ndims"] == 1:
            rwHist = np.zeros(len(self.bins), dtype=np.float64)

            for i in range(len(self.colvars_hist)):
                rwHist[i] = self.colvars_hist[i] * np.exp(self._biasingPotential(self.bins[i]) / self.p["kb"] / self.p["temperature"]) *\
                            np.exp(-maxValueOfBiasingPotential / self.p["kb"] / self.p["temperature"])

        if self.p["ndims"] == 2:
            rwHist = np.zeros((len(self.bins), len(self.bins)),
                              dtype=np.float64)
            for i in range(len(self.colvars_hist)):
                for j in range(len(self.colvars_hist)):
                    rwHist[i][j] = self.colvars_hist[i][j] * np.exp(self._biasingPotential(self.bins[i], self.bins[j]) / self.p["kb"] / self.p["temperature"]) *\
                                                             np.exp(-maxValueOfBiasingPotential / self.p["kb"] / self.p["temperature"])
        partitionFunc = np.sum(rwHist)
        probabilityDistr = rwHist / partitionFunc

        return probabilityDistr

    def getCurrentFreeEnergy(self):
        self.colvars_FreeE = -self.p["kb"] * self.p["temperature"] * np.log(
            self._probability())
        self.colvars_FreeE[np.isneginf(
            self.colvars_FreeE)] = 0.0  # deal with -inf
        self.colvars_FreeE[np.isinf(
            self.colvars_FreeE)] = 0.0  # deal with  inf
        self.colvars_FreeE = paddingRightMostBin(self.colvars_FreeE)

    def _updateBiasingPotential(self):
        self.biasingPotentialFromNN = -copy.deepcopy(
            self.colvars_FreeE_NN)  # phi(x) = -Fhat(x); for ANN
        self.biasingPotentialConv = -copy.deepcopy(
            self.colvars_FreeE)  # phi(x) = -Fhat(x); for non-ANN

    def _criteriaModCurr(self):
        if self.criteriaCounter <= 1:
            self.criteria_prev = self._probability()
        else:
            self.criteria_curr = self._probability()

    def _criteriaModPrev(self):
        self.criteria_prev = copy.deepcopy(self.criteria_curr)

    def _criteriaCheck(self, holder, prev, curr, msERROR):

        if self.criteriaCounter >= 2:
            holder = ((prev - curr) / curr)**2
            holder[np.isnan(holder)] = 0.0
            holder[np.isinf(holder)] = 0.0
            holder[np.isneginf(holder)] = 0.0
            holder = holder[holder > msERROR]
            return not holder.size
        return False

    def _learningProxy(self):
        if self.p["nnCheckFlag"] == "yes":
            output = trainingANN("loss.dat", "hyperparam.dat", self.p["ndims"],
                                 len(self.bins), self.binw)

            if self.p["init_frame"] < self.p["earlyStopCheck"] * self.p[
                    "switchSteps"]:
                self.colvars_FreeE_NN , _ = \
                output.training(self.colvars_coord, self.colvars_FreeE, self.p["earlyLearningRate"], self.p["earlyRegularCoeff"], self.p["earlyEpoch"], self.p["nnOutputFreq"])

            else:
                self.colvars_FreeE_NN , _ = \
                output.training(self.colvars_coord, self.colvars_FreeE, self.p["lateLearningRate"], self.p["lateRegularCoeff"], self.p["lateEpoch"], self.p["nnOutputFreq"])

    def _accumulateColvarsHist(self):
        for n in range(self.p["nparticle"]):
            if self.p["ndims"] == 1:
                self.colvars_hist[getIndices(self.current_coord[n][0],
                                             self.bins)] += 1
            elif self.p["ndims"] == 2:
                self.colvars_hist[getIndices(self.current_coord[n][0],
                                             self.bins)][getIndices(
                                                 self.current_coord[n][1],
                                                 self.bins)] += 1

    def _resetColvarsHist(self):
        self.colvars_hist.fill(0)

    def mdrun(self):

        init_real_world_time = time.time()

        # PRE-PROCESSING
        lammpstrj = open(
            "m%.1f_T%.5f_gamma%.2f_len_%d.lammpstrj" %
            (self.p["mass"], self.p["temperature"], self.p["frictCoeff"],
             self.p["total_frame"]), "w")
        forceOnCVs = open(
            "Force_m%.1fT%.5f_gamma%.2f_len_%d.dat" %
            (self.p["mass"], self.p["temperature"], self.p["frictCoeff"],
             self.p["total_frame"]), "w")
        freeEOnCVs = open(
            "FreeE_m%.1fT%.5f_gamma%.2f_len_%d.dat" %
            (self.p["mass"], self.p["temperature"], self.p["frictCoeff"],
             self.p["total_frame"]), "w")
        histogramOnCVs = open(
            "Hist_m%.1fT%.5f_gamma%.2f_len_%d.dat" %
            (self.p["mass"], self.p["temperature"], self.p["frictCoeff"],
             self.p["total_frame"]), "w")
        annABP = open("instantFreeEWANN_" + str(self.p["ndims"]) + "D.dat",
                      "a")
        convABP = open("instantFreeEWOANN_" + str(self.p["ndims"]) + "D.dat",
                       "a")
        tempHist = open("tempHist.dat", "a")
        tempBsp = open("tempBsp.dat", "a")
        earlyFreeE = open("earlyFreeE.dat", "a")

        # START of the simulation
        self.IO.writeParams(self.p)
        self.IO.lammpsFormatColvarsOutput(self.p["ndims"], self.p["nparticle"],
                                          self.p["half_boxboundary"],
                                          self.p["init_frame"],
                                          self.current_coord, lammpstrj,
                                          self.p["writeFreq"])
        self.IO.printCurrentStatus(self.p["init_frame"], init_real_world_time)

        while self.p["init_frame"] < self.p["total_frame"]:

            self.p["init_frame"] += 1
            self.IO.printCurrentStatus(self.p["init_frame"],
                                       init_real_world_time)
            self.mdInitializer.checkTargetTemperature(self.current_vel,
                                                      self.p["init_frame"],
                                                      self.p["total_frame"])

            # early stop
            if self.p["init_frame"] % self.p["earlyStopCheck"] == 0 and self.p[
                    "init_frame"] != 0 and self.p["abfCheckFlag"] == "yes":
                self.criteriaCounter += 1
                self._criteriaModCurr()

                if self._criteriaCheck(self.criteria_hist, self.criteria_prev,
                                       self.criteria_curr,
                                       self.p["trainingCriteria"]):
                    self.getCurrentFreeEnergy()

                    if self.p["nnCheckFlag"] == "no":
                        self.IO.certainFrequencyOutput(self.colvars_coord,
                                                       self.colvars_FreeE,
                                                       self.colvars_hist,
                                                       self.p["init_frame"],
                                                       earlyFreeE)

                    else:
                        self._learningProxy()
                        self.IO.certainFrequencyOutput(self.colvars_coord,
                                                       self.colvars_FreeE_NN,
                                                       self.colvars_hist,
                                                       self.p["init_frame"],
                                                       earlyFreeE)

                    self._updateBiasingPotential()

                    # retrieve FE
                    if self.criteriaFEBool % 2 == 0:
                        if self.p["nnCheckFlag"] == "yes":
                            self.colvars_FreeE_prev = copy.deepcopy(
                                self.colvars_FreeE_NN)
                        else:
                            self.colvars_FreeE_prev = copy.deepcopy(
                                self.colvars_FreeE)
                    else:
                        if self.p["nnCheckFlag"] == "yes":
                            self.colvars_FreeE_curr = copy.deepcopy(
                                self.colvars_FreeE_NN)
                        else:
                            self.colvars_FreeE_curr = copy.deepcopy(
                                self.colvars_FreeE)

                    self.criteriaFEBool += 1

                    # To clean invalid data (inf, nan), we let some data == 0, this would cause issues when evaluating criteria, so we should at least do twice
                    if self._criteriaCheck(
                            self.criteria_FreeE, self.colvars_FreeE_prev,
                            self.colvars_FreeE_curr, self.p["simlEndCriteria"]
                    ) and self.criteriaFEBool >= 2:
                        break
                    # retrieve FE
                    self._resetColvarsHist()

                if self.criteriaCounter > 1:
                    self._criteriaModPrev()

            self.mdInitializer.velocityVerletSimple(self.current_coord,
                                                    self.current_vel)
            self._accumulateColvarsHist()

            self.IO.lammpsFormatColvarsOutput(self.p["ndims"],
                                              self.p["nparticle"],
                                              self.p["half_boxboundary"],
                                              self.p["init_frame"],
                                              self.current_coord, lammpstrj,
                                              self.p["writeFreq"])

        # END of the simulation

        # POST-PROCESSING
        probability = copy.deepcopy(
            (self.colvars_hist / np.sum(self.colvars_hist)))
        probability = paddingRightMostBin(probability)
        self.IO.propertyOnColvarsOutput(self.bins, probability,
                                        self.colvars_hist, histogramOnCVs)

        self.colvars_force = (self.colvars_force / self.colvars_count)
        self.colvars_force[np.isnan(self.colvars_force)] = 0
        self.colvars_force = paddingRightMostBin(self.colvars_force)
        self.IO.propertyOnColvarsOutput(self.bins, self.colvars_force,
                                        self.colvars_count, forceOnCVs)

        if self.p["abfCheckFlag"] == "yes" and self.p["nnCheckFlag"] == "yes":
            self.IO.propertyOnColvarsOutput(self.bins, self.colvars_FreeE_NN,
                                            self.colvars_hist, freeEOnCVs)

        else:
            self.IO.propertyOnColvarsOutput(self.bins, self.colvars_FreeE,
                                            self.colvars_hist, freeEOnCVs)

        if self.p["ndims"] == 2:
            s = rendering(self.p["ndims"], self.p["half_boxboundary"],
                          self.p["binNum"], self.p["temperature"])
            s.render(
                self.colvars_FreeE,
                name=str(self.p["abfCheckFlag"] + "_" + self.p["nnCheckFlag"] +
                         "_" + "FEsurface_Original" + str(self.p["ndims"]) +
                         "D"))
            s.render(
                self.colvars_force[0],
                name=str(self.p["abfCheckFlag"] + "_" + self.p["nnCheckFlag"] +
                         "_" + "forceX_UnderABP" + str(self.p["ndims"]) + "D"))
            s.render(
                self.colvars_force[1],
                name=str(self.p["abfCheckFlag"] + "_" + self.p["nnCheckFlag"] +
                         "_" + "forceY_UnderABP" + str(self.p["ndims"]) + "D"))
            s.render(
                probability,
                name=str(self.p["abfCheckFlag"] + "_" + self.p["nnCheckFlag"] +
                         "_" + "boltzDistr_NN" + str(self.p["ndims"]) + "D"))
            if self.p["abfCheckFlag"] == "yes" and self.p[
                    "nnCheckFlag"] == "yes":
                s.render(self.colvars_FreeE_NN,
                         name=str(self.p["abfCheckFlag"] + "_" +
                                  self.p["nnCheckFlag"] + "_" +
                                  "FEsurface_NN" + str(self.p["ndims"]) + "D"))

        # Close files, mdkir and mv files
        self.IO.closeAllFiles(lammpstrj, forceOnCVs, freeEOnCVs,
                              histogramOnCVs, annABP, convABP, tempHist,
                              tempBsp, earlyFreeE)
        self.IO.makeDirAndMoveFiles(self.p["ndims"], self.p["mass"], self.p["temperature"], self.p["frictCoeff"], self.p["total_frame"],\
                                    self.p["abfCheckFlag"], self.p["nnCheckFlag"], __class__.__name__)
示例#4
0
class ABF(object):
    def __init__(self, input_mdp_file):

        self.IO = mdFileIO()
        self.p = self.IO.readParamFile(input_mdp_file)  # p for md parameters
        self.bins = np.linspace(-self.p["half_boxboundary"],
                                self.p["half_boxboundary"],
                                self.p["binNum"] + 1,
                                dtype=np.float64)
        self.colvars_coord = np.linspace(-self.p["half_boxboundary"],
                                         self.p["half_boxboundary"],
                                         self.p["binNum"] + 1,
                                         dtype=np.float64)

        self.mdInitializer   = mdEngine(self.p["nparticle"], self.p["box"], self.p["kb"],\
                                        self.p["time_step"], self.p["temperature"], self.p["ndims"],\
                                        self.p["mass"], self.p["thermoStatFlag"], self.getCurrentForce, self.p["frictCoeff"])

        self.initializeForce = Force(self.p["kb"], self.p["time_step"],
                                     self.p["temperature"], self.p["ndims"],
                                     self.p["mass"], self.p["thermoStatFlag"],
                                     self.p["frictCoeff"])

        # init coord and vel
        self.current_coord = np.zeros((self.p["nparticle"], self.p["ndims"]),
                                      dtype=np.float64)
        self.current_vel = self.mdInitializer.genVelocity()
        # init coord and vel

        if self.p["ndims"] == 1:
            self.colvars_force = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_force_NN = np.zeros(len(self.bins), dtype=np.float64)
            self.colvars_count = np.zeros(len(self.bins), dtype=np.float64)

        if self.p["ndims"] == 2:
            self.colvars_force = np.zeros(
                (self.p["ndims"], len(self.bins), len(self.bins)),
                dtype=np.float64)
            self.colvars_force_NN = np.zeros(
                (self.p["ndims"], len(self.bins), len(self.bins)),
                dtype=np.float64)
            self.colvars_count = np.zeros(
                (self.p["ndims"], len(self.bins), len(self.bins)),
                dtype=np.float64)

    def _forceHistDistrRecord(self, coord_x, coord_y, d):

        if self.p["ndims"] == 1:
            self.colvars_count[getIndices(coord_x, self.bins)] += 1

        if self.p["ndims"] == 2:
            self.colvars_count[d][getIndices(coord_x, self.bins)][getIndices(
                coord_y, self.bins)] += 1

    def _forceDistrRecord(self, coord_x, updated_Fsys, coord_y, d):

        if self.p["ndims"] == 1:
            self.colvars_force[getIndices(coord_x, self.bins)] += updated_Fsys

        if self.p["ndims"] == 2:
            self.colvars_force[d][getIndices(coord_x, self.bins)][getIndices(
                coord_y, self.bins)] += updated_Fsys

    def _inverseGradient(self):
        """ cv == cartesian so return 1"""
        return 1

    def _Jacobian(self):
        """ cv == cartesian -> ln|J| = 0 so return 0"""
        return 0

    def _entropicCorrection(self):
        return self.p["kb"] * self.p["temperature"] * self._Jacobian()

    def _calBiasingForce(self, coord_x, coord_y, d):
        if self.p["ndims"] == 1:
            if self.colvars_count[getIndices(coord_x, self.bins)] == 0:
                return 0
            else:
                return -(
                    (self.colvars_force[getIndices(coord_x, self.bins)] /
                     self.colvars_count[getIndices(coord_x, self.bins)] +
                     self._entropicCorrection()) * self._inverseGradient())

        if self.p["ndims"] == 2:
            if self.colvars_count[d][getIndices(coord_x,
                                                self.bins)][getIndices(
                                                    coord_y, self.bins)] == 0:
                return 0
            else:
                return -((self.colvars_force[d][getIndices(coord_x, self.bins)][getIndices(coord_y, self.bins)] / self.colvars_count[d][getIndices(coord_x, self.bins)][getIndices(coord_y, self.bins)] +\
                        self._entropicCorrection()) * self._inverseGradient())

    def _abfDecorator(func):
        def _wrapper(self, coord_x, d, vel, coord_y):
            Fabf = func(self, coord_x, d, vel, coord_y)
            currentFsys = self.initializeForce.getForce(
                coord_x, d, vel, coord_y)
            self._forceDistrRecord(coord_x, currentFsys, coord_y, d)
            self._forceHistDistrRecord(coord_x, coord_y, d)
            return Fabf + currentFsys

        return _wrapper

    @_abfDecorator
    def getCurrentForce(self, coord_x, d, vel, coord_y):

        if self.p["abfCheckFlag"] == "no" and self.p["nnCheckFlag"] == "no":
            Fabf = 0

        elif self.p["abfCheckFlag"] == "yes" and self.p["nnCheckFlag"] == "no":
            Fabf = self._calBiasingForce(coord_x, coord_y, d)

        elif self.p["abfCheckFlag"] == "yes" and self.p["nnCheckFlag"] == "yes":

            if self.p["init_frame"] < self.p["trainingFreq"]:
                Fabf = self._calBiasingForce(coord_x, coord_y, d)

            else:  # ANN takes over here; reload the previous training model

                tf.reset_default_graph()

                with tf.Session() as sess:
                    Saver = tf.train.import_meta_graph("net" +
                                                       str(self.p["ndims"]) +
                                                       "D" +
                                                       "/netSaver.ckpt.meta")
                    Saver.restore(
                        sess,
                        tf.train.latest_checkpoint("net" +
                                                   str(self.p["ndims"]) +
                                                   "D/"))
                    graph = tf.get_default_graph()
                    #y_estimatedOP = graph.get_operation_by_name("criticalOP")  # get tensor with suffix :0
                    layerOutput = graph.get_tensor_by_name("annOutput:0")

                    if self.p["ndims"] == 1:
                        coord_x = np.array([coord_x])[:, np.newaxis]
                        CV = graph.get_tensor_by_name("colvars:0")
                        Fabf = -sess.run(layerOutput, feed_dict={
                            CV: coord_x
                        }).reshape(self.p["ndims"])[d]

                    if self.p["ndims"] == 2:
                        coord_x = np.array([coord_x])[:, np.newaxis]
                        coord_y = np.array([coord_y])[:, np.newaxis]
                        CV_x = graph.get_tensor_by_name("colvars_x:0")
                        CV_y = graph.get_tensor_by_name("colvars_y:0")
                        Fabf = -sess.run(layerOutput,
                                         feed_dict={
                                             CV_x: coord_x,
                                             CV_y: coord_y
                                         }).reshape(self.p["ndims"])[d]

                tf.reset_default_graph()

        return Fabf

    def _learningProxy(self):
        if self.p["nnCheckFlag"] == "yes":
            if self.p["init_frame"] % self.p["trainingFreq"] == 0 and self.p[
                    "init_frame"] != 0:
                output = trainingANN("loss.dat", "hyperparam.dat",
                                     self.p["ndims"], len(self.bins))

                self.colvars_force = (self.colvars_force / self.colvars_count)
                self.colvars_force[np.isnan(
                    self.colvars_force)] = 0  # 0/0 = nan n/0 = inf
                self.colvars_force = paddingRightMostBin(self.colvars_force)

                if self.p["init_frame"] < self.p["trainingFreq"] * self.p[
                        "switchSteps"]:
                    self.colvars_force_NN = \
                    output.training(self.colvars_coord, self.colvars_force, self.p["earlyLearningRate"], self.p["earlyRegularCoeff"], self.p["earlyEpoch"], self.p["nnOutputFreq"])
                else:
                    self.colvars_force_NN = \
                    output.training(self.colvars_coord, self.colvars_force, self.p["lateLearningRate"], self.p["lateRegularCoeff"], self.p["lateEpoch"], self.p["nnOutputFreq"])

                self.colvars_force = (self.colvars_force * self.colvars_count)

    def mdrun(self):

        init_real_world_time = time.time()

        # PRE-PROCESSING
        lammpstrj = open(
            "m%.1f_T%.3f_gamma%.4f_len_%d_%s_%s.lammpstrj" %
            (self.p["mass"], self.p["temperature"], self.p["frictCoeff"],
             self.p["total_frame"], self.p["abfCheckFlag"],
             self.p["nnCheckFlag"]), "w")
        forceOnCVs = open(
            "Force_m%.1fT%.3f_gamma%.4f_len_%d_%s_%s.dat" %
            (self.p["mass"], self.p["temperature"], self.p["frictCoeff"],
             self.p["total_frame"], self.p["abfCheckFlag"],
             self.p["nnCheckFlag"]), "w")
        histogramOnCVs = open(
            "Hist_m%.1fT%.3f_gamma%.4f_len_%d_%s_%s.dat" %
            (self.p["mass"], self.p["temperature"], self.p["frictCoeff"],
             self.p["total_frame"], self.p["abfCheckFlag"],
             self.p["nnCheckFlag"]), "w")

        withANN = open("instantForceWANN_" + str(self.p["ndims"]) + "D.dat",
                       "a")
        woANN = open("instantForceWOANN_" + str(self.p["ndims"]) + "D.dat",
                     "a")

        # START of the simulation
        self.IO.writeParams(self.p)
        self.IO.lammpsFormatColvarsOutput(self.p["ndims"], self.p["nparticle"],
                                          self.p["half_boxboundary"],
                                          self.p["init_frame"],
                                          self.current_coord, lammpstrj,
                                          self.p["writeFreq"])
        self.IO.printCurrentStatus(self.p["init_frame"], init_real_world_time)

        while self.p["init_frame"] < self.p["total_frame"]:

            self.p["init_frame"] += 1
            self.IO.printCurrentStatus(self.p["init_frame"],
                                       init_real_world_time)
            self.mdInitializer.checkTargetTemperature(self.current_vel,
                                                      self.p["init_frame"],
                                                      self.p["total_frame"])

            if self.p["init_frame"] % self.p["trainingFreq"] == 0 and self.p[
                    "init_frame"] != 0 and self.p[
                        "abfCheckFlag"] == "yes" and self.p[
                            "nnCheckFlag"] == "yes":
                self._learningProxy()
                self.colvars_force = (self.colvars_force / self.colvars_count)
                self.colvars_force[np.isnan(self.colvars_force)] = 0
                self.IO.certainFrequencyOutput(self.colvars_coord,
                                               self.colvars_force_NN,
                                               self.colvars_count,
                                               self.p["init_frame"],
                                               self.p["certainOutFreq"],
                                               withANN)
                self.IO.certainFrequencyOutput(self.colvars_coord,
                                               self.colvars_force,
                                               self.colvars_count,
                                               self.p["init_frame"],
                                               self.p["certainOutFreq"], woANN)
                self.colvars_force = (self.colvars_force * self.colvars_count)

            if self.p["init_frame"] % self.p["certainOutFreq"] == 0 and self.p[
                    "init_frame"] != 0 and self.p["nnCheckFlag"] == "no":
                self.colvars_force = (self.colvars_force / self.colvars_count)
                self.colvars_force[np.isnan(self.colvars_force)] = 0
                self.IO.certainFrequencyOutput(self.colvars_coord,
                                               self.colvars_force,
                                               self.colvars_count,
                                               self.p["init_frame"],
                                               self.p["certainOutFreq"], woANN)
                self.colvars_force = (self.colvars_force * self.colvars_count)

            self.mdInitializer.velocityVerletSimple(self.current_coord,
                                                    self.current_vel)

            self.IO.lammpsFormatColvarsOutput(self.p["ndims"],
                                              self.p["nparticle"],
                                              self.p["half_boxboundary"],
                                              self.p["init_frame"],
                                              self.current_coord, lammpstrj,
                                              self.p["writeFreq"])
        # END of the simulation

        # POST-PROCESSING
        probability = self.colvars_count / (
            np.sum(self.colvars_count) / self.p["ndims"]
        )  # both numerator and denominator should actually be divided by two but this would be cacncelled
        probability = paddingRightMostBin(probability)
        self.IO.propertyOnColvarsOutput(self.bins, probability,
                                        self.colvars_count / 2, histogramOnCVs)

        if self.p["nnCheckFlag"] == "yes":
            self.IO.propertyOnColvarsOutput(self.bins, self.colvars_force_NN,
                                            self.colvars_count, forceOnCVs)

        else:
            self.colvars_force = (self.colvars_force / self.colvars_count)
            self.colvars_force[np.isnan(self.colvars_force)] = 0
            self.colvars_force = paddingRightMostBin(self.colvars_force)
            self.IO.propertyOnColvarsOutput(self.bins, self.colvars_force,
                                            self.colvars_count, forceOnCVs)

        # ndims >= 2 -> plot using matplotlib
        if self.p["ndims"] == 2:
            s = rendering(self.p["ndims"], self.p["half_boxboundary"],
                          self.p["binNum"], self.p["temperature"])
            s.render(
                probability[0],
                name=str(self.p["abfCheckFlag"] + "_" + self.p["nnCheckFlag"] +
                         "_" + "boltzDist" + str(self.p["ndims"]) + "D"))
            if self.p["nnCheckFlag"] == "yes":
                s.render(self.colvars_force_NN[0],
                         name=str(self.p["abfCheckFlag"] + "_" +
                                  self.p["nnCheckFlag"] + "_" + "forcex" +
                                  str(self.p["ndims"]) + "D"))
                s.render(self.colvars_force_NN[1],
                         name=str(self.p["abfCheckFlag"] + "_" +
                                  self.p["nnCheckFlag"] + "_" + "forcey" +
                                  str(self.p["ndims"]) + "D"))
            else:
                s.render(self.colvars_force[0],
                         name=str(self.p["abfCheckFlag"] + "_" +
                                  self.p["nnCheckFlag"] + "_" + "forcex" +
                                  str(self.p["ndims"]) + "D"))
                s.render(self.colvars_force[1],
                         name=str(self.p["abfCheckFlag"] + "_" +
                                  self.p["nnCheckFlag"] + "_" + "forcey" +
                                  str(self.p["ndims"]) + "D"))

        # Close files, mkdir and mv files
        self.IO.closeAllFiles(lammpstrj, forceOnCVs, histogramOnCVs, withANN,
                              woANN)
        self.IO.makeDirAndMoveFiles(self.p["ndims"], self.p["mass"], self.p["temperature"], self.p["frictCoeff"], self.p["total_frame"],\
                                    self.p["abfCheckFlag"], self.p["nnCheckFlag"], __class__.__name__)