Beispiel #1
0
def ConfBisect(snap1, snap2, eis1, eis2, L, dmax=0.002):
    """
	This function takes two thermal snapshots that end in two separate IS,
	and makes a linear interpolation between the positions of the two.
	Through bisection, the point that separates the two basins is found.
	"""
    assert (np.abs(eis1 - eis2) > THRES)
    dstart = 0.1 * dmax
    Natoms = snap1.particles.N
    dist12 = med.PeriodicDistance(snap1.particles.position,
                                  snap2.particles.position,
                                  L).sum() / Natoms  #the box is cubic
    snap12 = LinearConfInterpolation(snap1, snap2, L)
    snapis12, eis12 = Minimize(snap12, verbose=False)

    count = 0
    maxcount = 100
    while dist12 > dstart:
        if np.abs(eis1 -
                  eis12) <= THRES:  #If snap12 belongs to snap1, snap1=snap12
            snap1.particles.position[:] = snap12.particles.position
            eis1 = eis12
            pos1 = np.array(snap1.particles.position[:], dtype=np.float64)
        elif np.abs(eis2 -
                    eis12) <= THRES:  #If snap12 belongs to snap2, snap2=snap12
            snap2.particles.position[:] = snap12.particles.position
            eis2 = eis12

        else:  #If snap12 does not belong to either, we throw a warning and change snap2
            print(
                "ConfBisect: found an intermediate IS while searching the TS")
            snap2.particles.position[:] = snap12.particles.position
            eis2 = eis12

        dist12 = med.PeriodicDistance(snap1.particles.position,
                                      snap2.particles.position,
                                      L).sum() / Natoms
        count += 1
        assert (np.abs(eis1 - eis2) > THRES)
        snap12 = LinearConfInterpolation(snap1, snap2, L)
        snapis12, eis12 = Minimize(snap12, verbose=False)

        if count > maxcount:
            raise SystemExit(
                "ConfBisect ERROR: the interpolation bisection is not converging."
            )
    return snap1, snap2, snap12, eis1, eis2, eis12, dist12
Beispiel #2
0
def ConfBisect(snap1, snap2, eis1, eis2, L, dmax=0.002):
	"""
	This function takes two thermal snapshots that end in two separate IS,
	and makes a linear interpolation between the positions of the two.
	Through bisection, the point that separates the two basins is found.
	#0.002 is about half the typical distance between confs at subsequent time steps w/ dt=0.0025
	"""
	print('···ConfBisect···')
	print('eis1 = ',eis1,'; eis2 = ',eis2)

	if np.abs(eis1-eis2)<args.deltaE: raise ValueError('ConfBisect ERROR: the two starting ISs the same one [abs(eis1-eis2)<args.deltaE]')
	dstart=0.5*dmax
	Natoms=snap1.particles.N
	dist12=med.PeriodicDistance(snap1.particles.position, snap2.particles.position, L).sum()/Natoms #the box is cubic
	snap12=LinearConfInterpolation(snap1, snap2, L)

	eis12,snapis12=Minimize(snap12)
	print('snap1 .particles.position[0] = ',snap1.particles.position[0])
	print('snap2 .particles.position[0] = ',snap2.particles.position[0])
	print('snap12.particles.position[0] = ',snap12.particles.position[0])

	count=0
	maxcount=100
	while dist12>dstart:
		print('eis1 = ',eis1,'; eis2 = ',eis2,'; eis12 = ',eis12)
		if np.abs(eis1-eis12) <= args.deltaE: #If snap12 belongs to snap1, snap1=snap12
			snap1.particles.position[:]=snap12.particles.position
			eis1=eis12
		elif np.abs(eis2-eis12) <= args.deltaE: #If snap12 belongs to snap2, snap2=snap12
			snap2.particles.position[:]=snap12.particles.position
			eis2=eis12
		else: #If snap12 does not belong to either, we print a warning and change snap2
			print("ConfBisect: found an intermediate IS while searching the TS (Eis12=%.14g)"%eis12)
			snap2.particles.position[:]=snap12.particles.position
			eis2=eis12
		dist12=med.PeriodicDistance(snap1.particles.position, snap2.particles.position, L).sum()/Natoms
		print("dist12=",dist12)
		count+=1
		if  np.abs(eis1-eis2)<args.deltaE: raise ValueError('ConfBisect ERROR: the two ISs became the same one [abs(eis1-eis2)<args.deltaE]')
		snap12=LinearConfInterpolation(snap1, snap2, L)
		print('snap12.particles.position[0] = ',snap12.particles.position[0])
		eis12,snapis12=Minimize(snap12)

		if count>maxcount:
			raise RecursionError("ConfBisect ERROR: the interpolation bisection is not converging.")
	return snap1,snap2,snap12,eis1,eis2,eis12,dist12
