root / ase / optimize / oldqn.py @ 14
Historique | Voir | Annoter | Télécharger (14,44 ko)
| 1 | 1 | tkerber | # Copyright (C) 2003 CAMP
|
|---|---|---|---|
| 2 | 1 | tkerber | # Please see the accompanying LICENSE file for further information.
|
| 3 | 1 | tkerber | |
| 4 | 1 | tkerber | """
|
| 5 | 1 | tkerber | Quasi-Newton algorithm
|
| 6 | 1 | tkerber | """
|
| 7 | 1 | tkerber | |
| 8 | 1 | tkerber | __docformat__ = 'reStructuredText'
|
| 9 | 1 | tkerber | |
| 10 | 1 | tkerber | import numpy as np |
| 11 | 1 | tkerber | import weakref,time,sys |
| 12 | 1 | tkerber | |
| 13 | 1 | tkerber | |
| 14 | 1 | tkerber | def f(lamda,Gbar,b,radius): |
| 15 | 1 | tkerber | b1 = b - lamda |
| 16 | 1 | tkerber | g = radius**2 - np.dot(Gbar/b1, Gbar/b1)
|
| 17 | 1 | tkerber | return g
|
| 18 | 1 | tkerber | |
| 19 | 1 | tkerber | |
| 20 | 1 | tkerber | |
| 21 | 1 | tkerber | def scale_radius_energy(f,r): |
| 22 | 1 | tkerber | scale = 1.0
|
| 23 | 1 | tkerber | # if(r<=0.01):
|
| 24 | 1 | tkerber | # return scale
|
| 25 | 1 | tkerber | |
| 26 | 1 | tkerber | if f<0.01: scale*=1.4 |
| 27 | 1 | tkerber | if f<0.05: scale*=1.4 |
| 28 | 1 | tkerber | if f<0.10: scale*=1.4 |
| 29 | 1 | tkerber | if f<0.40: scale*=1.4 |
| 30 | 1 | tkerber | |
| 31 | 1 | tkerber | if f>0.5: scale *= 1./1.4 |
| 32 | 1 | tkerber | if f>0.7: scale *= 1./1.4 |
| 33 | 1 | tkerber | if f>1.0: scale *= 1./1.4 |
| 34 | 1 | tkerber | |
| 35 | 1 | tkerber | return scale
|
| 36 | 1 | tkerber | |
| 37 | 1 | tkerber | def scale_radius_force(f,r): |
| 38 | 1 | tkerber | scale = 1.0
|
| 39 | 1 | tkerber | # if(r<=0.01):
|
| 40 | 1 | tkerber | # return scale
|
| 41 | 1 | tkerber | g = abs(f -1) |
| 42 | 1 | tkerber | if g<0.01: scale*=1.4 |
| 43 | 1 | tkerber | if g<0.05: scale*=1.4 |
| 44 | 1 | tkerber | if g<0.10: scale*=1.4 |
| 45 | 1 | tkerber | if g<0.40: scale*=1.4 |
| 46 | 1 | tkerber | |
| 47 | 1 | tkerber | if g>0.5: scale *= 1./1.4 |
| 48 | 1 | tkerber | if g>0.7: scale *= 1./1.4 |
| 49 | 1 | tkerber | if g>1.0: scale *= 1./1.4 |
| 50 | 1 | tkerber | |
| 51 | 1 | tkerber | return scale
|
| 52 | 1 | tkerber | |
| 53 | 1 | tkerber | def find_lamda(upperlimit,Gbar,b,radius): |
| 54 | 1 | tkerber | lowerlimit = upperlimit |
| 55 | 1 | tkerber | eps = 1e-12
|
| 56 | 1 | tkerber | step = 0.1
|
| 57 | 1 | tkerber | while f(lowerlimit,Gbar,b,radius) < 0: |
| 58 | 1 | tkerber | lowerlimit -= step |
| 59 | 1 | tkerber | |
| 60 | 1 | tkerber | converged = False
|
| 61 | 1 | tkerber | |
| 62 | 1 | tkerber | while not converged: |
| 63 | 1 | tkerber | |
| 64 | 1 | tkerber | midt = (upperlimit+lowerlimit)/2.
|
| 65 | 1 | tkerber | lamda = midt |
| 66 | 1 | tkerber | fmidt = f(midt,Gbar,b,radius) |
| 67 | 1 | tkerber | fupper = f(upperlimit,Gbar,b,radius) |
| 68 | 1 | tkerber | flower = f(lowerlimit,Gbar,b,radius) |
| 69 | 1 | tkerber | |
| 70 | 1 | tkerber | if fupper*fmidt<0: |
| 71 | 1 | tkerber | lowerlimit = midt |
| 72 | 1 | tkerber | else:
|
| 73 | 1 | tkerber | upperlimit = midt |
| 74 | 1 | tkerber | |
| 75 | 1 | tkerber | if abs(upperlimit-lowerlimit)<1e-6: |
| 76 | 1 | tkerber | converged = True
|
| 77 | 1 | tkerber | |
| 78 | 1 | tkerber | return lamda
|
| 79 | 1 | tkerber | |
| 80 | 1 | tkerber | def get_hessian_inertia(eigenvalues): |
| 81 | 1 | tkerber | # return number of negative modes
|
| 82 | 1 | tkerber | n = 0
|
| 83 | 1 | tkerber | print 'eigenvalues ',eigenvalues[0],eigenvalues[1],eigenvalues[2] |
| 84 | 1 | tkerber | while eigenvalues[n]<0: |
| 85 | 1 | tkerber | n+=1
|
| 86 | 1 | tkerber | return n
|
| 87 | 1 | tkerber | |
| 88 | 1 | tkerber | |
| 89 | 1 | tkerber | from numpy.linalg import eigh, solve |
| 90 | 1 | tkerber | |
| 91 | 1 | tkerber | from ase.optimize.optimize import Optimizer |
| 92 | 1 | tkerber | |
| 93 | 1 | tkerber | |
| 94 | 1 | tkerber | |
| 95 | 1 | tkerber | class GoodOldQuasiNewton(Optimizer): |
| 96 | 1 | tkerber | |
| 97 | 1 | tkerber | def __init__(self, atoms, restart=None, logfile='-', trajectory=None, |
| 98 | 1 | tkerber | fmax=None, converged=None, |
| 99 | 1 | tkerber | hessianupdate='BFGS',hessian=None,forcemin=True, |
| 100 | 1 | tkerber | verbosity=None,maxradius=None, |
| 101 | 1 | tkerber | diagonal=20.,radius=None, |
| 102 | 1 | tkerber | transitionstate = False):
|
| 103 | 1 | tkerber | |
| 104 | 1 | tkerber | Optimizer.__init__(self, atoms, restart, logfile, trajectory)
|
| 105 | 1 | tkerber | |
| 106 | 1 | tkerber | self.eps = 1e-12 |
| 107 | 1 | tkerber | self.hessianupdate = hessianupdate
|
| 108 | 1 | tkerber | self.forcemin = forcemin
|
| 109 | 1 | tkerber | self.verbosity = verbosity
|
| 110 | 1 | tkerber | self.diagonal = diagonal
|
| 111 | 1 | tkerber | |
| 112 | 1 | tkerber | self.atoms = atoms
|
| 113 | 1 | tkerber | |
| 114 | 1 | tkerber | n = len(self.atoms) * 3 |
| 115 | 1 | tkerber | if radius is None: |
| 116 | 1 | tkerber | self.radius = 0.05*np.sqrt(n)/10.0 |
| 117 | 1 | tkerber | else:
|
| 118 | 1 | tkerber | self.radius = radius
|
| 119 | 1 | tkerber | |
| 120 | 1 | tkerber | if maxradius is None: |
| 121 | 1 | tkerber | self.maxradius = 0.5*np.sqrt(n) |
| 122 | 1 | tkerber | else:
|
| 123 | 1 | tkerber | self.maxradius = maxradius
|
| 124 | 1 | tkerber | |
| 125 | 1 | tkerber | # 0.01 < radius < maxradius
|
| 126 | 1 | tkerber | self.radius = max(min( self.radius, self.maxradius ), 0.0001) |
| 127 | 1 | tkerber | |
| 128 | 1 | tkerber | self.transitionstate = transitionstate
|
| 129 | 1 | tkerber | |
| 130 | 1 | tkerber | # check if this is a nudged elastic band calculation
|
| 131 | 1 | tkerber | if hasattr(atoms,'springconstant'): |
| 132 | 1 | tkerber | self.forcemin=False |
| 133 | 1 | tkerber | |
| 134 | 1 | tkerber | self.t0 = time.time()
|
| 135 | 1 | tkerber | |
| 136 | 1 | tkerber | def initialize(self):pass |
| 137 | 1 | tkerber | |
| 138 | 1 | tkerber | def write_log(self,text): |
| 139 | 1 | tkerber | if self.logfile is not None: |
| 140 | 1 | tkerber | self.logfile.write(text + '\n') |
| 141 | 1 | tkerber | self.logfile.flush()
|
| 142 | 1 | tkerber | |
| 143 | 1 | tkerber | def set_max_radius(self, maxradius): |
| 144 | 1 | tkerber | self.maxradius = maxradius
|
| 145 | 1 | tkerber | self.radius = min(self.maxradius, self.radius) |
| 146 | 1 | tkerber | |
| 147 | 1 | tkerber | def set_hessian(self,hessian): |
| 148 | 1 | tkerber | self.hessian = hessian
|
| 149 | 1 | tkerber | |
| 150 | 1 | tkerber | def get_hessian(self): |
| 151 | 1 | tkerber | if not hasattr(self,'hessian'): |
| 152 | 1 | tkerber | self.set_default_hessian()
|
| 153 | 1 | tkerber | return self.hessian |
| 154 | 1 | tkerber | |
| 155 | 1 | tkerber | def set_default_hessian(self): |
| 156 | 1 | tkerber | # set unit matrix
|
| 157 | 1 | tkerber | n = len(self.atoms) * 3 |
| 158 | 1 | tkerber | hessian = np.zeros((n,n)) |
| 159 | 1 | tkerber | for i in range(n): |
| 160 | 1 | tkerber | hessian[i][i] = self.diagonal
|
| 161 | 1 | tkerber | self.set_hessian(hessian)
|
| 162 | 1 | tkerber | |
| 163 | 1 | tkerber | def read_hessian(self,filename): |
| 164 | 1 | tkerber | import cPickle |
| 165 | 1 | tkerber | f = open(filename,'r') |
| 166 | 1 | tkerber | self.set_hessian(cPickle.load(f))
|
| 167 | 1 | tkerber | f.close() |
| 168 | 1 | tkerber | |
| 169 | 1 | tkerber | def write_hessian(self,filename): |
| 170 | 1 | tkerber | import cPickle |
| 171 | 1 | tkerber | f = paropen(filename,'w')
|
| 172 | 1 | tkerber | cPickle.dump(self.get_hessian(),f)
|
| 173 | 1 | tkerber | f.close() |
| 174 | 1 | tkerber | |
| 175 | 1 | tkerber | def write_to_restartfile(self): |
| 176 | 1 | tkerber | import cPickle |
| 177 | 1 | tkerber | f = paropen(self.restartfile,'w') |
| 178 | 1 | tkerber | cPickle.dump((self.oldpos,
|
| 179 | 1 | tkerber | self.oldG,
|
| 180 | 1 | tkerber | self.oldenergy,
|
| 181 | 1 | tkerber | self.radius,
|
| 182 | 1 | tkerber | self.hessian,
|
| 183 | 1 | tkerber | self.energy_estimate),f)
|
| 184 | 1 | tkerber | f.close() |
| 185 | 1 | tkerber | |
| 186 | 1 | tkerber | |
| 187 | 1 | tkerber | |
| 188 | 1 | tkerber | def update_hessian(self,pos,G): |
| 189 | 1 | tkerber | import copy |
| 190 | 1 | tkerber | if hasattr(self,'oldG'): |
| 191 | 1 | tkerber | if self.hessianupdate=='BFGS': |
| 192 | 1 | tkerber | self.update_hessian_bfgs(pos,G)
|
| 193 | 1 | tkerber | elif self.hessianupdate== 'Powell': |
| 194 | 1 | tkerber | self.update_hessian_powell(pos,G)
|
| 195 | 1 | tkerber | else:
|
| 196 | 1 | tkerber | self.update_hessian_bofill(pos,G)
|
| 197 | 1 | tkerber | else:
|
| 198 | 1 | tkerber | if not hasattr(self,'hessian'): |
| 199 | 1 | tkerber | self.set_default_hessian()
|
| 200 | 1 | tkerber | |
| 201 | 1 | tkerber | self.oldpos = copy.copy(pos)
|
| 202 | 1 | tkerber | self.oldG = copy.copy(G)
|
| 203 | 1 | tkerber | |
| 204 | 1 | tkerber | if self.verbosity: |
| 205 | 1 | tkerber | print 'hessian ',self.hessian |
| 206 | 1 | tkerber | |
| 207 | 1 | tkerber | |
| 208 | 1 | tkerber | |
| 209 | 1 | tkerber | def update_hessian_bfgs(self,pos,G): |
| 210 | 1 | tkerber | n = len(self.hessian) |
| 211 | 1 | tkerber | dgrad = G - self.oldG
|
| 212 | 1 | tkerber | dpos = pos - self.oldpos
|
| 213 | 1 | tkerber | absdpos = np.sqrt(np.dot(dpos, dpos)) |
| 214 | 1 | tkerber | dotg = np.dot(dgrad,dpos) |
| 215 | 1 | tkerber | tvec = np.dot(dpos,self.hessian)
|
| 216 | 1 | tkerber | dott = np.dot(dpos,tvec) |
| 217 | 1 | tkerber | if (abs(dott)>self.eps) and (abs(dotg)>self.eps): |
| 218 | 1 | tkerber | for i in range(n): |
| 219 | 1 | tkerber | for j in range(n): |
| 220 | 1 | tkerber | h = dgrad[i]*dgrad[j]/dotg - tvec[i]*tvec[j]/dott |
| 221 | 1 | tkerber | self.hessian[i][j] += h
|
| 222 | 1 | tkerber | |
| 223 | 1 | tkerber | |
| 224 | 1 | tkerber | |
| 225 | 1 | tkerber | def update_hessian_powell(self,pos,G): |
| 226 | 1 | tkerber | n = len(self.hessian) |
| 227 | 1 | tkerber | dgrad = G - self.oldG
|
| 228 | 1 | tkerber | dpos = pos - self.oldpos
|
| 229 | 1 | tkerber | absdpos = np.dot(dpos, dpos) |
| 230 | 1 | tkerber | if absdpos<self.eps: |
| 231 | 1 | tkerber | return
|
| 232 | 1 | tkerber | |
| 233 | 1 | tkerber | dotg = np.dot(dgrad,dpos) |
| 234 | 1 | tkerber | tvec = dgrad-np.dot(dpos,self.hessian)
|
| 235 | 1 | tkerber | tvecdot = np.dot(tvec,tvec) |
| 236 | 1 | tkerber | tvecdpos = np.dot(tvec,dpos) |
| 237 | 1 | tkerber | ddot = tvecdpos/absdpos |
| 238 | 1 | tkerber | |
| 239 | 1 | tkerber | dott = np.dot(dpos,tvec) |
| 240 | 1 | tkerber | if (abs(dott)>self.eps) and (abs(dotg)>self.eps): |
| 241 | 1 | tkerber | for i in range(n): |
| 242 | 1 | tkerber | for j in range(n): |
| 243 | 1 | tkerber | h = tvec[i]*dpos[j] + dpos[i]*tvec[j]-ddot*dpos[i]*dpos[j] |
| 244 | 1 | tkerber | h *= 1./absdpos
|
| 245 | 1 | tkerber | self.hessian[i][j] += h
|
| 246 | 1 | tkerber | |
| 247 | 1 | tkerber | |
| 248 | 1 | tkerber | def update_hessian_bofill(self,pos,G): |
| 249 | 1 | tkerber | print 'update Bofill' |
| 250 | 1 | tkerber | n = len(self.hessian) |
| 251 | 1 | tkerber | dgrad = G - self.oldG
|
| 252 | 1 | tkerber | dpos = pos - self.oldpos
|
| 253 | 1 | tkerber | absdpos = np.dot(dpos, dpos) |
| 254 | 1 | tkerber | if absdpos<self.eps: |
| 255 | 1 | tkerber | return
|
| 256 | 1 | tkerber | dotg = np.dot(dgrad,dpos) |
| 257 | 1 | tkerber | tvec = dgrad-np.dot(dpos,self.hessian)
|
| 258 | 1 | tkerber | tvecdot = np.dot(tvec,tvec) |
| 259 | 1 | tkerber | tvecdpos = np.dot(tvec,dpos) |
| 260 | 1 | tkerber | ddot = tvecdpos/absdpos |
| 261 | 1 | tkerber | |
| 262 | 1 | tkerber | coef1 = 1. - tvecdpos*tvecdpos/(absdpos*tvecdot)
|
| 263 | 1 | tkerber | coef2 = (1. - coef1)*absdpos/tvecdpos
|
| 264 | 1 | tkerber | coef3 = coef1*tvecdpos/absdpos |
| 265 | 1 | tkerber | |
| 266 | 1 | tkerber | dott = np.dot(dpos,tvec) |
| 267 | 1 | tkerber | if (abs(dott)>self.eps) and (abs(dotg)>self.eps): |
| 268 | 1 | tkerber | for i in range(n): |
| 269 | 1 | tkerber | for j in range(n): |
| 270 | 1 | tkerber | h = coef1*(tvec[i]*dpos[j] + dpos[i]*tvec[j])-dpos[i]*dpos[j]*coef3 + coef2*tvec[i]*tvec[j] |
| 271 | 1 | tkerber | h *= 1./absdpos
|
| 272 | 1 | tkerber | self.hessian[i][j] += h
|
| 273 | 1 | tkerber | |
| 274 | 1 | tkerber | |
| 275 | 1 | tkerber | |
| 276 | 1 | tkerber | def step(self, f): |
| 277 | 1 | tkerber | """ Do one QN step
|
| 278 | 1 | tkerber | """
|
| 279 | 1 | tkerber | |
| 280 | 1 | tkerber | pos = self.atoms.get_positions().ravel()
|
| 281 | 1 | tkerber | G = -self.atoms.get_forces().ravel()
|
| 282 | 1 | tkerber | energy = self.atoms.get_potential_energy()
|
| 283 | 1 | tkerber | |
| 284 | 1 | tkerber | |
| 285 | 1 | tkerber | self.write_iteration(energy,G)
|
| 286 | 1 | tkerber | |
| 287 | 1 | tkerber | if hasattr(self,'oldenergy'): |
| 288 | 1 | tkerber | |
| 289 | 1 | tkerber | self.write_log('energies ' + str(energy) + ' ' + str(self.oldenergy)) |
| 290 | 1 | tkerber | |
| 291 | 1 | tkerber | if self.forcemin: |
| 292 | 1 | tkerber | de = 1e-4
|
| 293 | 1 | tkerber | else:
|
| 294 | 1 | tkerber | de = 1e-2
|
| 295 | 1 | tkerber | |
| 296 | 1 | tkerber | if self.transitionstate: |
| 297 | 1 | tkerber | de = 0.2
|
| 298 | 1 | tkerber | |
| 299 | 1 | tkerber | if (energy-self.oldenergy)>de: |
| 300 | 1 | tkerber | self.write_log('reject step') |
| 301 | 1 | tkerber | self.atoms.set_positions(self.oldpos.reshape((-1, 3))) |
| 302 | 1 | tkerber | G = self.oldG
|
| 303 | 1 | tkerber | energy = self.oldenergy
|
| 304 | 1 | tkerber | self.radius *= 0.5 |
| 305 | 1 | tkerber | else:
|
| 306 | 1 | tkerber | self.update_hessian(pos,G)
|
| 307 | 1 | tkerber | de = energy - self.oldenergy
|
| 308 | 1 | tkerber | f = 1.0
|
| 309 | 1 | tkerber | if self.forcemin: |
| 310 | 1 | tkerber | self.write_log("energy change; actual: %f estimated: %f "%(de,self.energy_estimate)) |
| 311 | 1 | tkerber | if abs(self.energy_estimate)>self.eps: |
| 312 | 1 | tkerber | f = abs((de/self.energy_estimate)-1) |
| 313 | 1 | tkerber | self.write_log('Energy prediction factor ' + str(f)) |
| 314 | 1 | tkerber | # fg = self.get_force_prediction(G)
|
| 315 | 1 | tkerber | self.radius *= scale_radius_energy(f,self.radius) |
| 316 | 1 | tkerber | |
| 317 | 1 | tkerber | else:
|
| 318 | 1 | tkerber | self.write_log("energy change; actual: %f "%(de)) |
| 319 | 1 | tkerber | self.radius*=1.5 |
| 320 | 1 | tkerber | |
| 321 | 1 | tkerber | fg = self.get_force_prediction(G)
|
| 322 | 1 | tkerber | self.write_log("Scale factors %f %f "%(scale_radius_energy(f,self.radius), |
| 323 | 1 | tkerber | scale_radius_force(fg,self.radius)))
|
| 324 | 1 | tkerber | |
| 325 | 1 | tkerber | |
| 326 | 1 | tkerber | self.radius = max(min(self.radius,self.maxradius), 0.0001) |
| 327 | 1 | tkerber | else:
|
| 328 | 1 | tkerber | self.update_hessian(pos,G)
|
| 329 | 1 | tkerber | |
| 330 | 1 | tkerber | self.write_log("new radius %f "%(self.radius)) |
| 331 | 1 | tkerber | self.oldenergy = energy
|
| 332 | 1 | tkerber | |
| 333 | 1 | tkerber | b,V = eigh(self.hessian)
|
| 334 | 1 | tkerber | V=V.T.copy() |
| 335 | 1 | tkerber | self.V = V
|
| 336 | 1 | tkerber | |
| 337 | 1 | tkerber | # calculate projection of G onto eigenvectors V
|
| 338 | 1 | tkerber | Gbar = np.dot(G,np.transpose(V)) |
| 339 | 1 | tkerber | |
| 340 | 1 | tkerber | lamdas = self.get_lambdas(b,Gbar)
|
| 341 | 1 | tkerber | |
| 342 | 1 | tkerber | D = -Gbar/(b-lamdas) |
| 343 | 1 | tkerber | n = len(D)
|
| 344 | 1 | tkerber | step = np.zeros((n)) |
| 345 | 1 | tkerber | for i in range(n): |
| 346 | 1 | tkerber | step += D[i]*V[i] |
| 347 | 1 | tkerber | |
| 348 | 1 | tkerber | pos = self.atoms.get_positions().ravel()
|
| 349 | 1 | tkerber | pos += step |
| 350 | 1 | tkerber | |
| 351 | 1 | tkerber | energy_estimate = self.get_energy_estimate(D,Gbar,b)
|
| 352 | 1 | tkerber | self.energy_estimate = energy_estimate
|
| 353 | 1 | tkerber | self.gbar_estimate = self.get_gbar_estimate(D,Gbar,b) |
| 354 | 1 | tkerber | self.old_gbar = Gbar
|
| 355 | 1 | tkerber | |
| 356 | 1 | tkerber | self.atoms.set_positions(pos.reshape((-1, 3))) |
| 357 | 1 | tkerber | |
| 358 | 1 | tkerber | |
| 359 | 1 | tkerber | |
| 360 | 1 | tkerber | |
| 361 | 1 | tkerber | def get_energy_estimate(self,D,Gbar,b): |
| 362 | 1 | tkerber | |
| 363 | 1 | tkerber | de = 0.0
|
| 364 | 1 | tkerber | for n in range(len(D)): |
| 365 | 1 | tkerber | de += D[n]*Gbar[n] + 0.5*D[n]*b[n]*D[n]
|
| 366 | 1 | tkerber | return de
|
| 367 | 1 | tkerber | |
| 368 | 1 | tkerber | def get_gbar_estimate(self,D,Gbar,b): |
| 369 | 1 | tkerber | gbar_est = (D*b) + Gbar |
| 370 | 1 | tkerber | self.write_log('Abs Gbar estimate ' + str(np.dot(gbar_est,gbar_est))) |
| 371 | 1 | tkerber | return gbar_est
|
| 372 | 1 | tkerber | |
| 373 | 1 | tkerber | def get_lambdas(self,b,Gbar): |
| 374 | 1 | tkerber | lamdas = np.zeros((len(b)))
|
| 375 | 1 | tkerber | |
| 376 | 1 | tkerber | D = -Gbar/b |
| 377 | 1 | tkerber | #absD = np.sqrt(np.sum(D**2))
|
| 378 | 1 | tkerber | absD = np.sqrt(np.dot(D, D)) |
| 379 | 1 | tkerber | |
| 380 | 1 | tkerber | eps = 1e-12
|
| 381 | 1 | tkerber | nminus = self.get_hessian_inertia(b)
|
| 382 | 1 | tkerber | |
| 383 | 1 | tkerber | if absD < self.radius: |
| 384 | 1 | tkerber | if not self.transitionstate: |
| 385 | 1 | tkerber | self.write_log('Newton step') |
| 386 | 1 | tkerber | return lamdas
|
| 387 | 1 | tkerber | else:
|
| 388 | 1 | tkerber | if nminus==1: |
| 389 | 1 | tkerber | self.write_log('Newton step') |
| 390 | 1 | tkerber | return lamdas
|
| 391 | 1 | tkerber | else:
|
| 392 | 1 | tkerber | self.write_log("Wrong inertia of Hessian matrix: %2.2f %2.2f "%(b[0],b[1])) |
| 393 | 1 | tkerber | |
| 394 | 1 | tkerber | else:
|
| 395 | 1 | tkerber | self.write_log("Corrected Newton step: abs(D) = %2.2f "%(absD)) |
| 396 | 1 | tkerber | |
| 397 | 1 | tkerber | if not self.transitionstate: |
| 398 | 1 | tkerber | # upper limit
|
| 399 | 1 | tkerber | upperlimit = min(0,b[0])-eps |
| 400 | 1 | tkerber | lowerlimit = upperlimit |
| 401 | 1 | tkerber | lamda = find_lamda(upperlimit,Gbar,b,self.radius)
|
| 402 | 1 | tkerber | lamdas += lamda |
| 403 | 1 | tkerber | else:
|
| 404 | 1 | tkerber | # upperlimit
|
| 405 | 1 | tkerber | upperlimit = min(-b[0],b[1],0)-eps |
| 406 | 1 | tkerber | lamda = find_lamda(upperlimit,Gbar,b,self.radius)
|
| 407 | 1 | tkerber | lamdas += lamda |
| 408 | 1 | tkerber | lamdas[0] -= 2*lamda |
| 409 | 1 | tkerber | |
| 410 | 1 | tkerber | return lamdas
|
| 411 | 1 | tkerber | |
| 412 | 1 | tkerber | |
| 413 | 1 | tkerber | |
| 414 | 1 | tkerber | def print_hessian(self): |
| 415 | 1 | tkerber | hessian = self.get_hessian()
|
| 416 | 1 | tkerber | n = len(hessian)
|
| 417 | 1 | tkerber | for i in range(n): |
| 418 | 1 | tkerber | for j in range(n): |
| 419 | 1 | tkerber | print "%2.4f " %(hessian[i][j]), |
| 420 | 1 | tkerber | print " " |
| 421 | 1 | tkerber | |
| 422 | 1 | tkerber | |
| 423 | 1 | tkerber | |
| 424 | 1 | tkerber | |
| 425 | 1 | tkerber | def get_hessian_inertia(self,eigenvalues): |
| 426 | 1 | tkerber | # return number of negative modes
|
| 427 | 1 | tkerber | self.write_log("eigenvalues %2.2f %2.2f %2.2f "%(eigenvalues[0], |
| 428 | 1 | tkerber | eigenvalues[1],
|
| 429 | 1 | tkerber | eigenvalues[2]))
|
| 430 | 1 | tkerber | n = 0
|
| 431 | 1 | tkerber | while eigenvalues[n]<0: |
| 432 | 1 | tkerber | n+=1
|
| 433 | 1 | tkerber | return n
|
| 434 | 1 | tkerber | |
| 435 | 1 | tkerber | def get_force_prediction(self,G): |
| 436 | 1 | tkerber | # return measure of how well the forces are predicted
|
| 437 | 1 | tkerber | Gbar = np.dot(G,np.transpose(self.V))
|
| 438 | 1 | tkerber | dGbar_actual = Gbar-self.old_gbar
|
| 439 | 1 | tkerber | dGbar_predicted = Gbar-self.gbar_estimate
|
| 440 | 1 | tkerber | |
| 441 | 1 | tkerber | f = np.dot(dGbar_actual,dGbar_predicted)/np.dot(dGbar_actual,dGbar_actual) |
| 442 | 1 | tkerber | self.write_log('Force prediction factor ' + str(f)) |
| 443 | 1 | tkerber | return f
|
| 444 | 1 | tkerber | |
| 445 | 1 | tkerber | def write_iteration(self,energy,G):pass |