def test_dsygv_dgelsd(self): a = Diamond('C', size=[4,4,4]) b = a.copy() b.positions += (np.random.random(b.positions.shape)-0.5)*0.1 i, j = neighbour_list("ij", b, 1.85) dr_now = mic(b.positions[i] - b.positions[j], b.cell) dr_old = mic(a.positions[i] - a.positions[j], a.cell) dgrad1 = get_delta_plus_epsilon_dgesv(len(b), i, dr_now, dr_old) dgrad2 = get_delta_plus_epsilon(len(b), i, dr_now, dr_old) self.assertArrayAlmostEqual(dgrad1, dgrad2)
def get_D_square_min(atoms_now, atoms_old, i_now, j_now, delta_plus_epsilon=None): """ Calculate the D^2_min norm of Falk and Langer """ nat = len(atoms_now) assert len(atoms_now) == len(atoms_old) pos_now = atoms_now.positions pos_old = atoms_old.positions # Compute current and old distance vectors. Note that current distance # vectors cannot be taken from the neighbor calculation, because neighbors # are calculated from the sheared cell while these distance need to come # from the unsheared cell. Taking the distance from the unsheared cell # make periodic boundary conditions (and flipping of cell) a lot easier. dr_now = mic(pos_now[i_now] - pos_now[j_now], atoms_now.cell) dr_old = mic(pos_old[i_now] - pos_old[j_now], atoms_old.cell) # Sanity check: Shape needs to be identical! assert dr_now.shape == dr_old.shape if delta_plus_epsilon is None: # Get minimum strain tensor delta_plus_epsilon = get_delta_plus_epsilon(nat, i_now, dr_now, dr_old) # Spread epsilon out for each neighbor index delta_plus_epsilon_n = delta_plus_epsilon[i_now] # Compute D^2_min (residual of the least squares fit) residual_n = np.sum((dr_now - np.sum( delta_plus_epsilon_n.reshape(-1, 3, 3) * dr_old.reshape(-1, 1, 3), axis=2))**2, axis=1) # For each atom, sum over all neighbors residual = np.bincount(i_now, weights=residual_n) return delta_plus_epsilon, residual
def _fill_shifts_upto(self, i): # Iterate up to frame i the full trajectory first and generate a list # of displacement vectors. while len(self.shifts) <= i: j = len(self.shifts) a0 = self.traj[j - 1] a1 = self.traj[j] s0 = a0.get_scaled_positions() % 1.0 s1 = a1.get_scaled_positions() % 1.0 sdisps = mic(s1 - s0, np.eye(3), pbc=a0.pbc) self.shifts += [self.shifts[-1] + sdisps.mean(axis=0)]
def _fill_shifts_upto(self, i): # Iterate up to frame i the full trajectory first and generate a list # of displacement vectors. while len(self.shifts) <= i: j = len(self.shifts) a0 = self.traj[j-1] a1 = self.traj[j] s0 = a0.get_scaled_positions()%1.0 s1 = a1.get_scaled_positions()%1.0 sdisps = mic(s1-s0, np.eye(3), pbc=a0.pbc) self.shifts += [self.shifts[-1]+sdisps.mean(axis=0)]
def get_D_square_min(atoms_now, atoms_old, i_now, j_now, delta_plus_epsilon=None): """ Calculate the D^2_min norm of Falk and Langer """ nat = len(atoms_now) assert len(atoms_now) == len(atoms_old) pos_now = atoms_now.positions pos_old = atoms_old.positions # Compute current and old distance vectors. Note that current distance # vectors cannot be taken from the neighbor calculation, because neighbors # are calculated from the sheared cell while these distance need to come # from the unsheared cell. Taking the distance from the unsheared cell # make periodic boundary conditions (and flipping of cell) a lot easier. dr_now = mic(pos_now[i_now] - pos_now[j_now], atoms_now.cell) dr_old = mic(pos_old[i_now] - pos_old[j_now], atoms_old.cell) # Sanity check: Shape needs to be identical! assert dr_now.shape == dr_old.shape if delta_plus_epsilon is None: # Get minimum strain tensor delta_plus_epsilon = get_delta_plus_epsilon(nat, i_now, dr_now, dr_old) # Spread epsilon out for each neighbor index delta_plus_epsilon_n = delta_plus_epsilon[i_now] # Compute D^2_min (residual of the least squares fit) residual_n = np.sum( ( dr_now- np.sum(delta_plus_epsilon_n.reshape(-1,3,3)*dr_old.reshape(-1,1,3), axis=2) )**2, axis=1) # For each atom, sum over all neighbors residual = np.bincount(i_now, weights=residual_n) return delta_plus_epsilon, residual
def test_neighbour_list(self): a = io.read('aC.cfg') j, dr, i, abs_dr = neighbour_list("jDid", a, 1.85) self.assertTrue((np.bincount(i) == np.bincount(j)).all()) r = a.get_positions() dr_direct = mic(r[j] - r[i], a.cell) abs_dr_from_dr = np.sqrt(np.sum(dr * dr, axis=1)) abs_dr_direct = np.sqrt(np.sum(dr_direct * dr_direct, axis=1)) self.assertTrue(np.all(np.abs(abs_dr - abs_dr_from_dr) < 1e-12)) self.assertTrue(np.all(np.abs(abs_dr - abs_dr_direct) < 1e-12)) self.assertTrue(np.all(np.abs(dr - dr_direct) < 1e-12))
def test_neighbour_list(self): a = io.read('aC.cfg') j, dr, i, abs_dr = neighbour_list("jDid", a, 1.85) self.assertTrue((np.bincount(i) == np.bincount(j)).all()) r = a.get_positions() dr_direct = mic(r[j]-r[i], a.cell) abs_dr_from_dr = np.sqrt(np.sum(dr*dr, axis=1)) abs_dr_direct = np.sqrt(np.sum(dr_direct*dr_direct, axis=1)) self.assertTrue(np.all(np.abs(abs_dr-abs_dr_from_dr) < 1e-12)) self.assertTrue(np.all(np.abs(abs_dr-abs_dr_direct) < 1e-12)) self.assertTrue(np.all(np.abs(dr-dr_direct) < 1e-12))
def test_neighbour_list(self): for pbc in [True, False, [True, False, True]]: a = io.read('aC.cfg') a.set_pbc(pbc) j, dr, i, abs_dr, shift = neighbour_list("jDidS", a, 1.85) self.assertTrue((np.bincount(i) == np.bincount(j)).all()) r = a.get_positions() dr_direct = mic(r[j]-r[i], a.cell) self.assertArrayAlmostEqual(r[j]-r[i]+shift.dot(a.cell), dr_direct) abs_dr_from_dr = np.sqrt(np.sum(dr*dr, axis=1)) abs_dr_direct = np.sqrt(np.sum(dr_direct*dr_direct, axis=1)) self.assertTrue(np.all(np.abs(abs_dr-abs_dr_from_dr) < 1e-12)) self.assertTrue(np.all(np.abs(abs_dr-abs_dr_direct) < 1e-12)) self.assertTrue(np.all(np.abs(dr-dr_direct) < 1e-12))
def compare_configurations(dislo, bulk, dislo_ref, bulk_ref, alat, cylinder_r=None, print_info=True): """Compares two dislocation configurations based on the gradient of the displacements along the bonds. Parameters ---------- dislo : ase.Atoms Dislocation configuration. bulk : ase.Atoms Corresponding bulk configuration for calculation of displacements. dislo_ref : ase.Atoms Reference dislocation configuration. bulk_ref : ase.Atoms Corresponding reference bulk configuration for calculation of displacements. alat : float Lattice parameter for calculation of neghbour list cutoff. cylinder_r : float or None Radius of region of comparison around the dislocation coreself. If None makes global comparison based on the radius of `dislo` configuration, else compares the regions with `cylinder_r` around the dislocation core position. print_info : bool Flag to switch print statement about the type of the comparison Returns ------- float The Du norm of the differences per atom. """ if cylinder_r is None: x, y, __ = bulk.positions.T radius = np.sqrt(x**2 + y**2) cutoff_radius = radius.max() - 10. if print_info: print("Making a global comparison with radius %.2f" % cutoff_radius) else: cutoff_radius = cylinder_r if print_info: print("Making a local comparison with radius %.2f" % cutoff_radius) x, y, __ = bulk_ref.positions.T radius = np.sqrt(x**2 + y**2) cutoff_mask = (radius < cutoff_radius) second_NN_distance = alat bulk_i, bulk_j = neighbour_list('ij', bulk_ref, second_NN_distance) I_core, J_core = np.array([(i, j) for i, j in zip(bulk_i, bulk_j) if cutoff_mask[i]]).T mapping = {} for i in range(len(bulk)): mapping[i] = np.linalg.norm(bulk_ref.positions - bulk.positions[i], axis=1).argmin() u_ref = dislo_ref.positions - bulk_ref.positions u = dislo.positions - bulk.positions u_extended = np.zeros(u_ref.shape) u_extended[mapping.values(), :] = u du = u_extended - u_ref Du = np.linalg.norm(np.linalg.norm(mic(du[J_core, :] - du[I_core, :], bulk.cell), axis=1)) return Du
ref_frame = traj[0] individual_elements = set(ref_frame.numbers) s = '#{:>9s}'.format('frame') if 'time' in ref_frame.info: s = '{} {:>10s}'.format(s, 'time') s = '{} {:>10s}'.format(s, 'tot. rms') for element in individual_elements: s = '{} {:>10s}'.format(s, 'rms ({})'.format(chemical_symbols[element])) print(s) last_frame = traj[0] displacements = np.zeros_like(ref_frame.positions) for i, frame in enumerate(traj[1:]): last_frame.set_cell(frame.cell, scale_atoms=True) cur_displacements = frame.positions - last_frame.positions cur_displacements = mic(cur_displacements, frame.cell, frame.pbc) displacements += cur_displacements s = '{:10}'.format(i+1) if 'time' in frame.info: s = '{} {:10.6}'.format(s, frame.info['time']) s = '{} {:10.6}'.format(s, np.sqrt((displacements**2).mean())) for element in individual_elements: s = '{} {:10.6}'.format(s, np.sqrt( (displacements[frame.numbers == element]**2).mean())) print(s) last_frame = frame