def struct_energy(e0_per_atom, filename): V_unrel = [] V_rel = [] E_unrel = [] E_rel = [] ats = ase.io.read(os.path.dirname(__file__) + "/" + filename, index=':', format='extxyz') for (i, at_orig) in enumerate(ats): at = at_orig.copy() at.set_calculator(model.calculator) # # The commented out bit that follows seems to break CASTEP_file - no minimization runs are set up, apparently because call to relax_atoms_cell doesn't actually trigger a calculate() # unrelaxed_e_per_atom = at.get_potential_energy()/len(at) # print 'at unrelaxed energy per atom', unrelaxed_e_per_atom # E_unrel.append(unrelaxed_e_per_atom-e0_per_atom) # relax fully print "BOB: calling relax_atoms_cell" if os.path.basename(os.path.dirname(model.__file__)) == 'CASTEP_file': at = relax_atoms_cell(at, tol=fmax, traj_file="model-" + model.name + "-RSS-{}-".format(i) + filename + "-relaxed.opt.xyz") else: n_at = len(at) config_minim = UnitCellFilter(at) x = config_minim.get_positions() converged = False for i_minim in range(500): config_minim.set_positions(x) grad_f = -config_minim.get_forces() E = config_minim.get_potential_energy() try: pred_err = predictive_error(config_minim.atoms) except: pred_err = None if isinstance(config_minim, UnitCellFilter): print i, "SD2: {} {} {} {}".format( i_minim, E, np.max(np.abs(grad_f[:n_at])), np.max(np.abs(grad_f[n_at:]))) else: print i, "SD2: {} {} {}".format( i_minim, E, np.max(np.abs(grad_f[:n_at]))) if np.max(np.abs(grad_f[:n_at])) < fmax and np.max( np.abs(grad_f[n_at:])) < fmax: converged = True break if i_minim == 0: alpha = 1.0e-6 else: alpha = np.sum( (x - x_old) * (grad_f - grad_f_old)) / np.sum( (grad_f - grad_f_old)**2) x_old = x.copy() grad_f_old = grad_f.copy() x -= np.abs(alpha) * grad_f print "BOB: done relax_atoms_cell" ase.io.write(sys.stdout, at, format='extxyz') print "BOB: calling get_potential_energy for relaxed" relaxed_e_per_atom = at.get_potential_energy() / len(at) print "BOB: done get_potential_energy for relaxed" print 'at relaxed energy per atom', relaxed_e_per_atom E_rel.append(relaxed_e_per_atom - e0_per_atom) V_rel.append(at.get_volume() / len(at)) # This is a workaround for the problem mentioned above ats = ase.io.read(os.path.dirname(__file__) + "/" + filename, index=':', format='extxyz') for (i, at) in enumerate(ats): at.set_calculator(model.calculator) # relax fully print "BOB: calling get_potential_energy for unrelaxed" unrelaxed_e_per_atom = at.get_potential_energy() / len(at) print "BOB: done get_potential_energy for unrelaxed" print 'at unrelaxed energy per atom', unrelaxed_e_per_atom E_unrel.append(unrelaxed_e_per_atom - e0_per_atom) V_unrel.append(at.get_volume() / len(at)) # end of workaround return (V_unrel, E_unrel, V_rel, E_rel)
model.geom_method = 'tpsd' model.geom_force_tol = tol model.geom_stress_tol = tol model.geom_energy_tol = 1.0e8 model.geom_disp_tol = 1.0e8 print "BOB relax atoms" at = relax_atoms_cell(at, tol=tol) i_minim = -1 converged = True else: config_minim = UnitCellFilter(at) x = config_minim.get_positions() converged = False for i_minim in range(500): config_minim.set_positions(x) grad_f = -config_minim.get_forces() E = config_minim.get_potential_energy() try: pred_err = predictive_error(config_minim.atoms) except: pred_err = None if isinstance(config_minim, UnitCellFilter): print config_i, "SD2: {} {} {} {}".format( i_minim, E, np.max(np.abs(grad_f[:n_at])), np.max(np.abs(grad_f[n_at:]))) else: print config_i, "SD2: {} {} {}".format( i_minim, E, np.max(np.abs(grad_f[:n_at]))) if np.max(np.abs(grad_f[:n_at])) < tol and np.max( np.abs(grad_f[n_at:])) < tol: converged = True
def relax_use_method(xc, method, fmax=0.002, steps=100, clear=False): # allow only up to 100 steps atoms = mater.copy() # same start point! if xc.upper() not in ("PBE", "LDA"): raise ValueError("XC method not known!") if method.upper() not in ("UCF", "ECF", "IT"): raise ValueError("Optimization method not known!") parprint("Running {}-{} for {}-{}".format(xc, method, name, prototype)) calc = GPAW( mode=dict(name="pw", ecut=800), occupations=dict(name="fermi-dirac", width=0.01), basis="dzp", xc=xc.upper(), kpts=dict(gamma=True, density=4.0), # Very rough k-density txt=os.path.join(base_dir, "{}-{}.txt".format(xc.upper(), method.upper()))) atoms.set_calculator(calc) traj_filename = os.path.join( base_dir, "{}-{}.traj".format(xc.upper(), method.upper())) log_filename = os.path.join( base_dir, "{}-{}.log".format(xc.upper(), method.upper())) if clear is True: with open(traj_filename, "w") as _: pass with open(log_filename, "w") as _: pass res_fmax = None if method.upper() == "UCF": # UnitCellFilter ff = UnitCellFilter(atoms) opt = ase.optimize.BFGS(ff, trajectory=traj_filename, logfile=log_filename) opt.run(fmax=fmax, steps=steps) f = ff.get_forces() smax = numpy.sqrt((f**2).sum(axis=1).max()) elif method.upper() == "ECF": # ExpCellFilter ff = ExpCellFilter(atoms) opt = ase.optimize.BFGS(ff, trajectory=traj_filename, logfile=log_filename) opt.run(fmax=fmax, steps=steps) f = ff.get_forces() smax = numpy.sqrt((f**2).sum(axis=1).max()) elif method.upper() == "IT": # Iterative sf = StrainFilter(atoms) opt_strain = ase.optimize.BFGS(sf, trajectory=traj_filename, logfile=log_filename) opt_force = ase.optimize.BFGS(atoms, trajectory=traj_filename, logfile=log_filename) opt_strain.run(fmax=fmax, steps=steps) opt_force.run(fmax=fmax, steps=steps) f = atoms.get_forces() smax = numpy.sqrt((f**2).sum(axis=1).max()) a, b, c, *_ = atoms.get_cell_lengths_and_angles() if "smax" not in dir(): smax = None res_entry = dict(name=name, prototype=prototype, xc=xc.upper(), method=method.upper(), abc=(a, b, c), max_force=smax) return res_entry