def test_struc_from_ase(): from ase import Atoms from ase.calculators.singlepoint import SinglePointCalculator results = { "forces": np.random.randn(20, 3), "energy": np.random.rand(), "stress": np.random.randn(6), } uc = Atoms( ["Pd" for i in range(10)] + ["Ag" for i in range(10)], positions=np.random.rand(20, 3), cell=np.random.rand(3, 3), ) calculator = SinglePointCalculator(uc, **results) uc.set_calculator(calculator) new_struc = Structure.from_ase_atoms(uc) assert np.all(new_struc.species_labels == uc.get_chemical_symbols()) assert np.all(new_struc.positions == uc.get_positions()) assert np.all(new_struc.cell == uc.get_cell()) assert np.all(new_struc.forces == results["forces"]) assert np.all(new_struc.energy == results["energy"]) assert np.all(new_struc.stress == results["stress"])
def restart(self): # Recover atomic configuration: positions, velocities, forces positions, self.nsteps = self.read_frame('positions.xyz', -1) self.atoms.set_positions(positions) self.atoms.set_velocities(self.read_frame('velocities.dat', -1)[0]) self.atoms.calc.results['forces'] = self.read_frame('forces.dat', -1)[0] print('Last frame recovered') # Recover training data set gp_model = self.atoms.calc.gp_model atoms = deepcopy(self.atoms) nat = len(self.atoms.positions) dft_positions = self.read_all_frames('dft_positions.xyz', nat) dft_forces = self.read_all_frames('dft_forces.dat', nat) added_atoms = self.read_all_frames('added_atoms.dat', 1, 1, 'int') for i, frame in enumerate(dft_positions): atoms.set_positions(frame) curr_struc = Structure.from_ase_atoms(atoms) gp_model.update_db(curr_struc, dft_forces[i], added_atoms[i]) gp_model.set_L_alpha() print('GP training set ready') # Recover FLARE calculator gp_model.ky_mat_inv = np.load(self.restart_from + '/ky_mat_inv.npy') gp_model.alpha = np.load(self.restart_from + '/alpha.npy') if self.atoms.calc.use_mapping: for map_3 in self.atoms.calc.mgp_model.maps_3: map_3.load_grid = self.restart_from + '/' self.atoms.calc.build_mgp(skip=False) print('GP and MGP ready') self.l_bound = 10
def otf_run(self, steps): """Perform a number of time steps.""" # initialize gp by a dft calculation if not self.atoms.calc.gp_model.training_data: self.dft_count = 0 self.std_in_bound = False self.target_atom = 0 self.stds = [] dft_forces = self.call_DFT() f = dft_forces # update gp model atom_struc = Structure(np.array(self.atoms.cell), self.atoms.get_atomic_numbers(), self.atoms.positions) self.atoms.calc.gp_model.update_db(atom_struc, dft_forces, custom_range=self.init_atoms) # train calculator self.train() print('mgp model:', self.atoms.calc.mgp_model) if self.md_engine == 'NPT': if not self.initialized: self.initialize() else: if self.have_the_atoms_been_changed(): raise NotImplementedError( "You have modified the atoms since the last timestep.") for i in range(steps): print('step:', i) if self.md_engine == 'NPT': self.step() else: f = self.step(f) self.nsteps += 1 self.stds = self.atoms.get_uncertainties() # figure out if std above the threshold self.call_observers() curr_struc = Structure.from_ase_atoms(self.atoms) curr_struc.stds = self.stds noise = self.atoms.calc.gp_model.hyps[-1] self.std_in_bound, self.target_atoms = is_std_in_bound(\ noise, self.std_tolerance, curr_struc, self.max_atoms_added) #self.is_std_in_bound([]) if not self.std_in_bound: # call dft/eam print('calling dft') dft_forces = self.call_DFT() # update gp print('updating gp') self.update_GP(dft_forces) self.observers[0][0].run_complete()
def test_struc_from_ase(): from ase import Atoms uc = Atoms(['Pd' for i in range(10)] + ['Ag' for i in range(10)], positions=np.random.rand(20, 3), cell=np.random.rand(3, 3)) new_struc = Structure.from_ase_atoms(uc) assert np.all(new_struc.species_labels == uc.get_chemical_symbols()) assert np.all(new_struc.positions == uc.get_positions()) assert np.all(new_struc.cell == uc.get_cell())
def update_GP(self, dft_forces): atom_count = 0 atom_list = [] gp_model = self.atoms.calc.gp_model # build gp structure from atoms atom_struc = Structure.from_ase_atoms(self.atoms) while (not self.std_in_bound and atom_count < np.min( [self.max_atoms_added, len(self.target_atoms)])): target_atom = self.target_atoms[atom_count] # update gp model gp_model.update_db(atom_struc, dft_forces, custom_range=[target_atom]) if gp_model.alpha is None: gp_model.set_L_alpha() else: gp_model.update_L_alpha() # atom_list.append(target_atom) ## force calculation needed before get_uncertainties # forces = self.atoms.calc.get_forces_gp(self.atoms) # self.stds = self.atoms.get_uncertainties() # write added atom to the log file, # refer to ase.optimize.optimize.Dynamics self.observers[0][0].add_atom_info(target_atom, self.stds[target_atom]) #self.is_std_in_bound(atom_list) atom_count += 1 self.train() self.observers[0][0].added_atoms_dat.write('\n') self.observers[0][0].write_wall_time()
def otf_run(self, steps, rescale_temp=[], rescale_steps=[]): """ Use `otf_run` intead of `run` to perform a number of time steps. Args: steps (int): the number of time steps Other Parameters: rescale_temp (list): a list of temepratures that rescale the system rescale_steps (list): a list of step numbers that the temperature rescaling in `rescale_temp` is done Example: # rescale temperature to 500K and 1000K at the 100th and 200th step rescale_temp = [500, 1000] rescale_steps = [100, 200] """ # restart from previous OTF training if self.restart_from is not None: self.restart() f = self.atoms.calc.results['forces'] # initialize gp by a dft calculation if not self.atoms.calc.gp_model.training_data: self.dft_count = 0 self.stds = np.zeros((self.noa, 3)) dft_forces = self.call_DFT() f = dft_forces # update gp model curr_struc = Structure.from_ase_atoms(self.atoms) self.l_bound = get_l_bound(100, curr_struc, self.two_d) print('l_bound:', self.l_bound) self.atoms.calc.gp_model.update_db(curr_struc, dft_forces, custom_range=self.init_atoms) # train calculator for atom in self.init_atoms: # the observers[0][0] is the logger self.observers[0][0].add_atom_info(atom, self.stds[atom]) self.train() self.observers[0][0].write_wall_time() if self.md_engine == 'NPT': if not self.initialized: self.initialize() else: if self.have_the_atoms_been_changed(): raise NotImplementedError( "You have modified the atoms since the last timestep.") step_0 = self.nsteps for i in range(step_0, steps): print('step:', i) self.atoms.calc.results = { } # clear the calculation from last step self.stds = np.zeros((self.noa, 3)) # temperature rescaling if self.nsteps in rescale_steps: temp = rescale_temp[rescale_steps.index(self.nsteps)] curr_velocities = self.atoms.get_velocities() curr_temp = self.atoms.get_temperature() self.atoms.set_velocities(curr_velocities *\ np.sqrt(temp/curr_temp)) if self.md_engine == 'NPT': self.step() else: f = self.step(f) self.nsteps += 1 self.stds = self.atoms.get_uncertainties(self.atoms) # figure out if std above the threshold self.call_observers() curr_struc = Structure.from_ase_atoms(self.atoms) self.l_bound = get_l_bound(self.l_bound, curr_struc, self.two_d) print('l_bound:', self.l_bound) curr_struc.stds = np.copy(self.stds) noise = self.atoms.calc.gp_model.hyps[-1] self.std_in_bound, self.target_atoms = is_std_in_bound(\ noise, self.std_tolerance, curr_struc, self.max_atoms_added) print('std in bound:', self.std_in_bound, self.target_atoms) #self.is_std_in_bound([]) if not self.std_in_bound: # call dft/eam print('calling dft') dft_forces = self.call_DFT() # update gp print('updating gp') self.update_GP(dft_forces) self.observers[0][0].run_complete()