Beispiel #3
0
def ConfBisect(snap1, snap2, eis1, eis2, L, dmax=0.002):
	'''
	0.002 is about half the typical distance between confs at subsequent time steps w/ dt=0.0025
	'''

	assert(np.abs(eis1-eis2)>deltaE)
	dstart=0.1*dmax
	Natoms=snap_ini.particles.N
	pos1=np.array(snap1.particles.position, dtype=np.float64)
	pos2=np.array(snap2.particles.position, dtype=np.float64)
	dist12=med.PeriodicDistance(pos1,pos2,boxParams[0]).sum()/Natoms #the box is cubic
	print("dist12=",dist12)
	snap12=LinearConfInterpolation(snap1, snap2, L)
	pos12=np.array(snap12.particles.position, dtype=np.float64)
	eis12=Minimize(snap12)

	print(" eis12=",eis12)
	count=0
	maxcount=10
	while dist12>dstart:
		#If snap12 belongs to snap1, snap1=snap12
		if np.abs(eis1-eis12) <= deltaE:
			snap1=snap12
			eis1=eis12
			pos1=np.array(snap1.particles.position, dtype=np.float64)
		#If snap12 belongs to snap2, snap2=snap12
		elif np.abs(eis2-eis12) <= deltaE:
			snap2=snap12
			eis2=eis12
			pos2=np.array(snap2.particles.position, dtype=np.float64)
		#If snap12 does not belong to either, we throw a warning and change snap2
		else:
			print("NonLocalRidge: found an intermediate IS while searching the TS")
			snap2=snap12
			eis2=eis12
		#
		dist12=med.PeriodicDistance(pos1,pos2,boxParams[0]).sum()/Natoms
		print("dist12=",dist12)
		count+=1
		assert(np.abs(eis1-eis2)>deltaE)
		snap12=LinearConfInterpolation(snap1, snap2, L)
		eis12=Minimize(snap12)
		if count>maxcount:
			print("NonLocalRidge ERROR: the interpolation bisection is not converging.")
	return snap1,snap2,snap12,eis1,eis2,eis12,dist12
def MeasureDistances(pivots):
    '''
	Misura le distanze tra i pivot in ascissa curvilinea
	'''
    distances = [0]
    for i in range(1, len(pivots)):
        distances.append(distances[i - 1] +
                         med.PeriodicDistance(pivots[i], pivots[i - 1], L))
    return distances
Beispiel #5
0
def InsertOnePivot(pivots, dmax, L):
    '''
	Create a new list of pivots, inserting an intermediate image between every two pivots at distance larger than dmax
	'''
    newpivots = []
    indices = []
    for i in range(0, len(pivots) - 1):
        newpivots.append(pivots[i])
        if med.PeriodicDistance(pivots[i], pivots[i + 1], L) > dmax:
            indices.append(len(newpivots))
            newpivots.append(
                med.PeriodicIntermPoints(pivots[i], pivots[i + 1], L))
    newpivots.append(pivots[-1])
    return newpivots, indices
Beispiel #6
0
def RedistributePivots(pivots, L):
    '''
	Redistributes the pivots so that they are all at the same distance in the tangent reference.
	'''
    distances = [
        med.PeriodicDistance(pivots[i], pivots[i - 1], L)
        for i in range(1, len(pivots))
    ]
    newpivots = np.copy(pivots)
    meandist = np.mean(distances)
    for i in range(len(distances) - 1):
        if distances[i] >= meandist:
            newpivots[i + 1] = med.PeriodicInterpPoints(
                pivots[i + 1], pivots[i], L, meandist / distances[i])
        else:
            newpivots[i + 1] = med.PeriodicInterpPoints(
                pivots[i + 2], pivots[i + 1], L,
                min(1, (meandist - distances[i]) / distances[i + 1]))
    return newpivots
