def neededVectors(self, short_length, centers=((0,0,0),), ): centers = np.array(centers) max_centers = np.max(centers, axis=0) min_centers = np.min(centers, axis=0) extent = max_centers - min_centers v1, v2 = self.unitCell() l1 = vectorLength(v1) l2 = vectorLength(v2) size = abs(np.dot(extent + short_length, v1/l1)) n1 = int(np.ceil(size/l1)) v1t = np.array([v1[1], -v1[0], 0]) v1t /= vectorLength(v1t) test_vector = np.dot(v2, v1t)*v1t lt = vectorLength(test_vector) size = abs(np.dot(extent+short_length, test_vector/lt)) n2 = int(np.ceil(size/lt)) vectors = np.array([(n1, 0), (0, n2)]) return vectors
def relaxationFactor(self): if self.relaxation() is None: return 1.0 lr = vectorLength(self.relaxation().get_cell()[2]) lu = vectorLength(self.__atoms.get_cell()[2]) return lr/lu
def defaultParameters(self, parameters=DEFAULT, centers=((0,0,0), )): if parameters is DEFAULT: parameters = self.surface().defaultParameters() parameters = parameters.toDictionary() parameters.pop('kpts') parameters.pop('vectors') parameters = SurfaceLineDefectParameters(**parameters) vectors = parameters['vectors'] if vectors is DEFAULT: new_centers = self.rattleAtoms().get_positions() tmp_centers = centers centers = np.zeros((len(tmp_centers)+len(new_centers), 3), float) centers[:len(tmp_centers)] = tmp_centers centers[len(tmp_centers):] = new_centers s_parameters = self.surface().defaultParameters( parameters=parameters, centers=centers, ) vectors = np.array(s_parameters['vectors']) parameters = parameters.copy(vectors=vectors) if len(self.periodicity()) == 1: vp = self.periodicity()[0] v1, v2 = parameters['vectors'] if (vectorLength(np.cross(vp, v1))==0): v1 = vp elif (vectorLength(np.cross(vp, v2))==0): v2 = vp else: raise Exception vectors = np.array((v1, v2)) parameters = parameters.copy(vectors=vectors) kpts = parameters['kpts'] if kpts is DEFAULT: s_parameters = self.surface().defaultParameters( parameters=parameters, ) kpts = s_parameters['kpts'] parameters = parameters.copy(kpts=kpts) cell_size = parameters['cell_size'] if cell_size is DEFAULT: parameters = parameters.copy(cell_size=45) return parameters
def atoms(self, constrained=True, parameters=DEFAULT): if parameters is DEFAULT: parameters = self.parameters() parameters = self.defaultParameters(parameters) vectors = np.array(parameters['vectors']) lengths = vectorLength(vectors, 1) assert lengths.all() atoms = self.__atoms.copy() pos = atoms.get_positions() size = np.array([pos[:, i].max() - pos[:,i].min() for i in range(3)]) size = size + parameters['length_scales']['correlation_length'] repeats = (1, 1, vectors[0][0]) vectors = atoms.cell[2] * vectors[0][0] atoms = atoms.repeat(repeats) atoms.set_cell(size) atoms.cell[2] = vectors atoms = removeCopies(atoms) atoms = orderAtoms(atoms) atoms = self.makeAtomsRelaxed(atoms, self.relaxation()) return atoms
def write(self): method = self.method() images = self.getOriginalImages() new_images = [] for i in range(len(images)-1): initial, final = images[i:i+2] diff = final.positions - initial.positions diff = vectorLength(diff, 1) n_images = int(np.ceil(diff.max()/0.3)) - 1 print 'n_images=%d' % n_images t_images = [initial] for j in range(n_images): temp = t_images[0].copy() t_images.append(temp) t_images.append(final) neb = NEB(t_images) neb.interpolate() new_images.extend(neb.images[:-1]) new_images.append(images[-1]) neb = NEB(new_images) kpts = self.baseTask().parameters().kpts() self.method().writeNEB( runfile=self.runFile(), neb=neb, kpts=kpts, )
def __init__(self, system, step, end, direction=(0,0,1)): self.__step = step self.__end = end self.__relaxed_value = None self.__system = system direction = np.array(direction, float) self.__diretion = direction/vectorLength(direction) API.HasInputs.__init__(self, inputs=system.tasks())
def determineWaveFunctionRange( rho, r, point_density=4, density_range=(-3.5, -2.5), ): min_value = 10**(density_range[0]) max_value = 10**(density_range[1]) r = np.array(r) dh_cell = gridSpacingCell(r) cell = np.array([r[:, -1, 0, 0], r[:, 0, -1, 0], r[:, 0, 0, -1]]) - r[:, 0, 0, 0] assert max_value > min_value sh = rho.shape t_density = np.reshape(rho, (sh[0]*sh[1], sh[2])) d_min = t_density.min(axis=0) d_max = t_density.max(axis=0) z_values = r[2][0,0,:] sh = len(z_values) z_values = (z_values + cell[2, 2]/2.0) % cell[2, 2] - cell[2, 2]/2.0 z_values = np.roll(z_values, sh/2) d_min = np.roll(d_min, sh/2) d_max = np.roll(d_max, sh/2) take = z_values > - 5 take = np.logical_and(take, d_min < max_value) take = np.logical_and(take, d_max > min_value) z_values = z_values[take] d_min = d_min[take] d_max = d_max[take] padding = dh_cell[2, 2] z_span = (z_values.min() - padding, z_values.max() + padding) shape = np.zeros(3, int) shape[0] = np.ceil(vectorLength(cell[0])*point_density) shape[1] = np.ceil(vectorLength(cell[1])*point_density) shape[2] = np.ceil((z_span[1] - z_span[0])*point_density + 1) X, Y, Z = xy_z(shape=shape, cell=cell, z_span=z_span) X -= (X.max() - X.min())/2 Y -= (Y.max() - Y.min())/2 return np.array((X, Y, Z))
def getBeyondRangeMask(atoms, position, radius): atoms = atoms.copy() atoms.translate(-position) middle = np.sum(atoms.get_cell(), axis=0)/2. atoms.translate(middle) atoms = wrap(atoms) atoms.translate(-middle) beyond_range = vectorLength(atoms.get_positions(), 1) > radius return beyond_range
def makeSample(crystal, vectors): radius = numpy.max(vectorLength(vectors)) repeats = findNeededRepetitions(crystal.unitCell(), radius) atoms = crystal.toAseAtoms() atoms = atoms.repeat(repeats) atoms.set_cell(vectors) atoms = wrap(atoms) atoms = removeCopies(atoms) return atoms
def findIndices(find_atoms, atoms, tolerance=1e-5): indices = [] for pos in find_atoms.positions: diff = vectorLength(atoms.positions - pos, 1) argmin = np.argmin(diff) if diff[argmin] > tolerance: indices.append(None) else: indices.append(argmin) return indices
def setCellAndPBC(atoms, periodicity): dim = len(periodicity) if dim == 0: pass elif dim == 1: v0 = np.dot(periodicity, atoms.cell[:2])[0] pro = [vectorLength(np.cross(v0, v)) for v in atoms.cell[:2]] v1 = atoms.cell[np.argmax(pro)] cell = np.array([v0, v1, atoms.cell[2]]) atoms.set_cell(cell) atoms.set_pbc([True]*dim + [False]*(3-dim))
def makeAtomsRelaxed(atoms, relaxed_atoms, tolerance=1.0, cell=None, change=None, correct_drift=False): atoms = atoms.copy() if relaxed_atoms is None: return atoms if change is None: change = np.ones(len(atoms), np.bool) if cell is None: cell = atoms.get_cell() cell[relaxed_atoms.pbc] = relaxed_atoms.cell[relaxed_atoms.pbc] drift = np.zeros(3, np.float) used = np.zeros(len(relaxed_atoms), np.bool) changed = [] if relaxed_atoms is not None: # Find relaxed atoms closest to originals. for i, atom in enumerate(atoms): if not change[i]: continue mask = np.array([r_atom.symbol == atom.symbol for r_atom in relaxed_atoms]) mask = np.logical_and(mask, np.logical_not(used)) if mask.sum() == 0: continue diff = relaxed_atoms.positions[mask] - atom.position diff = minimalDistance(diff, cell[relaxed_atoms.pbc]) index = vectorLength(diff, 1).argmin() adjustment = diff[index] if vectorLength(adjustment) < tolerance: drift += adjustment real_index = np.arange(len(relaxed_atoms))[mask][index] used[real_index] = False changed.append(i) atom.position += adjustment if correct_drift: changed = np.array(changed) drift /= len(changed) atoms.positions[changed] -= drift return atoms
def notestSaveReadWaveFunctionsTest(self): band = 21 kn = 4 ws = 2 potential = Topographic(voltage=-2) rho, r, dh_cell = readCubeDensity(label=test_label) dh = np.array(map(vectorLength, dh_cell)) rho = rho.sum(axis=0) c, variables, domain = surfaceIntegrator(rho=rho, variables=r, rho0=1e-3, DS=1) thick_surface = vectorLength(c, axis=0) > 1e-9 take_z = thick_surface.sum(axis=0) take_z = take_z.sum(axis=0) > 0 wf, r, dh_cell = readCubeWavefunction(label=test_label, band=band, kn=kn) EF, eigs= readEigenvalues(label=test_label) kpts = readKpoints(label=test_label) energy = eigs[kn-1, band-1, 0] we = STMWeighting(energies=[energy], potential=potential, EF=EF) we = we[0] kpt, wk = kpts[kn-1] kappa = getVacuumDecayRate(energy) eikr = phaseFactor(kpt, r) u = wf/eikr grad_u = np.array(np.gradient(u, *dh)) A = (c*grad_u).sum(axis=0) B = u*c A=A[:,:,take_z] B=B[:,:,:,take_z] r=r[:,:,:,take_z] u, variables = propagateWaveFunction( A=A, B=B, kpt=kpt, r=r, kappa=kappa, height=10, ) weight = we*ws*wk Itest = weight*abs(u)**2 self.assertFalse(os.path.exists(testfile)) saveWavefunctionsToPlane(filename=testfile, label=test_label) self.assertTrue(os.path.exists(testfile)) f = netcdf.netcdf_file(testfile, 'r') self.assertTrue(len(f.variables.keys()) >0) f.close() I, r = STMFromFile( label=join(test_folder, 'test'), potentials=[potential], cells=None, ) self.assertArraysEqual(np.log(Itest[0,0]), np.log(I[0,0,0]), 5)
def modifyAtoms(self, atoms, indices): direction = self.direction() diff = atoms.positions[indices].mean(axis=0) diff = np.dot(diff, direction) move = (self.difference() - diff)*direction atoms.positions[indices] += move w_to = 1 mode = np.zeros(3*len(atoms)) for index1 in indices: mode[3*index1: 3*(index1+1)] = w_to*direction mode /= vectorLength(mode) constraint = FixedMode(mode) atoms.constraints.append(constraint) return atoms
def findPeriodicallyEqualAtoms(atoms, other_atoms): center = atoms.positions.mean(axis=0) center, remain = convertToBasis(center, other_atoms.cell) center = (np.array([.5, .5, .5]) - center)[0] other_atoms = wrap(other_atoms, center=center) cell = other_atoms.get_cell() pbc = atoms.get_pbc() cell = atoms.cell[pbc] group = -np.ones(len(other_atoms), dtype=np.int) for i, atom in enumerate(atoms): diff = other_atoms.get_positions() - atom.position pos = minimalDistance(diff, cell) mask = vectorLength(pos, 1) < 1e-5 indices = np.arange(len(other_atoms))[mask] group[indices] = i return group
def __init__(self, probe_symbol, surface_symbol, ): self.__probe_symbol = probe_symbol surface = BodyCenteredCubic111(surface_symbol) l = vectorLength(surface.cell()[1])/3 x, y = self.probePlacement(l) positions = [(x,y,2.210), (x, y + l, 0.92), (x + l*np.cos(np.pi/6), y-l*np.sin(np.pi/6), 0.92), (x - l*np.cos(np.pi/6),y-l*np.sin(np.pi/6), 0.92), ] added_atoms = Atoms(probe_symbol*len(positions), positions) SurfacePointDefect.__init__( self, surface=surface, added_atoms=added_atoms, )
def defaultParameters( self, parameters=DEFAULT, centers=((0,0,0),), ): if parameters is DEFAULT: parameters = SurfaceParameters1D() scales = parameters['length_scales'] short_length = scales['short_correlation_length'] depth = scales.depth() in_equal_layers = self.inequivalentLayers() electrode_layers = parameters['electrode_layers'] bound_layers = parameters['bound_layers'] free_layers = parameters['free_layers'] if bound_layers is DEFAULT: bound_layers = 2 if electrode_layers is DEFAULT: electrode_layers = 0 size = vectorLength(self.cell('orth_surface')[0]) if free_layers is DEFAULT: n_layers = int(np.ceil(in_equal_layers*depth/size)) free_layers = n_layers - bound_layers - electrode_layers cell_size = parameters['cell_size'] if cell_size is DEFAULT: c_length = parameters['length_scales']['correlation_length'] cell_size = (c_length, c_length, c_length) parameters = parameters.copy( free_layers=free_layers, bound_layers=bound_layers, electrode_layers=electrode_layers, cell_size=cell_size, ) return parameters
def passivateLowerSurface(atoms, direction, length=1, angle=90): s_direc = np.sign(direction) a_direc = abs(direction) - 1 max_or_min = {-1: min, 1: max}[s_direc] atoms = atoms.copy() angle = angle * (math.pi / 180) positions = atoms.get_positions() z_m = max_or_min(positions[:, a_direc]) lower_positions = positions[s_direc * positions[:, a_direc] > s_direc * (z_m - s_direc * 0.5)] lower_positions[:, 2] = lower_positions[:, 2].min() upper_positions = positions[s_direc * positions[:, a_direc] < s_direc * (z_m - s_direc * 0.5)] diff = upper_positions - lower_positions[0] l = vectorLength(diff, 1) not_direction = np.array([i for i in range(3) if i != a_direc], int) closest = abs(diff[np.argmin(l)][not_direction]) if abs(closest[0]) > abs(closest[1]): h_positions = [ position + [0, -length * math.cos(angle), s_direc * length * math.sin(angle)] for position in lower_positions ] h_positions += [ position + [0, length * math.cos(angle), s_direc * length * math.sin(angle)] for position in lower_positions ] else: h_positions = [ position + [-length * math.cos(angle), 0, s_direc * length * math.sin(angle)] for position in lower_positions ] h_positions += [ position + [length * math.cos(angle), 0, s_direc * length * math.sin(angle)] for position in lower_positions ] new_atoms = Atoms("H%d" % len(h_positions), h_positions, cell=atoms.get_cell(), pbc=atoms.get_pbc()) new_atoms += atoms return new_atoms
def make_electrodes(self, atoms): unique_electrodes = uniqueElectrodes(atoms.electrodes()) electodes = [] for electrode, names in unique_electrodes: electrode_atoms = makeElectrodeConform(electrode) s_dir = electrode.semiInfiniteDirection() parameters = self.parameters.copy() label = '_'.join(names) label = 'EL_%s' % label parameters['label'] = label kpts = np.array(parameters['kpts'] ) l = vectorLength(electrode.cell()[s_dir]) k = int(np.ceil(400/l)) kpts[s_dir] = k parameters['kpts'] = tuple(kpts) electrode_calculator = self.__class__(**parameters) electrode_atoms.set_calculator(electrode_calculator) electodes.append(electrode_atoms) return electodes
def substitutionalDopingOfMiddleLayer(atoms, n_dopants=1, dopant_element='P', centers=None): assert isinstance(n_dopants, int) assert n_dopants > 0 atoms = atoms.copy() middle_layer = list(findMiddleLayer(atoms)) symbols = np.array(atoms.get_chemical_symbols()) make_dopants = [] for i in range(n_dopants): if centers is None: middle_layer_index = 0 centers = [] else: pos = atoms.positions[np.array(middle_layer, int)] for center in centers: middle_layer_index = vectorLength(minimalDistance(pos - center, atoms.cell), 1).argmax() index = middle_layer.pop(middle_layer_index) make_dopants.append(index) centers.append(atoms[index].position) symbols[np.array(make_dopants, int)] = dopant_element atoms.set_chemical_symbols(symbols) return atoms
def modifyAtoms(self, atoms, indices): index2 = indices[-1] other_indices = indices[:-1] direction = np.array([0, 0, 1.0]) diff = atoms.positions[index2] - atoms.positions[other_indices].mean(axis=0) diff = np.dot(diff, direction) move = self.difference()*direction move -= diff*direction w_other = 1.0/len(indices) w2 = 1.0 - w_other atoms.positions[index2] += move*w2 atoms.positions[other_indices] -= move*w_other mode = np.zeros(3*len(atoms)) for index1 in other_indices: mode[3*index1: 3*(index1+1)] = w_other*direction mode[3*index2: 3*(index2+1)] = -w2*direction mode /= vectorLength(mode) constraint = FixedMode(mode) atoms.constraints.append(constraint) return atoms
def atoms(self, constrained=True, parameters=DEFAULT): parameters = self.defaultParameters(parameters) vectors = np.array(parameters['vectors']) lengths = vectorLength(vectors, 1) assert lengths.all() atoms = self.__atoms.copy() vectors = convertFromBasis(vectors, atoms.cell) repeats = findNeededRepetitions(atoms.cell, 1.5*lengths.max()) atoms = atoms.repeat(repeats) atoms.cell[atoms.pbc] = vectors atoms.wrap() atoms = removeCopies(atoms) atoms.setTag('Reference', picker=None) padding = np.logical_not(atoms.pbc) assert padding.sum() == 0 atoms = self.makeAtomsRelaxed(atoms, self.relaxation()) return atoms
def saveWavefunctionsToPlane(filename, label='./siesta', density_range=(-3.5, -2.5)): rho, r, dh_cell = readCubeDensity(label=label) x, y, z = r dh = np.array([dh_cell[0,0], dh_cell[1,1], dh_cell[2,2]]) eigs, kpts, EF = readInfoForSTMSimulation(label=label) eigs, rho, w_s = handleSpinPolarization(eigs, rho) is_spin_polarized = w_s == 1 if is_spin_polarized: rho = rho.sum(axis=0) energies = np.array(eigs)[:,0] i_o = (energies < EF).sum() - 1 i_u = i_o + 1 i_t = i_o - 2 rho0 = 10**(np.array(density_range).mean()) DS = density_range[1] - density_range[0] c, c_r, domain = surfaceIntegrator(rho=rho, variables=r, rho0=rho0, DS=DS) thick_surface = vectorLength(c, axis=0) > 1e-9 take_z = thick_surface.sum(axis=0) take_z = take_z.sum(axis=0) > 0 thick_surface = thick_surface[:,:,take_z] x, y, z = c_r wfs = [] EF, energies = readEigenvalues(label=label) folder = os.path.dirname(label) for wf_filename in os.listdir(folder): wf_filename = wf_filename.split('.') if wf_filename[0] == 'siesta' and wf_filename[-2] == 'REAL' and wf_filename[-1] == 'cube': kn = int(wf_filename[1][1:]) band = int(wf_filename[2][2:]) spin = wf_filename[3] if is_spin_polarized: spin = {'UP':0, 'DOWN':1}[spin] elif spin=='DOWN': continue else: spin = 0 wfs.append((energies[kn-1, band-1, spin], kn-1, band-1, spin)) wfs.sort() nc_defined = False f = netcdf.netcdf_file(filename, 'w') for i, info in enumerate(wfs): energy, kn, band, spin = info kpt, w_k = kpts[kn] if energy > 0: continue kappa = getVacuumDecayRate(energy) wf, r, dh_cell = readCubeWavefunction(band + 1, kn=kn+1, spin=spin+1, folder=folder) eikr = phaseFactor(kpt, r) u = wf/eikr grad_u = np.array(np.gradient(u, *dh)) A = (c*grad_u).sum(axis=0) r = r[:,:,:, take_z] u = u[:,:,take_z] A = A[:,:,take_z] ct = c[:, :, :, take_z] if not nc_defined: nwf = f.createDimension('nwf', len(wfs)) xd = f.createDimension('x', u.shape[0]) yd = f.createDimension('y', u.shape[1]) zd = f.createDimension('z', u.shape[2]) ran = f.createDimension('range', 2) points = f.createDimension('points', thick_surface.sum()) vector3d = f.createDimension('vector3d', 3) comp = f.createDimension('complex', 2) d_var = f.createVariable('thick_surface', dimensions=('x', 'y', 'z'), type=np.dtype('b')) ran_var = f.createVariable('grid_cell', dimensions=('vector3d', 'vector3d'), type=np.dtype('f')) ran_var[:] = dh_cell origin_var = f.createVariable('origin', dimensions=('vector3d', ), type=np.dtype('f')) origin_var[:] = np.array([r[0].min(), r[1].min(), r[2].min()]) d_var[:] = thick_surface c_var = f.createVariable('c', dimensions=('vector3d', 'points'), type=np.dtype('f4')) for ci in range(3): c_var[ci,:] = ct[ci, thick_surface] spin_weight = f.createVariable('spin_weight', dimensions=tuple(), type=np.dtype('i')) spin_weight.assignValue(w_s) fermi_energy = f.createVariable('EF', dimensions=tuple(), type=np.dtype('f')) fermi_energy.assignValue(EF) kpts_var = f.createVariable('kpts', type=np.dtype(float), dimensions=('nwf', 'vector3d')) wk_var = f.createVariable('wk', type=np.dtype(float), dimensions=('nwf',)) energy_var = f.createVariable('energy', type=np.dtype(float), dimensions=('nwf',)) spin_var = f.createVariable('spin', type=np.dtype('i'), dimensions=('nwf',)) u_var = f.createVariable('u', type=np.dtype('f4'), dimensions=('nwf', 'points', 'complex')) A_var = f.createVariable('A', type=np.dtype('f4'), dimensions=('nwf', 'points', 'complex')) nc_defined = True wk_var[i] = w_k kpts_var[i] = kpt energy_var[i] = energy spin_var[i] = spin u_var[i,:, 0] = u[thick_surface].real u_var[i,:, 1] = u[thick_surface].imag A_var[i,:, 0] = A[thick_surface].real A_var[i,:, 1] = A[thick_surface].imag f.close() return True
def __init__(self, difference, direction=(0, 0, 1)): self.__difference = difference direction = np.array(direction, float) self.__direction = direction/vectorLength(direction)