def __init__(self, atoms, timestep, temperature, taut=0.5e3 * units.fs, pressure=1.01325, taup=1e3 * units.fs, compressibility=4.57e-5, fixcm=True, trajectory=None, logfile=None, loginterval=1, append_trajectory=False): NVTBerendsen.__init__(self, atoms, timestep, temperature, taut, fixcm, trajectory, logfile, loginterval, append_trajectory=append_trajectory) self.taup = taup self.pressure = pressure self.compressibility = compressibility
def step(self, f): """ move one timestep forward using Berenden NPT molecular dynamics.""" NVTBerendsen.scale_velocities(self) self.scale_positions_and_cell() #one step velocity verlet atoms = self.atoms p = self.atoms.get_momenta() p += 0.5 * self.dt * f if self.fixcm: # calculate the center of mass # momentum and subtract it psum = p.sum(axis=0) / float(len(p)) p = p - psum self.atoms.set_positions(self.atoms.get_positions() + self.dt * p / self.atoms.get_masses()[:, np.newaxis]) # We need to store the momenta on the atoms before calculating # the forces, as in a parallel Asap calculation atoms may # migrate during force calculations, and the momenta need to # migrate along with the atoms. For the same reason, we # cannot use self.masses in the line above. self.atoms.set_momenta(p) f = self.atoms.get_forces() atoms.set_momenta(self.atoms.get_momenta() + 0.5 * self.dt * f) return f
def step(self, f): """ move one timestep forward using Berenden NPT molecular dynamics.""" NVTBerendsen.scale_velocities(self) self.scale_positions_and_cell() #one step velocity verlet atoms = self.atoms p = self.atoms.get_momenta() p += 0.5 * self.dt * f if self.fixcm: # calculate the center of mass # momentum and subtract it psum = p.sum(axis=0) / float(len(p)) p = p - psum self.atoms.set_positions( self.atoms.get_positions() + self.dt * p / self.atoms.get_masses()[:, np.newaxis]) # We need to store the momenta on the atoms before calculating # the forces, as in a parallel Asap calculation atoms may # migrate during force calculations, and the momenta need to # migrate along with the atoms. For the same reason, we # cannot use self.masses in the line above. self.atoms.set_momenta(p) f = self.atoms.get_forces() atoms.set_momenta(self.atoms.get_momenta() + 0.5 * self.dt * f) return f
def __init__(self, atoms, timestep, temperature, taut, fixcm=True, trajectory=None, **kwargs): NVTBerendsen.__init__(self, atoms, timestep, temperature, taut, fixcm, trajectory) OTF.__init__(self, **kwargs) self.md_engine = 'NVTBerendsen'
def __init__(self, atoms, timestep, temperature, taut=0.5e3 * units.fs, pressure=1.01325, taup=1e3 * units.fs, compressibility=4.57e-5, fixcm=True, trajectory=None, logfile=None, loginterval=1): NVTBerendsen.__init__(self, atoms, timestep, temperature, taut, fixcm, trajectory, logfile, loginterval) self.taup = taup self.pressure = pressure self.compressibility = compressibility
def generate_data(count, filename='cmd.traj'): """Generates test or training data with a simple MD simulation.""" if os.path.exists(filename): return traj = io.Trajectory(filename, 'w') atoms = io.read('2.xyz') atoms.set_calculator(Amp.load('sio2.amp')) atoms.get_potential_energy() traj.write(atoms) mb(atoms, 300. * units.kB) # dyn = vv(atoms, dt=1. * units.fs, logfile='cmd.log') dyn = NVTB(atoms, timestep=0.5 * units.fs, temperature=300, taut=2.0 * units.fs, logfile='cmd.log') for step in range(count - 1): dyn.run(1) traj.write(atoms)
def set_initial_velocities(self, distribution, energy): distribution(self.atoms, energy) try: os.remove(self.traj) except: pass try: os.remove(self._log) except: pass NVTBerendsen.__init__(self, atoms=self.atoms, timestep=self.dt, trajectory=self.traj, loginterval=1, logfile=self._log, temperature=self.target_temperature, taut=self.tau, append_trajectory=False) self.update_properties()
def serve_md(nuclear_charges, coordinates, calculator=None, temp=None): """ """ if calculator is None: parameters = {} parameters["offset"] = -97084.83100465109 parameters["sigma"] = 10.0 alphas = np.load(FILENAME_ALPHAS) X = np.load(FILENAME_REPRESENTATIONS) Q = np.load(FILENAME_CHARGES, allow_pickle=True) alphas = np.array(alphas, order="F") X = np.array(X, order="F") calculator = QMLCalculator(parameters, X, Q, alphas) # SET MOLECULE molecule = ase.Atoms(nuclear_charges, coordinates) molecule.set_calculator(calculator) # SET ASE MD # Set the momenta corresponding to T=300K MaxwellBoltzmannDistribution(molecule, 200 * units.kB) time = 0.5 if temp is None: # We want to run MD with constant energy using the VelocityVerlet algorithm. dyn = VelocityVerlet(molecule, time * units.fs) # 1 fs time step. else: dyn = NVTBerendsen(molecule, time*units.fs, temp, time*units.fs, fixcm=False) # SET AND SERVE NARUPA MD imd = ASEImdServer(dyn) while True: imd.run(10) print("") dump_xyz(molecule, tmpdir + "snapshot.xyz") return
def md_run( parent_dataset, dft_calculator, starting_image, temp, dt, count, label, ensemble="NVE", ): slab = starting_image.copy() slab.set_calculator(AMPOnlineCalc(parent_dataset, dft_calculator, 3)) # MaxwellBoltzmannDistribution(slab, temp * units.kB) if ensemble == "nvtberendsen": dyn = NVTBerendsen(slab, dt * ase.units.fs, temp, taut=300 * ase.units.fs) traj = ase.io.Trajectory(label + ".traj", "w", slab) dyn.attach(traj.write, interval=1) dyn.run(count - 1)
# Parameters for the Morse potential for Cu D = 0.3429 r0 = 2.866 alpha = 1.3588 atoms = read('hexagonal_lattice.xyz') atoms.set_calculator(MorsePotential(D=D, alpha=alpha, r0=r0)) vel = np.zeros((len(atoms), 3)) # initialize velocities with uniform random numbers between [-0.005, 0.005] # gives random initial velocity vel[:, 0] = (np.random.rand(len(atoms)) - 0.5) * 1e-2 vel[:, 1] = (np.random.rand(len(atoms)) - 0.5) * 1e-2 atoms.set_velocities(vel) open('berendsen.log', 'w').close() dyn = NVTBerendsen(atoms, timestep=1 * units.fs, temperature=600, taut=100 * units.fs, logfile='berendsen.log', trajectory='berendsen.traj') # Note that the temperature in NVTBerendsen is given in K # taut = relaxtation time dyn.run(1000) write('berendsen.xyz', read('berendsen.traj@:'))
from ase.units import fs from run_opt import read_incar, write_contcar, get_ele_dict import os, sys calc = GAP(rcut=6.0) nsw, pstress, tebeg, potim, _ = read_incar() my_atoms = read('POSCAR', format='vasp') my_atoms.set_calculator(calc) """ for NVT """ #print(tebeg,'tebeg') dyn = NVTBerendsen(my_atoms, timestep=potim * fs, temperature=tebeg, taut=0.5 * 1000 * fs, trajectory='ase.traj') dyn.attach(MDLogger(dyn, my_atoms, 'OUTCAR', header=True, stress=True, pstress=pstress, peratom=False, mode="w"), interval=1) dyn.run(steps=nsw) atoms_lat = my_atoms.cell atoms_pos = my_atoms.positions
def __init__(self, atoms, timestep, temperature=None, *, temperature_K=None, pressure=None, pressure_au=None, taut=0.5e3 * units.fs, taup=1e3 * units.fs, compressibility=None, compressibility_au=None, fixcm=True, trajectory=None, logfile=None, loginterval=1, append_trajectory=False): """Berendsen (constant N, P, T) molecular dynamics. This dynamics scale the velocities and volumes to maintain a constant pressure and temperature. The shape of the simulation cell is not altered, if that is desired use Inhomogenous_NPTBerendsen. Parameters: atoms: Atoms object The list of atoms. timestep: float The time step in ASE time units. temperature: float The desired temperature, in Kelvin. temperature_K: float Alias for ``temperature``. pressure: float (deprecated) The desired pressure, in bar (1 bar = 1e5 Pa). Deprecated, use ``pressure_au`` instead. pressure: float The desired pressure, in atomic units (eV/Å^3). taut: float Time constant for Berendsen temperature coupling in ASE time units. Default: 0.5 ps. taup: float Time constant for Berendsen pressure coupling. Default: 1 ps. compressibility: float (deprecated) The compressibility of the material, in bar-1. Deprecated, use ``compressibility_au`` instead. compressibility_au: float The compressibility of the material, in atomic units (Å^3/eV). fixcm: bool (optional) If True, the position and momentum of the center of mass is kept unperturbed. Default: True. trajectory: Trajectory object or str (optional) Attach trajectory object. If *trajectory* is a string a Trajectory will be constructed. Use *None* for no trajectory. logfile: file object or str (optional) If *logfile* is a string, a file with that name will be opened. Use '-' for stdout. loginterval: int (optional) Only write a log line for every *loginterval* time steps. Default: 1 append_trajectory: boolean (optional) Defaults to False, which causes the trajectory file to be overwriten each time the dynamics is restarted from scratch. If True, the new structures are appended to the trajectory file instead. """ NVTBerendsen.__init__(self, atoms, timestep, temperature=temperature, temperature_K=temperature_K, taut=taut, fixcm=fixcm, trajectory=trajectory, logfile=logfile, loginterval=loginterval, append_trajectory=append_trajectory) self.taup = taup self.pressure = self._process_pressure(pressure, pressure_au) if compressibility is not None and compressibility_au is not None: raise TypeError( "Do not give both 'compressibility' and 'compressibility_au'") if compressibility is not None: # Specified in bar, convert to atomic units warnings.warn(FutureWarning( "Specify the compressibility in atomic units.")) self.set_compressibility( compressibility_au=compressibility / (1e5 * units.Pascal)) else: self.set_compressibility(compressibility_au=compressibility_au)
if atom.position[i] > cell[i,i]-self.margin: atom.momentum[i] = -abs(atom.momentum[i]) if __name__ == '__main__': # test from ase.cluster.cubic import FaceCenteredCubic from ase.calculators.emt import EMT from ase.md.nvtberendsen import NVTBerendsen from ase.io.trajectory import Trajectory from ase.md.velocitydistribution import MaxwellBoltzmannDistribution, Stationary, ZeroRotation from ase.units import fs, kB atoms = FaceCenteredCubic( 'Pt', [(1, 0, 0), (1, 1, 0), (1, 1, 1)], [2, 3, 1], 4.09) atoms.center(vacuum=5) atoms.set_calculator( EMT() ) T = 8000 # K -- try to vaporize MaxwellBoltzmannDistribution(atoms, kB*T) Stationary(atoms) ZeroRotation(atoms) #dyn = NVTBerendsen(atoms, 1*fs, T, 500*fs, logfile='-') dyn = NVTBerendsen(atoms, 1*fs, T, 500*fs, logfile='-') traj = Trajectory('borders_test.traj', 'w', atoms) dyn.attach(traj.write, interval=10) fr = Freeze(atoms) #fr = Mirror(atoms) dyn.attach( fr, interval=20 ) dyn.run(5000) traj.close()
def ribs(params, voidcount, voidrad, frame_count=1000): calc = IdealBrittleSolid(rc=params.rc, k=params.k, a=params.a, beta=params.beta) x_dimer = np.linspace(params.a - (params.rc - params.a), params.a + 1.1 * (params.rc - params.a), 51) dimers = [ Atoms('Si2', [(0, 0, 0), (x, 0, 0)], cell=[10., 10., 10.], pbc=True) for x in x_dimer ] calc.set_reference_crystal(dimers[0]) e_dimer = [] f_dimer = [] f_num = [] for d in dimers: d.set_calculator(calc) e_dimer.append(d.get_potential_energy()) f_dimer.append(d.get_forces()) f_num.append(calc.calculate_numerical_forces(d)) e_dimer = np.array(e_dimer) f_dimer = np.array(f_dimer) f_num = np.array(f_num) assert abs(f_dimer - f_num).max() < 0.1 #! crystal is created here, the length and height can be modified here as well #! edit 3N changed to different values to test crystal = triangular_lattice_slab(params.a, params.lm * params.N, params.N) calc.set_reference_crystal(crystal) crystal.set_calculator(calc) e0 = crystal.get_potential_energy() l = crystal.cell[0, 0] h = crystal.cell[1, 1] print('l=', l, 'h=', h) # compute surface (Griffith) energy b = crystal.copy() b.set_calculator(calc) shift = calc.parameters['rc'] * 2 y = crystal.positions[:, 1] b.positions[y > h / 2, 1] += shift b.cell[1, 1] += shift e1 = b.get_potential_energy() E_G = (e1 - e0) / l print('Griffith energy', E_G) # compute Griffith strain eps = 0.0 # initial strain is zero eps_max = 2 / np.sqrt(3) * (params.rc - params.a) * np.sqrt( params.N - 1) / h # Griffith strain assuming harmonic energy deps = eps_max / 100. # strain increment e_over_l = 0.0 # initial energy per unit length is zero energy = [] strain = [] while e_over_l < E_G: c = crystal.copy() c.set_calculator(calc) c.positions[:, 1] *= (1.0 + eps) c.cell[1, 1] *= (1.0 + eps) e_over_l = c.get_potential_energy() / l energy.append(e_over_l) strain.append(eps) eps += deps energy = np.array(energy) eps_of_e = interp1d(energy, strain, kind='linear') eps_G = eps_of_e(E_G) print('Griffith strain', eps_G) c = crystal.copy() c.info['E_G'] = E_G c.info['eps_G'] = eps_G # open up the cell along x and y by introducing some vaccum orig_cell_width = c.cell[0, 0] orig_cell_height = c.cell[1, 1] c.center(params.vacuum, axis=0) c.center(params.vacuum, axis=1) # centre the slab on the origin c.positions[:, 0] -= c.positions[:, 0].mean() c.positions[:, 1] -= c.positions[:, 1].mean() c.info['cell_origin'] = [-c.cell[0, 0] / 2, -c.cell[1, 1] / 2, 0.0] ase.io.write('crack_1.xyz', c, format='extxyz') width = (c.positions[:, 0].max() - c.positions[:, 0].min()) height = (c.positions[:, 1].max() - c.positions[:, 1].min()) c.info['OrigHeight'] = height print(( 'Made slab with %d atoms, original width and height: %.1f x %.1f A^2' % (len(c), width, height))) top = c.positions[:, 1].max() bottom = c.positions[:, 1].min() left = c.positions[:, 0].min() right = c.positions[:, 0].max() crack_seed_length = 0.2 * width strain_ramp_length = 8.0 * params.a # make this bigger until crack looks nicer delta_strain = params.strain_rate * params.dt # fix top and bottom rows, and setup Stokes damping mask # initial use constant strain set_constraints(c, params.a) # apply initial displacment field c.positions[:, 1] += thin_strip_displacement_y( c.positions[:, 0], c.positions[:, 1], params.delta * eps_G, left + crack_seed_length, left + crack_seed_length + strain_ramp_length) print('Applied initial load: delta=%.2f strain=%.4f' % (params.delta, params.delta * eps_G)) ase.io.write('crack_2.xyz', c, format='extxyz') c.set_calculator(calc) cl, cs, cr = calc.get_wave_speeds(c) print("rayleigh speed = %f" % cr) # relax initial structure # opt = FIRE(c) # opt.run(fmax=1e-3) ase.io.write('crack_3.xyz', c, format='extxyz') #length and height of the slab is defined here L = params.N * params.lm H = params.N * 2 #Atomic Void Simulations #😵------------------------------------------------------------------------------ #the following lines of code were written to convert 1D positions into a 2D array #so as to make manipulation of slab easier if True: #void parameters are defined here. #around a max of [0.3--1.7] recommended y_offset = 0.1 #y offset is a fraction of distance from the end of the slab x_offset = 0.4 rad = voidrad #this reference code is for 160x40 slab #in steps of 40 i.e. the height, create a list upto the length of slab #row0 = range(0,6400,40) row0 = range(0, len(c), H) #the 2D array will be held in slab slab = [] for col in range(H): row = [] for r in row0: i = col + r row.append(c.positions[i]) slab.append(row) slab = np.array(slab) #all items in the array reversed, needed because the salb is built from bottom left up #in other words, reflected in x axis slab = slab[::-1] # print(slab[0]) # slab[modifiers.mask(h=H,w=L, center=[int(L*x_offset),int((H - 1)*y_offset)], radius=rad)] = 0 #multiple voids if need be if True: for i in range(voidcount): y_offset = rand.uniform(0.1, 0.9) x_offset = rand.uniform(0.3, 0.95) slab[modifiers.mask( h=H, w=L, center=[int(L * x_offset), int((H - 1) * y_offset)], radius=rad)] = 0 #reversed the slab back again here slab = slab[::-1] # # this is a useful text-array representation of the slab, for debugging purposes # mtext = open('masktest.txt','w') # for row in slab: # mtext.write(str(row).replace("\n",",")+"\n") # mtext.close slab_1d = [] for col in range(L): for row in range(H): slab_1d.append(slab[row, col]) slab_1d = np.array(slab_1d) todel = [] for i in range(len(c)): if slab_1d[i][2] == 0: todel.append(i) print(todel) del c[todel] # return #End of Void Simulation #------------------------------------------------------------------------------- #Grain Boundary Simulations #------------------------------------------------------------------------------- if False: hi = 2 #------------------------------------------------------------------------------- #! replaced velcityVerlet with Lagevin to add temperature parameter if params.v_verlet: dyn = VelocityVerlet(c, params.dt * units.fs, logfile=None) # set_initial_velocities(dyn.atoms) else: print("Using NVT!") # mbd(c, 20 * units.kB, force_temp = True) # dyn = Langevin(c,params.dt*units.fs,params.T*units.kB, 5) dyn = NVTBerendsen(c, params.dt * units.fs, params.T, taut=0.5 * 1000 * units.fs) #dyn.atoms.rattle(1e-3) # non-deterministic simulations - adjust to suit #!simulation outputs numbered, avoids deleting exisiting results iterFile = open("simIteration.txt", 'r+') iteration = int(iterFile.readlines()[0]) + 1 if params.overwrite_output: iteration -= 1 iterFile.seek(0, 0) iterFile.write(str(iteration)) iterFile.close() dir = "./.simout/void/sim_" + str(iteration) + "_" + str( params.keep_test).lower() + "_" + params.desc + "/" cf.createFolder(dir) #!Saving parameter values for each iteration of the simulation logFile = open(dir + "params_log.txt", 'w') for p, value in params.compose_params().iteritems(): logFile.write(p + " ==> " + str(value) + "\n") logFile.close crack_pos = [] if params.keep_test: traj = NetCDFTrajectory(dir + 'traj' + str(iteration) + '.nc', 'w', c) dyn.attach(traj.write, 10, dyn.atoms, arrays=['stokes', 'momenta']) # #! isolating crack tip_x for saving # crack_tip_file2 = open(dir+'tip_x.txt','w') # crack_tip_file2.close() tip_x_file = open(dir + 'tip_x.txt', 'a') console_output = open(dir + 'console_output.txt', 'a') coord_file = open(dir + 'coordinates.csv', 'a') coordinates = [] distances = [] dyn.attach(find_crack_tip, 10, dyn.atoms, tipxfile=tip_x_file, cout=console_output, coord=coordinates, d=distances, dt=params.dt * 10, store=True, results=crack_pos) # run for 2000 time steps to reach steady state at initial load # for i in range(10): # dyn.run(250) # if extend_strip(dyn.atoms, params.a, params.N, params.M, params.vacuum): # set_constraints(dyn.atoms, params.a) # start decreasing strain #set_constraints(dyn.atoms, params.a, delta_strain=delta_strain) # strain_atoms = ConstantStrainRate(dyn.atoms.info['OrigHeight'], # delta_strain) # dyn.attach(strain_atoms.apply_strain, 1, dyn. atoms ) # for i in range(50): # dyn.run(100) # if extend_strip(dyn.atoms, params.a, params.N, params.M, params.vacuum): # set_constraints(dyn.atoms, params.a) # #cleardel dyn.observers[-1] # stop increasing the strain # for i in range(1000): # dyn.run(100) # if extend_strip(dyn.atoms, params.a, params.N, params.M, params.vacuum): # set_constraints(dyn.atoms, params.a) dyn.run(int(1 * frame_count) * 10 + 10) # print("\n\n\n\n\n -----Adding Temperature------\n\n\n\n\n") # # mbd(c, 2*params.T * units.kB, force_temp = True) # dyn.set_temperature(params.T*units.kB) # dyn.run(int(0.5*frame_count)*10+10) for c in coordinates: coord_file.write(str(c[0]) + ',' + str(c[1]) + '\n') coord_file.close() if params.keep_test: traj.close() tip_x_file.close() console_output.close()
si.set_calculator(calc) # geometry optimization si = optimize(si, box=True) print('equlirum cell para: ', si.get_cell()[0][0]) print('equlirum energy: ', si.get_potential_energy()) print('equlirum stress', -si.get_stress() / units.GPa) # Build the 2*2*2 supercell atoms = si * 2 atoms.set_calculator(calc) print(atoms) # NVT MD simulation dyn = NVTBerendsen(atoms, p.time_step * units.fs, p.temperature, taut=p.taut * units.fs) MaxwellBoltzmannDistribution(atoms, p.temperature * units.kB) dyn.attach(MDLogger(dyn, atoms, 'md.log', header=True, stress=False, mode="w"), interval=p.save_interval) traj = Trajectory('md.traj', 'w', atoms) dyn.attach(traj.write, interval=p.save_interval) dyn.run(p.run_step)