Beispiel #7
0
def CalculateRidge(snapT1, snapT2, Eis1, Eis2, L):
	''' Calculates energy at the ridge between two snapshots '''
	print("--- Calculate Ridge ---\n- Eis1:",Eis1,' Eis2:',Eis2)

	dmax=0.0001 #0.004 is about the typical distance between confs at subsequent time steps with dt=0.0025
	nsteps=1
	niter=10000
	snapT1.particles.velocity[:]=np.zeros((Natoms, 3))
	snapT2.particles.velocity[:]=np.zeros((Natoms, 3))

	#snapis are not inherent structures, but the gradually approach them
	snapis1,snapis2,snapis12,Eis1,Eis2,Eis12,dist12=ConfBisect(snapT1, snapT2, Eis1, Eis2, L, dmax=dmax)

	print("- Eis1=%.8f;\tEis2= %.8f (after ConfBisect)"%(Eis1,Eis2))

	context1 = hoomd.context.SimulationContext();
	with context1:
		system1 = hoomd.init.read_snapshot(snapis1)
		modeFire1=md.integrate.mode_minimize_fire(dt=dtFIRE, alpha_start=alphaFIRE, ftol=ftolFIRE, Etol=EtolFIRE, wtol=wtolFIRE)
		integrator1 = md.integrate.nve(group=hoomd.group.all())
		analyzerFire1=SetupAnalyzer(logname=None, period='None')
		md.update.zero_momentum(phase=2, period=10)
		pair=pot.LJ(md.nlist.cell(),type="KAshort")

	context2 = hoomd.context.SimulationContext();
	with context2:
		system2 = hoomd.init.read_snapshot(snapis2)
		modeFire2=md.integrate.mode_minimize_fire(dt=dtFIRE, alpha_start=alphaFIRE, ftol=ftolFIRE, Etol=EtolFIRE, wtol=wtolFIRE)
		integrator2 = md.integrate.nve(group=hoomd.group.all())
		analyzerFire2=SetupAnalyzer(logname=None, period='None')
		md.update.zero_momentum(phase=2, period=10)
		pair=pot.LJ(md.nlist.cell(),type="KAshort")

	modeFire1.reset()
	modeFire2.reset()


	for iter in range(niter):
		with context1:
			system1.restore_snapshot(snapis1)
			hoomd.run(nsteps)
			eis1=analyzerFire1.query('potential_energy')
			snapis1=system1.take_snapshot(dtype='double')
		with context2:
			system2.restore_snapshot(snapis2)
			hoomd.run(nsteps)
			eis2=analyzerFire2.query('potential_energy')
			snapis2=system2.take_snapshot(dtype='double')

		dist12=med.PeriodicDistance(snapis1.particles.position, snapis2.particles.position, L).sum()/Natoms

		print("iter: ",iter," dist12=",dist12,"eis1: %.14f"%eis1," eis2: %.14f"%eis2)

		if dist12>dmax:
			'''
			With the linear interpolations the found barrier is occasionally lower than one of the ISs, because of nonlinearities in the path.
			# snapRidge=LinearConfInterpolation(snapis1_old, snapis2_old, L)
			# Eridge=potential.CalculateEnergySlower(snapRidge)
			For this reason, I just take the energy of one of the two confs at the previous step.
			'''
			if eis1>eis2: 
				Eridge=ConsistentRidge(eis1_old,Eis1,Eis2,args.deltaE)
				snapRidge=snapis1_old
			else : 
				Eridge=ConsistentRidge(eis2_old,Eis1,Eis2,args.deltaE)
				snapRidge=snapis2_old
			print("Eridge = ",Eridge)
			break

		snapis1_old=snapis1
		snapis2_old=snapis2
		eis1_old=eis1
		eis2_old=eis2

	if iter==niter-1: sys.exit('CalculateRidge did not converge after '+str(niter)+' steps')
	return Eridge,snapRidge
