def calcVectorHessianVectorProduct2(mol, reactionCoordinate, h, vector1, vector2): ''' According to: v1^T * H(f(x)) * v2 := ( directionalGrad_f(x+h*v2) - directionalGrad_f(x-h*v2) ) / 2 / h with h->0 ''' molLeftCopy = openbabel.OBMol(mol) molRightCopy = openbabel.OBMol(mol) nOfAtoms = mol.NumAtoms() tmp = openbabel.doubleArray_frompointer(mol.GetCoordinates()) coords = [tmp[i] for i in xrange(3 * nOfAtoms)] reactionCoordinateValueLeft = shiftAndCalculateReactionCoordinate( molLeftCopy, nOfAtoms, reactionCoordinate, vector2, -h, coords) # WATCH OUT! reactionCoordinateValueRight = shiftAndCalculateReactionCoordinate( molRightCopy, nOfAtoms, reactionCoordinate, vector2, h, coords) # WATCH OUT! vector1Length = vecLength(vector1) vector2Length = vecLength(vector2) if vector1Length == 0 or vector2Length == 0: return 0 versor1 = multVec(1. / vector1Length, vector1) return vector1Length * (calcDirectionalGrad2( molRightCopy, reactionCoordinate, versor1, h, reactionCoordinateValueRight) - calcDirectionalGrad2( molLeftCopy, reactionCoordinate, versor1, h, reactionCoordinateValueLeft)) / 2 / h # WATCH OUT!
def calcHessian(mol, relevantCoordinates, reactionCoordinate, h): nOfAtoms = mol.NumAtoms() hessian = [[0 for i in xrange(3 * nOfAtoms)] for j in xrange(nOfAtoms * 3)] handleToOpenBabelDoubleArray = openbabel.doubleArray_frompointer( mol.GetCoordinates()) molCopy = openbabel.OBMol(mol) currentReactionCoordinateValue = reactionCoordinate(mol) for i in xrange(len(relevantCoordinates)): coordinateA = relevantCoordinates[i] hessian[coordinateA][ coordinateA] = calcSecondDerivativeInOneCoordinate( molCopy, nOfAtoms, reactionCoordinate, currentReactionCoordinateValue, h, coordinateA, handleToOpenBabelDoubleArray) for j in xrange(i + 1, len(relevantCoordinates)): coordinateB = relevantCoordinates[j] hessian[coordinateA][ coordinateB] = calcSecondDerivativeMixedCoordinates( molCopy, nOfAtoms, reactionCoordinate, h, coordinateA, coordinateB, handleToOpenBabelDoubleArray) hessian[coordinateB][coordinateA] = hessian[coordinateA][ coordinateB] return hessian
def shiftAndCalculateReactionCoordinate(mol,nOfAtoms,reactionCoordinate,vector,h,coords=None): # this function is called many times if coords==None: tmp = openbabel.doubleArray_frompointer(mol.GetCoordinates()) coords = [ tmp[i] for i in xrange(3*nOfAtoms) ] coords = addVec(coords,multVec(h,vector)) mol.SetCoordinates(openbabel.double_array(coords)) return reactionCoordinate(mol)
def calculateHessianDiagonal(self,mol,relevantCoordinates,reactionCoordinate,h): hessian = [ [ 0 for i in xrange(self.nOfAtomsX3) ] for j in xrange(self.nOfAtomsX3) ] currentReactionCoordinateValue = reactionCoordinate(mol) nOfAtoms = mol.NumAtoms() tmp = openbabel.doubleArray_frompointer(mol.GetCoordinates()) for i in relevantCoordinates: hessian[i][i] = calcSecondDerivativeInOneCoordinate(mol,nOfAtoms,reactionCoordinate,currentReactionCoordinateValue,h,i,tmp) self.setNonVelocityAtribute( self.hessian, hessian )
def calcDirectionalGrad2(mol,reactionCoordinate,versor,h,currentReactionCoordinate): tmp = openbabel.doubleArray_frompointer(mol.GetCoordinates()) for i in xrange(len(versor)): tmp[i] -= (h*versor[i]) mol.SetCoordinates(tmp) leftReactionCoordinate = reactionCoordinate(mol) for i in xrange(len(versor)): tmp[i] += (2*h*versor[i]) mol.SetCoordinates(tmp) rightReactionCoordinate = reactionCoordinate(mol) return differenceQuotientForDihedralAngle(leftReactionCoordinate,rightReactionCoordinate,h)
def shiftAndCalculateReactionCoordinate( mol, nOfAtoms, reactionCoordinate, vector, h, coords=None): # this function is called many times if coords == None: tmp = openbabel.doubleArray_frompointer(mol.GetCoordinates()) coords = [tmp[i] for i in xrange(3 * nOfAtoms)] coords = addVec(coords, multVec(h, vector)) mol.SetCoordinates(openbabel.double_array(coords)) return reactionCoordinate(mol)
def calculateHessianDiagonal(self, mol, relevantCoordinates, reactionCoordinate, h): hessian = [[0 for i in xrange(self.nOfAtomsX3)] for j in xrange(self.nOfAtomsX3)] currentReactionCoordinateValue = reactionCoordinate(mol) nOfAtoms = mol.NumAtoms() tmp = openbabel.doubleArray_frompointer(mol.GetCoordinates()) for i in relevantCoordinates: hessian[i][i] = calcSecondDerivativeInOneCoordinate( mol, nOfAtoms, reactionCoordinate, currentReactionCoordinateValue, h, i, tmp) self.setNonVelocityAtribute(self.hessian, hessian)
def calcDirectionalGrad2(mol, reactionCoordinate, versor, h, currentReactionCoordinate): tmp = openbabel.doubleArray_frompointer(mol.GetCoordinates()) for i in xrange(len(versor)): tmp[i] -= (h * versor[i]) mol.SetCoordinates(tmp) leftReactionCoordinate = reactionCoordinate(mol) for i in xrange(len(versor)): tmp[i] += (2 * h * versor[i]) mol.SetCoordinates(tmp) rightReactionCoordinate = reactionCoordinate(mol) return differenceQuotientForDihedralAngle(leftReactionCoordinate, rightReactionCoordinate, h)
def calcHessian(mol,relevantCoordinates,reactionCoordinate,h): nOfAtoms = mol.NumAtoms() hessian = [ [ 0 for i in xrange(3*nOfAtoms) ] for j in xrange(nOfAtoms*3) ] handleToOpenBabelDoubleArray = openbabel.doubleArray_frompointer(mol.GetCoordinates()) molCopy = openbabel.OBMol(mol) currentReactionCoordinateValue = reactionCoordinate(mol) for i in xrange(len(relevantCoordinates)): coordinateA = relevantCoordinates[i] hessian[coordinateA][coordinateA] = calcSecondDerivativeInOneCoordinate(molCopy,nOfAtoms,reactionCoordinate,currentReactionCoordinateValue,h,coordinateA,handleToOpenBabelDoubleArray) for j in xrange(i+1,len(relevantCoordinates)): coordinateB = relevantCoordinates[j] hessian[coordinateA][coordinateB] = calcSecondDerivativeMixedCoordinates(molCopy,nOfAtoms,reactionCoordinate,h,coordinateA,coordinateB,handleToOpenBabelDoubleArray) hessian[coordinateB][coordinateA] = hessian[coordinateA][coordinateB] return hessian
def calcGrad(mol,relevantCoordinates,reactionCoordinate,h): numOfAtomsX3 = 3*mol.NumAtoms() handleToOpenBabelDoubleArray = openbabel.doubleArray_frompointer(mol.GetCoordinates()) molCopy = openbabel.OBMol(mol) grad = numOfAtomsX3 * [ 0.0 ] for position in relevantCoordinates: tmp = handleToOpenBabelDoubleArray[position] handleToOpenBabelDoubleArray[position] -= h molCopy.SetCoordinates(handleToOpenBabelDoubleArray) # WATCH OUT! leftReactionCoordinate = reactionCoordinate(molCopy) handleToOpenBabelDoubleArray[position] += (2*h) molCopy.SetCoordinates(handleToOpenBabelDoubleArray) rightReactionCoordinate = reactionCoordinate(molCopy) grad[position] = differenceQuotientForDihedralAngle(leftReactionCoordinate,rightReactionCoordinate,h) handleToOpenBabelDoubleArray[position] = tmp return grad
def calcGrad(mol, relevantCoordinates, reactionCoordinate, h): numOfAtomsX3 = 3 * mol.NumAtoms() handleToOpenBabelDoubleArray = openbabel.doubleArray_frompointer( mol.GetCoordinates()) molCopy = openbabel.OBMol(mol) grad = numOfAtomsX3 * [0.0] for position in relevantCoordinates: tmp = handleToOpenBabelDoubleArray[position] handleToOpenBabelDoubleArray[position] -= h molCopy.SetCoordinates(handleToOpenBabelDoubleArray) # WATCH OUT! leftReactionCoordinate = reactionCoordinate(molCopy) handleToOpenBabelDoubleArray[position] += (2 * h) molCopy.SetCoordinates(handleToOpenBabelDoubleArray) rightReactionCoordinate = reactionCoordinate(molCopy) grad[position] = differenceQuotientForDihedralAngle( leftReactionCoordinate, rightReactionCoordinate, h) handleToOpenBabelDoubleArray[position] = tmp return grad
def calcVectorHessianVectorProduct2(mol,reactionCoordinate,h,vector1,vector2): ''' According to: v1^T * H(f(x)) * v2 := ( directionalGrad_f(x+h*v2) - directionalGrad_f(x-h*v2) ) / 2 / h with h->0 ''' molLeftCopy = openbabel.OBMol(mol) molRightCopy = openbabel.OBMol(mol) nOfAtoms = mol.NumAtoms() tmp = openbabel.doubleArray_frompointer(mol.GetCoordinates()) coords = [ tmp[i] for i in xrange(3*nOfAtoms) ] reactionCoordinateValueLeft = shiftAndCalculateReactionCoordinate(molLeftCopy,nOfAtoms,reactionCoordinate,vector2,-h,coords) # WATCH OUT! reactionCoordinateValueRight = shiftAndCalculateReactionCoordinate(molRightCopy,nOfAtoms,reactionCoordinate,vector2,h,coords) # WATCH OUT! vector1Length = vecLength(vector1) vector2Length = vecLength(vector2) if vector1Length==0 or vector2Length==0: return 0 versor1 = multVec(1./vector1Length,vector1) return vector1Length * ( calcDirectionalGrad2(molRightCopy,reactionCoordinate,versor1,h,reactionCoordinateValueRight) - calcDirectionalGrad2(molLeftCopy,reactionCoordinate,versor1,h,reactionCoordinateValueLeft) ) / 2 / h # WATCH OUT!
def samplingWithConstantReactionCoordinate(mol, conf, ff, angle): assert mol != None and ff != None whichAtomsForDih = conf["whichAtomsForDih"] if "whichAtomsForAux" in conf: whichAtomsForAux = conf["whichAtomsForAux"] prefix = conf["prefix"] nOfSamples = conf["nOfSamples"] nOfStepsInBetween = conf["nOfStepsInBetween"] twistPeriod = conf["twistPeriod"] nuTimesTimeStep = conf["nuTimesTimeStep"] timeStep = conf["timeStep"] timeStep2 = conf["timeStep2"] binWidth = conf["binWidth"] idleSteps = conf["idleSteps"] random.seed(13) relevantCoordinates = [] for atomNumber in whichAtomsForDih: for i in xrange(3): relevantCoordinates.append(3 * (atomNumber - 1) + i) # for testing purposes # relevantCoordinates = [i for i in xrange(33)] # constants h = 0.0001 # 10^-4 seemed best def reactionCoordinate(x): return calcDih(x, whichAtomsForDih) mol.SetTorsion(whichAtomsForDih[0], whichAtomsForDih[1], whichAtomsForDih[2], whichAtomsForDih[3], angle * math.pi / 180.) nOfAtoms = mol.NumAtoms() tmp = openbabel.doubleArray_frompointer(mol.GetCoordinates()) coords = 3 * nOfAtoms * [0] for i in xrange(3 * nOfAtoms): coords[i] = tmp[i] masses = [0] * 3 * nOfAtoms for i in xrange(nOfAtoms): masses[3 * i] = masses[3 * i + 1] = masses[ 3 * i + 2] = 1000 * mol.GetAtom(i + 1).GetAtomicMass() # data storage and calculation dataCalculator = DataAndCalculations(coords, masses) # data extracted from the simulation will be storred in the following data structures: index = 0 lowestEnergy = 100000000 configurationWithLowestEnergy = None dihedrals = MEMORY_BUFFER_SIZE * [None] energies = MEMORY_BUFFER_SIZE * [None] Zksis = MEMORY_BUFFER_SIZE * [None] mksi_gradU_invMasses_gradKsis = MEMORY_BUFFER_SIZE * [None] dAdKsis = MEMORY_BUFFER_SIZE * [None] #TODO: allProductsMatrices = MEMORY_BUFFER_SIZE * [ None ] ZksiToMinusHalf_ACCUMULATED = 0 mksi_gradU_invMasses_gradKsi_ACCUMULATED = 0 dAdKsi_ACCUMULATED = 0 allProductsMatrices_ACCUMULATED = initProductsMatrices(nOfAtoms) # quality / speed testing: noShiftTimes = [] dihedrals_aux = [] shiftTime = 0 nOfAccepts = 0 # tmp for simulation purposes: coords = [0] * 3 * nOfAtoms convergenceOutput = open( "convOutput_angle=%.2f_timestep=%s_twistPeriod=%d_nOfSamples=%d_binWidth=%s_idleSteps=%d.dat" % (angle, str(timeStep), twistPeriod, nOfSamples, str(binWidth), IDLE_STEPS), "w") convergenceOutput.write( "ZksiToMinusHalf_ACCUMULATED\tdAdKsi-<m_ksi gradU.M^(-1).gradKsi>\tdAdKsi\t\t<m_ksi gradU.M^(-1).gradKsi>\t-<v.grad(m_ksi gradKsi).v>\t-kT<m_ksi div(M^(-1).gradKsi)>\n" ) gatherStatisticsFlag = False start = time.clock() if LARGE_OUTPUT: generalOutputStream = gzip.open( PATH_TO_LARGE_OUTPUT + "generalOutput_prefix=%s_angle=%.2f_timestep=%s_twistPeriod=%d_nOfSamples=%d_binWidth=%s_idleSteps=%d.gz" % (prefix, angle, str(timeStep), twistPeriod, nOfSamples, str(binWidth), idleSteps), "wb") generalOutputStream.write( "dihedral\t\t\tdihedral_aux\t\t\tenergy\t\t\tdAdKsi\t\t\t<...gradU...>\t\t\tZksi\n" ) fullMatricesOutputStreams = {} for key in allProductsMatrices_ACCUMULATED.keys(): fullMatricesOutputStreams[key] = gzip.open( PATH_TO_LARGE_OUTPUT + "matrices_prefix=%s_angle=%.2f_timestep=%s_twistPeriod=%d_nOfSamples=%d_binWidth=%s_idleSteps=%d_interaction=%s.gz" % (prefix, angle, str(timeStep), twistPeriod, nOfSamples, str(binWidth), idleSteps, key), "w") allProductsMatrices = MEMORY_BUFFER_SIZE * [None] for iteration in xrange(nOfSamples * nOfStepsInBetween): if gatherStatisticsFlag == False: dataCalculator.idleKSteps(idleSteps, mol, relevantCoordinates, ff, reactionCoordinate, h, timeStep, timeStep2, nuTimesTimeStep) gatherStatisticsFlag = True else: #gradKsi = calcGrad(mol,reactionCoordinate,h) #dataCalculator.calculateZksi( gradKsi ) #energy = dataCalculator.calculateGradU(ff,mol) this is now in the AndersenIntegrator method # ONE STEP OF SIMULATION: energy = dataCalculator.AndersenIntegrator(mol, relevantCoordinates, ff, h, reactionCoordinate, timeStep, timeStep2, nuTimesTimeStep) if numpy.abs(reactionCoordinate(mol) - angle) > binWidth: print "dihedral = ", reactionCoordinate(mol) mol.SetTorsion(whichAtomsForDih[0], whichAtomsForDih[1], whichAtomsForDih[2], whichAtomsForDih[3], angle * math.pi / 180.) tmp = openbabel.doubleArray_frompointer(mol.GetCoordinates()) for i in xrange(3 * nOfAtoms): coords[i] = tmp[i] dataCalculator.reset(coords) print "shift!!!!" newAngle = reactionCoordinate(mol) print "now it's dihedral = ", newAngle if numpy.abs(newAngle - angle) > binWidth: print "WARNING!!!" obConversion.WriteFile( mol, "ERROR_ANGLE=%.3f_ENERGY=%.5f.mol2" % (angle, energy)) os.exit() noShiftTimes.append(shiftTime) shiftTime = 0 gatherStatisticsFlag = False continue else: shiftTime += 1 # remember lowest energy configuration (for visual verification) if energy < lowestEnergy: lowestEnergy = energy configurationWithLowestEnergy = openbabel.OBMol(mol) # calculate second derivatives of ksi dataCalculator.calculateHessianDiagonal(mol, relevantCoordinates, reactionCoordinate, h) Zksi = dataCalculator.getZksi() gradKsi = dataCalculator.getGradKsi() if Zksi == 0: print gradKsi tmp_mksi_gradU_invMasses_gradKsi = dataCalculator.getMksi_gradU_invMasses_gradKsi( ) # is multiplied by Zksi^(-0.5) in this method tmp_dAdKsi = dataCalculator.getKsiDerivativeOfFreeEnergy( ) # is multiplied by Zksi^(-0.5) in this method if tmp_mksi_gradU_invMasses_gradKsi != None and tmp_dAdKsi != None: mksi_gradU_invMasses_gradKsi_ACCUMULATED += tmp_mksi_gradU_invMasses_gradKsi dAdKsi_ACCUMULATED += tmp_dAdKsi ZksiToMinusHalf = Zksi**(-0.5) ZksiToMinusHalf_ACCUMULATED += ZksiToMinusHalf dAdKsis[index] = tmp_dAdKsi / ZksiToMinusHalf if "whichAtomsForAux" in conf: dihedrals_aux.append(mol.GetTorsion(*whichAtomsForAux)) else: dihedrals_aux.append(-10000) dihedral = reactionCoordinate(mol) energies[index] = energy dihedrals[index] = dihedral Zksis[index] = Zksi mksi_gradU_invMasses_gradKsis[ index] = tmp_mksi_gradU_invMasses_gradKsi / ZksiToMinusHalf productsMatrices = initProductsMatrices(nOfAtoms) variousForces = ff.GetVariousForces() products = parseVariousForces2(variousForces, gradKsi, Zksi, masses) fillOutProductsMatrices(products, productsMatrices) addToAllProductsMatrices( allProductsMatrices_ACCUMULATED, productsMatrices, nOfAtoms, ZksiToMinusHalf ) # it's where productsMatrices are multiplied by ZksiToMinusHalf allProductsMatrices[index] = productsMatrices if numpy.abs(dihedrals[index] - angle) > binWidth: print "gathering WRONG stats for dihedral = ", dihedrals[ -1] sys.exit(1) if energies[-1] != None: if LARGE_OUTPUT: for i in xrange(MEMORY_BUFFER_SIZE): generalOutputStream.write( "%f\t\t\t%f\t\t\t%f\t\t\t%f\t\t\t%f\t\t\t%f\n" % (dihedrals[i], dihedrals_aux[i], energies[i], dAdKsis[i], mksi_gradU_invMasses_gradKsis[i], Zksis[i])) index = 0 dihedrals = MEMORY_BUFFER_SIZE * [None] energies = MEMORY_BUFFER_SIZE * [None] Zksis = MEMORY_BUFFER_SIZE * [None] mksi_gradU_invMasses_gradKsis = MEMORY_BUFFER_SIZE * [None] dAdKsis = MEMORY_BUFFER_SIZE * [None] for i in xrange(MEMORY_BUFFER_SIZE): if LARGE_OUTPUT: for key in fullMatricesOutputStreams.keys(): for row in allProductsMatrices[i][key]: for elementInRow in row: if abs(elementInRow) > 0.000000000000: fullMatricesOutputStreams[ key].write("%f " % elementInRow) else: fullMatricesOutputStreams[ key].write("0 ") fullMatricesOutputStreams[key].write("\n") allProductsMatrices = MEMORY_BUFFER_SIZE * [None] else: index += 1 if numpy.mod(iteration + 1, int(0.001 * nOfStepsInBetween * nOfSamples)) == 0: gradKsi = dataCalculator.getGradKsi() percent = int( 1000.0 * iteration / nOfSamples / nOfStepsInBetween) / 10. elapsed = (time.clock() - start) start = time.clock() outTmp = "\t%.8f\t\t\t%.8f\t\t\t%.8f\t\t%.8f\t\t\t%.8f\t\t\t%.8f\t\t(%s percents, one took %s secs)\n" % ( ZksiToMinusHalf_ACCUMULATED, (dAdKsi_ACCUMULATED - mksi_gradU_invMasses_gradKsi_ACCUMULATED) / ZksiToMinusHalf_ACCUMULATED, dAdKsi_ACCUMULATED / ZksiToMinusHalf_ACCUMULATED, mksi_gradU_invMasses_gradKsi_ACCUMULATED / ZksiToMinusHalf_ACCUMULATED, 0, 0, str(percent), str(elapsed)) convergenceOutput.write(outTmp) print outTmp # SETTING NEW COORDINATES: #mol.SetCoordinates( openbabel.double_array(nextCoords) ) now in the AndersenIntegrator # CHECKING THE H-N-C-C DIHEDRAL ANGLE: if "whichAtomsForAux" in conf and numpy.mod( iteration + 1, twistPeriod) == 0: oldAngle = mol.GetTorsion(*whichAtomsForAux) newAngle = random.random() * 359.999 - 179.999 mol.SetTorsion(whichAtomsForAux[3], whichAtomsForAux[2], whichAtomsForAux[1], whichAtomsForAux[0], newAngle * math.pi / 180.) ff.Setup(mol) newEnergy = ff.Energy() if newEnergy <= energy or math.exp( (energy - newEnergy) / BOLTZMANN_CONSTANT / TEMPERATURE) > random.random(): tmp = openbabel.doubleArray_frompointer( mol.GetCoordinates()) coords = 3 * nOfAtoms * [0] for i in xrange(3 * nOfAtoms): coords[i] = tmp[i] dataCalculator.reset(coords) nOfAccepts += 1 gatherStatisticsFlag = False else: mol.SetTorsion(whichAtomsForAux[3], whichAtomsForAux[2], whichAtomsForAux[1], whichAtomsForAux[0], oldAngle * math.pi / 180.) if LARGE_OUTPUT: for i in xrange(index): generalOutputStream.write( "%f\t\t\t%f\t\t\t%f\t\t\t%f\t\t\t%f\t\t\t%f\n" % (dihedrals[i], dihedrals_aux[i], energies[i], dAdKsis[i], mksi_gradU_invMasses_gradKsis[i], Zksis[i])) generalOutputStream.close() for key in fullMatricesOutputStreams.keys(): for i in xrange(index): for row in allProductsMatrices[i][key]: for elementInRow in row: if abs(elementInRow) > 0.00000000000: fullMatricesOutputStreams[key].write("%f " % elementInRow) else: fullMatricesOutputStreams[key].write("0 ") fullMatricesOutputStreams[key].write("\n") fullMatricesOutputStreams[key].close() check_ACCUMULATED = 0 for key in allProductsMatrices_ACCUMULATED.keys(): for i in xrange(nOfAtoms): for j in xrange(nOfAtoms): allProductsMatrices_ACCUMULATED[key][i][ j] /= ZksiToMinusHalf_ACCUMULATED check_ACCUMULATED += allProductsMatrices_ACCUMULATED[key][i][j] fileNames = glob.glob("./lowestEnergyConfigurations/%s*ANGLE=%.3f*" % (conf["prefix"], angle)) if len(fileNames) > 1: print "what?" elif len(fileNames) == 1: lowestEnergySoFar = float( fileNames[0].split("ENERGY=")[1].split(".mol2")[0]) if lowestEnergySoFar > lowestEnergy: obConversion.WriteFile( configurationWithLowestEnergy, "./lowestEnergyConfigurations/%s_ANGLE=%.3f_ENERGY=%.5f.mol2" % (conf["prefix"], angle, lowestEnergy)) os.remove(fileNames[0]) elif len(fileNames) == 0: obConversion.WriteFile( configurationWithLowestEnergy, "./lowestEnergyConfigurations/%s_ANGLE=%.3f_ENERGY=%.5f.mol2" % (conf["prefix"], angle, lowestEnergy)) print print "The following two quantities should be approximately equal:" print "check_ACCUMULATED = \t\t\t\t", check_ACCUMULATED / 2 print "mksi_gradU_invMasses_gradKsi_ACCUMULATED = \t", mksi_gradU_invMasses_gradKsi_ACCUMULATED / ZksiToMinusHalf_ACCUMULATED print print "Probability of acceptance in the Monte Carlo shifts keeping the right dihedral angle: " print "P(acc) = ", float( nOfAccepts) / nOfSamples / nOfStepsInBetween * twistPeriod print "With a mean shift time of ", int(numpy.mean(noShiftTimes)) convergenceOutput.close() return allProductsMatrices_ACCUMULATED, noShiftTimes, ZksiToMinusHalf_ACCUMULATED
def samplingWithConstantReactionCoordinate(mol,conf,ff,angle): assert mol != None and ff != None whichAtomsForDih = conf["whichAtomsForDih"] if "whichAtomsForAux" in conf: whichAtomsForAux = conf["whichAtomsForAux"] prefix = conf["prefix"] nOfSamples = conf["nOfSamples"] nOfStepsInBetween = conf["nOfStepsInBetween"] twistPeriod = conf["twistPeriod"] nuTimesTimeStep = conf["nuTimesTimeStep"] timeStep = conf["timeStep"] timeStep2 = conf["timeStep2"] binWidth = conf["binWidth"] idleSteps = conf["idleSteps"] random.seed(13) relevantCoordinates = [] for atomNumber in whichAtomsForDih: for i in xrange(3): relevantCoordinates.append(3*(atomNumber-1)+i) # for testing purposes # relevantCoordinates = [i for i in xrange(33)] # constants h = 0.0001 # 10^-4 seemed best def reactionCoordinate(x): return calcDih(x,whichAtomsForDih) mol.SetTorsion(whichAtomsForDih[0],whichAtomsForDih[1],whichAtomsForDih[2],whichAtomsForDih[3], angle*math.pi/180.) nOfAtoms = mol.NumAtoms() tmp = openbabel.doubleArray_frompointer(mol.GetCoordinates()) coords = 3*nOfAtoms*[0] for i in xrange(3*nOfAtoms): coords[i] = tmp[i] masses = [ 0 ] * 3*nOfAtoms for i in xrange(nOfAtoms): masses[3*i] = masses[3*i+1] = masses[3*i+2] = 1000 * mol.GetAtom(i+1).GetAtomicMass() # data storage and calculation dataCalculator = DataAndCalculations(coords,masses) # data extracted from the simulation will be storred in the following data structures: index = 0 lowestEnergy = 100000000 configurationWithLowestEnergy = None dihedrals = MEMORY_BUFFER_SIZE * [ None ] energies = MEMORY_BUFFER_SIZE * [ None ] Zksis = MEMORY_BUFFER_SIZE * [ None ] mksi_gradU_invMasses_gradKsis = MEMORY_BUFFER_SIZE * [ None ] dAdKsis = MEMORY_BUFFER_SIZE * [ None ] #TODO: allProductsMatrices = MEMORY_BUFFER_SIZE * [ None ] ZksiToMinusHalf_ACCUMULATED = 0 mksi_gradU_invMasses_gradKsi_ACCUMULATED = 0 dAdKsi_ACCUMULATED = 0 allProductsMatrices_ACCUMULATED = initProductsMatrices(nOfAtoms) # quality / speed testing: noShiftTimes = [] dihedrals_aux = [] shiftTime = 0 nOfAccepts = 0 # tmp for simulation purposes: coords = [ 0 ] * 3*nOfAtoms convergenceOutput = open("convOutput_angle=%.2f_timestep=%s_twistPeriod=%d_nOfSamples=%d_binWidth=%s_idleSteps=%d.dat" % (angle,str(timeStep),twistPeriod,nOfSamples,str(binWidth),IDLE_STEPS),"w") convergenceOutput.write( "ZksiToMinusHalf_ACCUMULATED\tdAdKsi-<m_ksi gradU.M^(-1).gradKsi>\tdAdKsi\t\t<m_ksi gradU.M^(-1).gradKsi>\t-<v.grad(m_ksi gradKsi).v>\t-kT<m_ksi div(M^(-1).gradKsi)>\n" ) gatherStatisticsFlag = False start = time.clock() if LARGE_OUTPUT: generalOutputStream = gzip.open(PATH_TO_LARGE_OUTPUT+"generalOutput_prefix=%s_angle=%.2f_timestep=%s_twistPeriod=%d_nOfSamples=%d_binWidth=%s_idleSteps=%d.gz" % (prefix,angle,str(timeStep),twistPeriod,nOfSamples,str(binWidth),idleSteps),"wb") generalOutputStream.write("dihedral\t\t\tdihedral_aux\t\t\tenergy\t\t\tdAdKsi\t\t\t<...gradU...>\t\t\tZksi\n") fullMatricesOutputStreams = {} for key in allProductsMatrices_ACCUMULATED.keys(): fullMatricesOutputStreams[key] = gzip.open(PATH_TO_LARGE_OUTPUT+"matrices_prefix=%s_angle=%.2f_timestep=%s_twistPeriod=%d_nOfSamples=%d_binWidth=%s_idleSteps=%d_interaction=%s.gz" % (prefix,angle,str(timeStep),twistPeriod,nOfSamples,str(binWidth),idleSteps,key),"w") allProductsMatrices = MEMORY_BUFFER_SIZE * [ None ] for iteration in xrange(nOfSamples*nOfStepsInBetween): if gatherStatisticsFlag==False: dataCalculator.idleKSteps(idleSteps,mol,relevantCoordinates,ff,reactionCoordinate,h,timeStep,timeStep2,nuTimesTimeStep) gatherStatisticsFlag = True else: #gradKsi = calcGrad(mol,reactionCoordinate,h) #dataCalculator.calculateZksi( gradKsi ) #energy = dataCalculator.calculateGradU(ff,mol) this is now in the AndersenIntegrator method # ONE STEP OF SIMULATION: energy = dataCalculator.AndersenIntegrator(mol,relevantCoordinates,ff,h,reactionCoordinate,timeStep,timeStep2,nuTimesTimeStep) if numpy.abs(reactionCoordinate(mol)-angle)>binWidth: print "dihedral = ",reactionCoordinate(mol) mol.SetTorsion(whichAtomsForDih[0],whichAtomsForDih[1],whichAtomsForDih[2],whichAtomsForDih[3],angle*math.pi/180.) tmp = openbabel.doubleArray_frompointer(mol.GetCoordinates()) for i in xrange(3*nOfAtoms): coords[i] = tmp[i] dataCalculator.reset( coords ) print "shift!!!!" newAngle = reactionCoordinate(mol) print "now it's dihedral = ",newAngle if numpy.abs(newAngle-angle)>binWidth: print "WARNING!!!" obConversion.WriteFile(mol,"ERROR_ANGLE=%.3f_ENERGY=%.5f.mol2" % (angle,energy)) os.exit() noShiftTimes.append(shiftTime) shiftTime = 0 gatherStatisticsFlag = False continue else: shiftTime += 1 # remember lowest energy configuration (for visual verification) if energy<lowestEnergy: lowestEnergy = energy configurationWithLowestEnergy = openbabel.OBMol(mol) # calculate second derivatives of ksi dataCalculator.calculateHessianDiagonal(mol,relevantCoordinates,reactionCoordinate,h) Zksi = dataCalculator.getZksi() gradKsi = dataCalculator.getGradKsi() if Zksi==0: print gradKsi tmp_mksi_gradU_invMasses_gradKsi = dataCalculator.getMksi_gradU_invMasses_gradKsi() # is multiplied by Zksi^(-0.5) in this method tmp_dAdKsi = dataCalculator.getKsiDerivativeOfFreeEnergy() # is multiplied by Zksi^(-0.5) in this method if tmp_mksi_gradU_invMasses_gradKsi!=None and tmp_dAdKsi!=None: mksi_gradU_invMasses_gradKsi_ACCUMULATED += tmp_mksi_gradU_invMasses_gradKsi dAdKsi_ACCUMULATED += tmp_dAdKsi ZksiToMinusHalf = Zksi**(-0.5) ZksiToMinusHalf_ACCUMULATED += ZksiToMinusHalf dAdKsis[index] = tmp_dAdKsi / ZksiToMinusHalf if "whichAtomsForAux" in conf: dihedrals_aux.append( mol.GetTorsion(*whichAtomsForAux) ) else: dihedrals_aux.append( -10000 ) dihedral = reactionCoordinate(mol) energies[index] = energy dihedrals[index] = dihedral Zksis[index] = Zksi mksi_gradU_invMasses_gradKsis[index] = tmp_mksi_gradU_invMasses_gradKsi / ZksiToMinusHalf productsMatrices = initProductsMatrices(nOfAtoms) variousForces = ff.GetVariousForces() products = parseVariousForces2(variousForces,gradKsi,Zksi,masses) fillOutProductsMatrices(products,productsMatrices) addToAllProductsMatrices(allProductsMatrices_ACCUMULATED,productsMatrices,nOfAtoms,ZksiToMinusHalf) # it's where productsMatrices are multiplied by ZksiToMinusHalf allProductsMatrices[index] = productsMatrices if numpy.abs(dihedrals[index]-angle)>binWidth: print "gathering WRONG stats for dihedral = ",dihedrals[-1] sys.exit(1) if energies[-1] != None: if LARGE_OUTPUT: for i in xrange(MEMORY_BUFFER_SIZE): generalOutputStream.write( "%f\t\t\t%f\t\t\t%f\t\t\t%f\t\t\t%f\t\t\t%f\n" % (dihedrals[i], dihedrals_aux[i], energies[i], dAdKsis[i], mksi_gradU_invMasses_gradKsis[i], Zksis[i]) ) index = 0 dihedrals = MEMORY_BUFFER_SIZE * [ None ] energies = MEMORY_BUFFER_SIZE * [ None ] Zksis = MEMORY_BUFFER_SIZE * [ None ] mksi_gradU_invMasses_gradKsis = MEMORY_BUFFER_SIZE * [ None ] dAdKsis = MEMORY_BUFFER_SIZE * [ None ] for i in xrange(MEMORY_BUFFER_SIZE): if LARGE_OUTPUT: for key in fullMatricesOutputStreams.keys(): for row in allProductsMatrices[i][key]: for elementInRow in row: if abs(elementInRow)>0.000000000000: fullMatricesOutputStreams[key].write( "%f " % elementInRow ) else: fullMatricesOutputStreams[key].write( "0 " ) fullMatricesOutputStreams[key].write( "\n" ) allProductsMatrices = MEMORY_BUFFER_SIZE * [ None ] else: index += 1 if numpy.mod(iteration+1,int(0.001*nOfStepsInBetween*nOfSamples))==0: gradKsi = dataCalculator.getGradKsi() percent = int(1000.0*iteration/nOfSamples/nOfStepsInBetween)/10. elapsed = (time.clock() - start) start = time.clock() outTmp = "\t%.8f\t\t\t%.8f\t\t\t%.8f\t\t%.8f\t\t\t%.8f\t\t\t%.8f\t\t(%s percents, one took %s secs)\n" % (ZksiToMinusHalf_ACCUMULATED,(dAdKsi_ACCUMULATED-mksi_gradU_invMasses_gradKsi_ACCUMULATED)/ZksiToMinusHalf_ACCUMULATED,dAdKsi_ACCUMULATED/ZksiToMinusHalf_ACCUMULATED,mksi_gradU_invMasses_gradKsi_ACCUMULATED/ZksiToMinusHalf_ACCUMULATED,0,0, str(percent),str(elapsed)) convergenceOutput.write( outTmp ) print outTmp # SETTING NEW COORDINATES: #mol.SetCoordinates( openbabel.double_array(nextCoords) ) now in the AndersenIntegrator # CHECKING THE H-N-C-C DIHEDRAL ANGLE: if "whichAtomsForAux" in conf and numpy.mod(iteration+1,twistPeriod)==0: oldAngle = mol.GetTorsion(*whichAtomsForAux) newAngle = random.random()*359.999-179.999 mol.SetTorsion(whichAtomsForAux[3],whichAtomsForAux[2],whichAtomsForAux[1],whichAtomsForAux[0],newAngle*math.pi/180.) ff.Setup(mol) newEnergy = ff.Energy() if newEnergy <= energy or math.exp((energy-newEnergy)/BOLTZMANN_CONSTANT/TEMPERATURE) > random.random(): tmp = openbabel.doubleArray_frompointer(mol.GetCoordinates()) coords = 3*nOfAtoms*[0] for i in xrange(3*nOfAtoms): coords[i] = tmp[i] dataCalculator.reset( coords ) nOfAccepts += 1 gatherStatisticsFlag = False else: mol.SetTorsion(whichAtomsForAux[3],whichAtomsForAux[2],whichAtomsForAux[1],whichAtomsForAux[0],oldAngle*math.pi/180.) if LARGE_OUTPUT: for i in xrange(index): generalOutputStream.write( "%f\t\t\t%f\t\t\t%f\t\t\t%f\t\t\t%f\t\t\t%f\n" % (dihedrals[i],dihedrals_aux[i],energies[i],dAdKsis[i],mksi_gradU_invMasses_gradKsis[i],Zksis[i]) ) generalOutputStream.close() for key in fullMatricesOutputStreams.keys(): for i in xrange(index): for row in allProductsMatrices[i][key]: for elementInRow in row: if abs(elementInRow)>0.00000000000: fullMatricesOutputStreams[key].write( "%f " % elementInRow ) else: fullMatricesOutputStreams[key].write( "0 " ) fullMatricesOutputStreams[key].write( "\n" ) fullMatricesOutputStreams[key].close() check_ACCUMULATED = 0 for key in allProductsMatrices_ACCUMULATED.keys(): for i in xrange(nOfAtoms): for j in xrange(nOfAtoms): allProductsMatrices_ACCUMULATED[key][i][j] /= ZksiToMinusHalf_ACCUMULATED check_ACCUMULATED += allProductsMatrices_ACCUMULATED[key][i][j] fileNames = glob.glob("./lowestEnergyConfigurations/%s*ANGLE=%.3f*" % (conf["prefix"],angle) ) if len(fileNames)>1: print "what?" elif len(fileNames)==1: lowestEnergySoFar = float(fileNames[0].split("ENERGY=")[1].split(".mol2")[0]) if lowestEnergySoFar>lowestEnergy: obConversion.WriteFile(configurationWithLowestEnergy,"./lowestEnergyConfigurations/%s_ANGLE=%.3f_ENERGY=%.5f.mol2" % (conf["prefix"],angle,lowestEnergy)) os.remove(fileNames[0]) elif len(fileNames)==0: obConversion.WriteFile(configurationWithLowestEnergy,"./lowestEnergyConfigurations/%s_ANGLE=%.3f_ENERGY=%.5f.mol2" % (conf["prefix"],angle,lowestEnergy)) print print "The following two quantities should be approximately equal:" print "check_ACCUMULATED = \t\t\t\t",check_ACCUMULATED/2 print "mksi_gradU_invMasses_gradKsi_ACCUMULATED = \t",mksi_gradU_invMasses_gradKsi_ACCUMULATED/ZksiToMinusHalf_ACCUMULATED print print "Probability of acceptance in the Monte Carlo shifts keeping the right dihedral angle: " print "P(acc) = ", float(nOfAccepts) / nOfSamples / nOfStepsInBetween * twistPeriod print "With a mean shift time of ",int(numpy.mean(noShiftTimes)) convergenceOutput.close() return allProductsMatrices_ACCUMULATED, noShiftTimes, ZksiToMinusHalf_ACCUMULATED