Ejemplo n.º 1
0
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!
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
    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 )
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
    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)
Ejemplo n.º 8
0
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)
Ejemplo n.º 9
0
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 
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
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
Ejemplo n.º 12
0
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!
Ejemplo n.º 13
0
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
Ejemplo n.º 14
0
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