Beispiel #8
0
def NonLocalRidge(snap1, snap2, eis1,eis2):
	"""Finds the Transition State through the algorithm proposed in Doliwa&Heuer, PRE 67 031506 (2003)"""
	print("Calculate TS now: |e1-e2|=",np.abs(eis1-eis2))
	dmax=0.002 #0.004 is about the typical distance between confs at subsequent time steps w/ dt=0.0025

	snap1,snap2,snap12,eis1,eis2,eis12,dist12=ConfBisect(snap1, snap2, eis1, eis2, np.float64(boxParams[0]),dmax=dmax)



	## Calculation of the gradient

	e1,G1=potential.CalculateGradient(snap1)
	e2,G2=potential.CalculateGradient(snap2)
	Gsq1=np.square(G1).sum()
	Gsq2=np.square(G2).sum()
	Gsq=0.5*(Gsq1+Gsq2) #Questa variabile ha senso solo dopo ConfBisect, che garantisce che le configurazioni siano vicine
	eis1=Minimize(snap1)
	eis2=Minimize(snap2)

	GsqThres=0.02
	niter=0
	maxiter=200
	print("Nonlocal Ridge, caratteristiche configurazione termica:")
	print("e1=",e1)
	print("e2=",e2)
	print("Gsq1=",Gsq1)
	print("Gsq2=",Gsq2)
	print("Struttura inerente:")
	print("eis1=",eis1/Natoms)
	print("eis2=",eis2/Natoms)
	nsteps=25
	while(Gsq>GsqThres):

		snap1=MinimizeFewSteps(snap1, nsteps)
		snap2=MinimizeFewSteps(snap2, nsteps)
		pos1=np.array(snap1.particles.position,dtype=np.float64)
		pos2=np.array(snap2.particles.position,dtype=np.float64)
		dist12=med.PeriodicDistance(pos1,pos2,boxParams[0]).sum()/Natoms #the box is cubic
		# if dist12>dmax:
		snap1,snap2,snap12,eis1,eis2,eis12,dist12=ConfBisect(snap1, snap2, eis1, eis2, np.float64(boxParams[0]), dmax=dmax)

		e1,G1=potential.CalculateGradient(snap1)
		e2,G2=potential.CalculateGradient(snap2)
		e12,G12=potential.CalculateGradient(snap12)
		# eis1=Minimize(snap1)
		# eis2=Minimize(snap2)
		Gsq1=np.square(G1).sum()
		Gsq2=np.square(G2).sum()
		Gsq12=np.square(G12).sum()
		Gsq=0.5*(Gsq1+Gsq2)
		print("e1=",e1,"\te2=",e2)
		print("eis1=",eis1/Natoms,"\teis2=",eis2/Natoms)
		print("Gsq1=",Gsq1,"  Gsq2=",Gsq2,"  Gsq12=",Gsq12,"  Gsq=",Gsq,"\n")
		if np.abs(eis1-eis2)<deltaE:
			print("The two configurations are falling into the same IS. Abort.")
			raise SystemExit

		if niter>maxiter:
			print("IL CAZZO DI ALGORITMO DELLE SELLE DI MERDA NON CONVERGE MANCO SE LO PAGHI")
			raise SystemExit
		niter+=1

	snap1,snap2,snap12,eis1,eis2,eis12,dist12=ConfBisect(snap1, snap2, eis1, eis2, np.float64(boxParams[0]),dmax=dmax)
	eTS=e12
	e12,G12=potential.CalculateGradient(snap12)
	Gsq12=np.square(G12).sum()
	print("Ora bisogna fare una minimizzazione del gradiente quadro, a partire da snap12")
	print("Per la cronaca, l'energia di snap12 e` e12=",e12)
	print("Quella della struttura inerente e` eis12=",eis12)
	print("Il gradiente della configurazione termica e` Gsq12=",Gsq12)
	raise SystemExit
	return eTS
                    dtype=np.float64)

#Make interpolations
delta = 1. / args.npoints
alphas = np.arange(0, 1 + delta, delta)
energies = []
distances = []
for alpha in alphas:
    interpPos = med.PeriodicInterpPoints(pos2, pos1, L, alpha)
    snap.particles.position[:] = interpPos
    system.restore_snapshot(snap)
    hoomd.run(2)
    energy = analyzer.query('potential_energy')
    print(energy)
    energies.append(energy)
    distances.append(med.PeriodicDistance(pos1, interpPos, L))

#Vector of all the particle displacements
disp = med.PeriodicDisplacement(pos1, pos2, L)

#
# FIGURES
#
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import seaborn as sns

#Barrier from the linear interpolation
fig, ax1 = plt.subplots()
ax1.set_xlabel('distance')
ax1.set_ylabel('energy')
Beispiel #10
0
###################
#                 #
# Calculate Ridge #
#                 #
###################
print(
    "-- Find two thermal configurations that are very close to eachother, but end up in two different ISs --"
)
dmax = 0.0004  #0.004 is about the typical distance between confs at subsequent time steps with dt=0.0025
snap1, snap2, snap12, eis1, eis2, eis12, dist12 = ConfBisect(snapT1,
                                                             snapT2,
                                                             Eis1,
                                                             Eis2,
                                                             L,
                                                             dmax=dmax)
dist12 = med.PeriodicDistance(snap1.particles.position,
                              snap2.particles.position, L).sum() / Natoms
print("eis1 = ", eis1, "\teis2 = ", eis2)

print("-- Prepare two parallel minimization contexts --")
snapIS1 = snap1
snapIS2 = snap2
snapIS1.particles.velocity[:] = np.zeros((Natoms, 3))
snapIS2.particles.velocity[:] = np.zeros((Natoms, 3))
simIS1 = hoomd.context.SimulationContext()
simIS2 = hoomd.context.SimulationContext()
with simIS1:
    systemIS1 = hoomd.init.read_snapshot(snapIS1)
    assert (Natoms == len(systemIS1.particles))
    myLjPair = pot.LJ(md.nlist.cell(), type="KAshort")
    analyzerFire1 = SetupAnalyzer(logname=None, period='None')
    modeFire1 = md.integrate.mode_minimize_fire(dt=dtFIRE,