def test_names(testdir): """Test different gs vs excited name. Tests also default names.""" # do a Vibrations calculation first atoms = H2Morse() vib = Vibrations(atoms) vib.run() assert '0x-' in vib.cache # do a Resonant Raman calculation rmc = ResonantRamanCalculator(atoms, H2MorseExcitedStatesCalculator, verbose=True) rmc.run() # excitation files should reside in the same directory as cache files assert (Path(rmc.name) / ('ex.eq' + rmc.exext)).is_file() # XXX does this still make sense? # remove the corresponding pickle file, # then Placzek can not anymore use it for vibrational properties key = '0x-' assert key in rmc.cache del rmc.cache[key] # make sure this is not used om = 1 gam = 0.1 pz = Placzek(atoms, H2MorseExcitedStates, name='vib', exname='raman') pzi = pz.get_absolute_intensities(omega=om, gamma=gam)[-1] parprint(pzi, 'Placzek') # check that work was distributed correctly assert len(pz.myindices) <= -(-6 // world.size)
def hse_spinorbit(base_dir="./"): hse_file = os.path.join(base_dir, "hse.gpw") hse_nowfs_file = os.path.join(base_dir, "hse_nowfs.gpw") hse_eigen_file = os.path.join(base_dir, "hse_eigenvalues.npz") hse_eigen_soc_file = os.path.join(base_dir, 'hse_eigenvalues_soc.npz') if not os.path.isfile(hse_eigen_file): return if not os.path.isfile(hse_eigen_file): return ranks = [0] comm = mpi.world.new_communicator(ranks) if mpi.world.rank in ranks: calc = GPAW(hse_nowfs_file, communicator=comm, txt=None) with open(hse_eigen_file, 'rb') as fd: dct = dict(np.load(fd)) e_skn = dct.get('e_hse_skn') dct = {} e_mk, s_kvm = get_soc_eigs(calc, gw_kn=e_skn, return_spin=True, bands=np.arange(e_skn.shape[2])) dct['e_hse_mk'] = e_mk dct['s_hse_mk'] = s_kvm[:, 2, :].transpose() with open(hse_eigen_soc_file, 'wb') as fd: np.savez(fd, **dct) parprint("SOC HSE06 finished!")
def elph_do_raman_spectra(calc, supercell, laser_freqs, do_permutations, laser_broadening, phonon_broadening, shift_step, polarizations, write_mode_intensities): from ase.units import _hplanck, _c, J parprint('Computing phonons') ph = ase.phonons.Phonons(atoms=calc.atoms, name="phonons", supercell=supercell) ph.read() w_ph = np.array(ph.band_structure([[0, 0, 0]])[0]) if calc.world.rank == 0: np.save('frequencies.npy', w_ph * 8065.544) # frequencies in cm-1 # And the Raman spectra are calculated for laser_nm in laser_freqs: w_l = _hplanck*_c*J/(laser_nm*10**(-9)) for polarization in polarizations: if len(polarization) != 2: raise ValueError(f'invalid polarization "{polarization}", should be two characters like "xy"') d_i = 'xyz'.index(polarization[0]) d_o = 'xyz'.index(polarization[1]) name = "{}nm-{}".format(laser_nm, polarization) if not os.path.isfile(f"RI_{name}.npy"): leffers.calculate_raman( calc=calc, w_ph=w_ph, permutations=do_permutations, w_l=w_l, ramanname=name, d_i=d_i, d_o=d_o, gamma_l=laser_broadening, phonon_sigma=phonon_broadening, shift_step=shift_step, write_mode_intensities=write_mode_intensities, ) #And plotted leffers.plot_raman(relative = True, figname = f"Raman_{name}.png", ramanname = name)
def __init__(self, atoms, propertyfunction, save=False, name='fd', ending='', d=0.001, parallel=0, world=None): self.atoms = atoms self.indices = np.asarray(range(len(atoms))) self.propertyfunction = propertyfunction self.save = save self.name = name self.ending = ending self.d = d self.value = np.empty([len(self.atoms), 3]) if world is None: world = mpi.world self.world = world if world.size < 2: if parallel > 1: parprint('#', (self.__class__.__name__ + ':'), 'Serial calculation, keyword parallel ignored.') parallel = 0 self.parallel = parallel if parallel > 1: self.set_parallel()
def get_mode_raman(outpath, eigendata, cart_pol_derivs): if os.path.exists(outpath): parprint(f'Found existing {outpath}') return world.barrier() parprint(f'Computing mode raman tensors... ({outpath})') cart_pol_derivs = np.load('raman-cart.npy') mode_pol_derivs = [] for row in eigendata['eigenvectors']: mode_displacements = eigendata['atom_masses'].repeat(3) ** -0.5 * row mode_displacements /= np.linalg.norm(mode_displacements) # ∂α_ij ∂α_ij ∂x_ak # ----- = sum ( ----- ----- ) # ∂u_n a,k ∂x_ak ∂u_n # # = dot product of (3n-dimensional gradient of ∂α_ij) # with (3n-dimensional displacement vector of mode n) mode_pol_deriv = np.dot( # move i and j (axes 2 and 3) to the outside and combine axes 0 and 1 (x components) cart_pol_derivs.transpose((2, 3, 0, 1)).reshape((9, -1)), mode_displacements, ).reshape((3, 3)) mode_pol_derivs.append(mode_pol_deriv) np.save(outpath, mode_pol_derivs)
def main( name, # root="../ZnVO/", root="/cluster/scratch/ttian/ZnVO", clean=False): if name not in ("Zn", "Co"): return False # Directory if rank == 0: base_dir = os.path.join(root, "{}V2O5".format(name)) if clean: shutil.rmtree(base_dir, ignore_errors=True) if not os.path.exists(base_dir): os.makedirs(base_dir) world.barrier() if clean: return # on all ranks atoms = get_structure(name) parprint(atoms) base_dir = os.path.join(root, "{}V2O5".format(name)) relax(atoms, name=name, base_dir=base_dir) return 0
def elph_do_symmetry_expansion(supercell, calc, displacement_dist, phonon, disp_carts, disp_sites, supercell_atoms): from gpaw.elph.electronphonon import ElectronPhononCoupling natoms_prim = len(calc.get_atoms()) disp_values = [read_elph_input(f'sym-{index}') for index in range(len(disp_sites))] # NOTE: phonon.symmetry includes pure translational symmetries of the supercell # so we use an empty quotient group quotient_perms = np.array([np.arange(len(supercell_atoms))]) super_lattice = supercell_atoms.get_cell()[...] super_symmetry = phonon.symmetry.get_symmetry_operations() oper_sfrac_rots = super_symmetry['rotations'] oper_sfrac_trans = super_symmetry['translations'] oper_cart_rots = np.array([super_lattice.T @ Rfrac @ np.linalg.inv(super_lattice).T for Rfrac in oper_sfrac_rots]) oper_cart_trans = oper_sfrac_trans @ super_lattice oper_phonopy_coperms = phonon.symmetry.get_atomic_permutations() oper_phonopy_deperms = np.argsort(oper_phonopy_coperms, axis=1) # Convert permutations by composing the following three permutations: into phonopy order, apply oper, back to ase order parprint('phonopy deperms:', oper_phonopy_deperms.shape) deperm_phonopy_to_ase = interop.get_deperm_from_phonopy_sc_to_ase_sc(natoms_prim, supercell) oper_deperms = [np.argsort(deperm_phonopy_to_ase)[deperm][deperm_phonopy_to_ase] for deperm in oper_phonopy_deperms] del oper_phonopy_coperms, oper_phonopy_deperms elphsym = symmetry.ElphGpawSymmetrySource.from_setups_and_ops( setups=supercell_atoms.calc.wfs.setups, lattice=super_lattice, oper_cart_rots=oper_cart_rots, oper_cart_trans=oper_cart_trans, oper_deperms=oper_deperms, ) if world.rank == 0: full_derivatives = symmetry.expand_derivs_by_symmetry( disp_sites, # disp -> atom disp_carts, # disp -> 3-vec disp_values, # disp -> T (displaced value, optionally minus equilibrium value) elph_callbacks_2(supercell_atoms.calc.wfs, elphsym, supercell=supercell), # how to work with T oper_cart_rots, # oper -> 3x3 oper_perms=oper_deperms, # oper -> atom' -> atom quotient_perms=quotient_perms, ) # NOTE: confusingly, Elph wants primitive atoms, but a calc for the supercell elph = ElectronPhononCoupling(calc.atoms, calc=supercell_atoms.calc, supercell=supercell) displaced_cell_index = elph.offset del elph # that's all we needed it for eq_Vt, eq_dH, eq_forces = read_elph_input('eq') for a in range(natoms_prim): for c in range(3): delta_Vt, delta_dH, delta_forces = full_derivatives[natoms_prim * displaced_cell_index + a][c] for sign in [-1, +1]: disp = interop.AseDisplacement(atom=a, axis=c, sign=sign) disp_Vt = eq_Vt + sign * displacement_dist * delta_Vt disp_dH = {k: eq_dH[k] + sign * displacement_dist * delta_dH[k] for k in eq_dH} disp_forces = eq_forces + sign * displacement_dist * delta_forces pickle.dump(disp_forces, paropen(f'phonons.{disp}.pckl', 'wb'), protocol=2) pickle.dump((disp_Vt, disp_dH), paropen(f'elph.{disp}.pckl', 'wb'), protocol=2) world.barrier()
def getBulkEnergy(latticeParams, jobID): """ For a given set of bravais lattice parameters, optimize atomic coordinates and return minimum energy """ ### INITIALIZE jobObject, bulkObject, calcObject, dft, preCalcObject, preCalcObject, existsPrecalc, atoms, magmoms = initialize( jobID, latticeParams) ### PRECALCULATE if existsPrecalc: optimizePos(atoms, dft, preCalcObject, magmoms, restart=False, saveWF=True) ### CALCULATE optimizePos(atoms, dft, calcObject, magmoms, restart=existsPrecalc, saveWF=False) ### GET ENERGY energy = atoms.get_potential_energy() with paropen('lattice_opt.log', 'a') as logfile: logfile.write('%s\t%s\n' % (energy, latticeParams)) parprint('%s\t%s\n' % (energy, latticeParams)) return energy
def get_ensemble_energies(self, size: int = 2000, seed: int = 0) -> np.ndarray: """Returns an array of ensemble total energies""" self.seed = seed if self.verbose: parprint(self.beef_type, 'ensemble started') if self.contribs is None: self.contribs = self.calc.get_nonselfconsistent_energies( self.beef_type) self.e = self.calc.get_potential_energy(self.atoms) if self.beef_type == 'beefvdw': assert len(self.contribs) == 32 coefs = self.get_beefvdw_ensemble_coefs(size, seed) elif self.beef_type == 'mbeef': assert len(self.contribs) == 64 coefs = self.get_mbeef_ensemble_coefs(size, seed) elif self.beef_type == 'mbeefvdw': assert len(self.contribs) == 28 coefs = self.get_mbeefvdw_ensemble_coefs(size, seed) self.de = np.dot(coefs, self.contribs) self.done = True if self.verbose: parprint(self.beef_type, 'ensemble finished') return self.e + self.de
def get_nmse_structure(self, structure_numbers): """ Read cif files from NMSE database directory, return lists of ASE Atoms objects and names :param structure_numbers: list of NMSE database index numbers :return: tuple: list of Atoms objects, list of structure names """ nmse_data = pd.read_json(self.db_path + 'nmse_data_frame.json') # Filter structures in NMSE database general_filters = ['Error==False', 'is_ordered==True', 'Layers==1.0'] compound_filters = dict( include=['Pb\d*I'], # include only lead iodide compounds exclude=['Pb\d*I\d*\D' ]) # exclude any lead iodide mixed halide compounds dft_database = filter_structures(database=nmse_data, general_filters=general_filters, compound_filters=compound_filters) atoms_list = [] structure_base_name_list = [] for structure_number in structure_numbers: structure_info = dft_database.query(f'Index=={structure_number}') structure_file_name = structure_info.loc[structure_info.index[0], 'CIF'] structure_base_name, _ = splitext(structure_file_name) structure_base_name_list.append(structure_base_name) parprint('Loading file: ', structure_file_name) # display(structure_info) atoms_list.append(load_atoms_from_cif(structure_file_name)) return atoms_list, structure_base_name_list
def gwqeh(mater, n_layers, band_num=3): bb_file(mater) parprint("Calculate QP correction for {} with {} layers".format( mater, n_layers)) assert mater in d_list.keys() assert n_layers >= 2 structure = ["{}{}".format(int(n_layers), mater)] distances = [d_list[mater]] * (n_layers - 1) d0 = d_list[mater] f_out = os.path.join(data_path, "{}/gwqeh_{}".format(mater, n_layers)) # The GWQEH calculation calc = GPAW(restart=gs_wfs(mater)) ne = calc.get_number_of_electrons() nb = int(ne // 2) bands = (nb - band_num, nb + band_num) del calc # Calc GWQEH qeh_corr = GWQEHCorrection( calc=es_wfs(mater), gwfile=g0w0_file(mater), filename=f_out, structure=structure, d=distances, layer=int(n_layers // 2), bands=bands, include_q0=True # Why? ) qeh_corr.calculate_qp_energies() # parprint(corr) qeh_corr.save_state_file()
def test_names(): """Test different gs vs excited name. Tests also default names.""" # do a Vibrations calculation first atoms = H2Morse() Vibrations(atoms).run() assert os.path.isfile('vib.0x-.pckl') # do a Resonant Raman calculation rmc = ResonantRamanCalculator(atoms, H2MorseExcitedStatesCalculator, verbose=True) rmc.run() # remove the corresponding pickle file, # then Placzek can not anymore use it for vibrational properties assert os.path.isfile('raman.0x-.pckl') os.remove('raman.0x-.pckl') # make sure this is not used om = 1 gam = 0.1 pz = Placzek(atoms, H2MorseExcitedStates, name='vib', exname='raman') pzi = pz.get_absolute_intensities(omega=om, gamma=gam)[-1] parprint(pzi, 'Placzek') # check that work was distributed correctly assert len(pz.myindices) <= -(-6 // world.size)
def set_calculator(self, calc=None, nkpts=4096): """ Sets the calculator and resets the k-points according to the cell shape """ if calc is None and self.calc is None: parprint("ERROR: no calculator provided") return elif calc is not None: self.calc = calc kcell = self.atoms.get_reciprocal_cell() # Vcell = np.abs(np.dot(kcell[0, :], # np.cross(kcell[1, :], kcell[2, :]))) k12 = np.cross(kcell[0, :], kcell[1, :]) k23 = np.cross(kcell[1, :], kcell[2, :]) k31 = np.cross(kcell[2, :], kcell[0, :]) n1 = 1. / np.linalg.norm(k23) n2 = 1. / np.linalg.norm(k31) n3 = 1. / np.linalg.norm(k12) tot_kpts = nkpts / self.atoms.get_number_of_atoms() av_kpts = (tot_kpts / (n1 * n2 * n3))**(1. / 3) kpts1 = int(round(n1 * av_kpts, 0)) kpts2 = int(round(n2 * av_kpts, 0)) kpts3 = int(round(n3 * av_kpts, 0)) kpts = (np.max((kpts1, 1)), np.max((kpts2, 1)), np.max((kpts3, 1))) if self.verbosity > 0: parprint("k-points:", kpts) self.calc.set(kpts={'size': kpts, 'gamma': True}) self.atoms.set_calculator(calc)
def gap(base_dir="./", mode="gllb"): curr_dir = os.path.dirname(os.path.abspath(__file__)) param_file = os.path.join(curr_dir, "../parameters.json") gpw_file = os.path.join(base_dir, "gs.gpw") gap_res = os.path.join(base_dir, "gap.txt") # Check is gap calculated if os.path.exists(gap_res): parprint("Bandgap calculated, will use gpw directly!") return 0 # Check if gpw file exists if not os.path.exists(gpw_file): raise FileNotFoundError("Structure relaxation not done yet!") if os.path.exists(param_file): params = json.load(open(param_file, "r")) else: raise FileNotFoundError("no parameter file!") # The true gllb-sc calculation calc = GPAW(gpw_file, **params["gap"]) calc.get_potential_energy() # Now for bg response = calc.hamiltonian.xc.xcs["RESPONSE"] response.calculate_delta_xc() EKs, Dxc = response.calculate_delta_xc_perturbation() gap = EKs + Dxc if rank == 0: print("{:.4f}".format(gap), open(gap_res, "w")) # write answer return 0
def relax(atoms, name="", base_dir="./", smax=2e-4): curr_dir = os.path.dirname(os.path.abspath(__file__)) param_file = os.path.join(curr_dir, "../parameters.json") gpw_file = os.path.join(base_dir, "gs.gpw") if os.path.exists(gpw_file): parprint("Relaxation already done, will use gpw directly!") return 0 if os.path.exists(param_file): params = json.load(open(param_file, "r")) else: raise FileNotFoundError("no parameter file!") # calculation asign calc = GPAW(**params["relax"]) atoms.set_calculator(calc) traj_filename = os.path.join(base_dir, "{}_relax.traj".format(name)) log_filename = os.path.join(base_dir, "{}_relax.log".format(name)) opt = QuasiNewton(atoms, trajectory=traj_filename, logfile=log_filename) mask = [1, 1, 1, 0, 0, 0] # Relax for bulk opt.run(fmax=0.01, smax=smax, smask=mask) # Calculate the ground state calc.set(**params["gs"]) atoms.get_potential_energy() calc.write(gpw_file)
def calculate_periodic_correction(self): G_z = self.G_z if self.Elp is not None: return self.Elp if self.epsilon_GG is None: self.calculate_epsilon_GG() Elp = 0.0 for vector in self.G_parallel: G2 = (np.dot(vector, vector) + G_z * G_z) rho_G = self.q * np.exp(- G2 * self.sigma ** 2 / 2, dtype=complex) if self.dimensionality == '2d': rho_G *= np.exp(1j * self.z0 * G_z) A_GG = (self.GG * self.epsilon_GG['out-of-plane'] + np.dot(vector, vector) * self.epsilon_GG['in-plane']) if np.allclose(vector, 0): A_GG[0, 0] = 1 # The d.c. potential is poorly defined V_G = np.linalg.solve(A_GG, rho_G) if np.allclose(vector, 0): parprint('Skipping G^2=0 contribution to Elp') V_G[0] = 0 Elp += (rho_G * V_G).sum() Elp *= 2.0 * np.pi * Ha / self.Omega self.Elp = Elp return Elp
def getBulkEnergy(latticeParams): """For a given set of bravais lattice parameters, optimize atomic coordinates and return minimum energy""" global nIter nIter += 1 atoms = job.fromParams(latticeParams) calc = job.calc(restart=True) if existsPrecalc else job.calc() if existsPrecalc: preCalc = job.calc(precalc=True) job.optimizePos(atoms,preCalc,saveWF = True) if job.dftcode =='gpaw': atoms,calc = job.gpawRestart() job.optimizePos(atoms,calc) energy = atoms.get_potential_energy() with paropen('lattice_opt.log','a') as logfile: logfile.write('%s\t%s\n' %(energy,latticeParams)) parprint('%s\t%s\n' %(energy,latticeParams)) if job.dftcode=='gpaw': atoms.calc.write('inp.gpw', mode='all') #for use in getXCContribs io.write('out.traj',atoms) return energy
def main( name, # root="../ZnVO/", root="/cluster/scratch/ttian/ZnVO", model="A", clean=False): if name not in ("Zn", "Co"): return False # Directory if rank == 0: base_dir = os.path.join(root, "{}V2O5".format(name)) if clean: shutil.rmtree(base_dir, ignore_errors=True) if not os.path.exists(base_dir): os.makedirs(base_dir) world.barrier() if clean: return # on all ranks base_dir = os.path.join(root, "{}V2O5".format(name)) parprint("Running {} with model type {}".format(name, model)) relax(base_dir=base_dir, model=model) return 0
def check_diff(g1, g2, gd, txt): # print rank, txt, "shapes", g1.shape, g2.shape intd = gd.integrate(np.abs(g1 - g2)) parprint(txt, 'integrated diff=', intd, end='') maxd = np.max(np.abs(g1 - g2)) parprint('max diff=', maxd) equal(intd, 0, 1.e-8) equal(maxd, 0, 1.e-9)
def check_diff(g1, g2, gd, txt): # print rank, txt, "shapes", g1.shape, g2.shape intd = gd.integrate(np.abs(g1 - g2)) parprint(txt, "integrated diff=", intd, end="") maxd = np.max(np.abs(g1 - g2)) parprint("max diff=", maxd) equal(intd, 0, 1.0e-8) equal(maxd, 0, 1.0e-9)
def test_single(self): sb = StructureBuilder() atoms, *_ = sb.get_structure("Si", "diamond") base_dir = os.path.join(os.path.dirname(__file__), "../../tmp/Si-eps-test/") m_calc = MaterCalc(atoms=atoms, base_dir=base_dir) # PBE parprint(m_calc.check_status())
def run_job(label): cmd = "g09 < {0}.com > {0}.log".format(label) parprint(cmd) exit_state = os.system(cmd) if exit_state == 0: print("Calculation exited normally") else: print("Abnormal job with exit code {0}".format(exit_state)) return exit_state
def print_version(version): parprint(""" ____ _ _ / ___|__ _| |_| | ___ __ _ _ __ _ __ | | / _` | __| | / _ \/ _` | '__| '_ \ | |__| (_| | |_| |__| __/ (_| | | | | | | \____\__,_|\__|_____\___|\__,_|_| |_| |_| """ + version + """ """)
def do_structure(supercell_atoms, name): forces_path = f'phonons.{name}.pckl' elph_path = f'elph.{name}.pckl' if not os.path.exists(elph_path): parprint(f'== computing elph.{name}.pckl') elph_data = get_elph_data(supercell_atoms) forces = supercell_atoms.get_forces() pickle.dump(forces, paropen(forces_path, 'wb'), protocol=2) pickle.dump(elph_data, paropen(elph_path, 'wb'), protocol=2)
def polarizability(base_dir="./", mode="df", fermi_shift=None): curr_dir = os.path.dirname(os.path.abspath(__file__)) es_gpw = os.path.join(base_dir, "es.gpw") param_file = os.path.join(curr_dir, "../parameters.json") if os.path.exists(param_file): params = json.load(open(param_file, "r")) else: raise FileNotFoundError("no parameter file!") if not os.path.exists(es_gpw): raise FileNotFoundError("Excited state not calculated!") if mode not in ("df", "tetra"): raise ValueError("Mode should be df or tetra") if fermi_shift is None: data_file = os.path.join(base_dir, "polarizability_{}.npz".format(mode)) else: data_file = os.path.join(base_dir, "polarizability_{}_{:.2f}.npz".format(mode, fermi_shift)) params[mode]["intraband"] = True if os.path.exists(data_file): parprint("Polarizability file exists!") return 0 df = DielectricFunction(calc=es_gpw, **params[mode], gate_voltage=fermi_shift) # add energy shift alpha0x, alphax = df.get_polarizability(q_c=[0, 0, 0], direction="x", pbc=[True, True, False], filename=None) alpha0y, alphay = df.get_polarizability(q_c=[0, 0, 0], direction="y", pbc=[True, True, False], filename=None) alpha0z, alphaz = df.get_polarizability(q_c=[0, 0, 0], direction="z", pbc=[True, True, False], filename=None) freq = df.get_frequencies() data = dict(frequencies=freq, alpha_x=alphax, alpha_y=alphay, alpha_z=alphaz, alpha_x0=alpha0x, alpha_y0=alpha0y, alpha_z0=alpha0z,) from ase.parallel import world import numpy if world.rank == 0: numpy.savez_compressed(data_file, **data)
def set_atoms(self, structure=None): """ Sets the atoms from a given ATAT structure file """ if structure is not None: to_min_tilt = self.parameters.to_min_tilt to_niggli = self.parameters.to_niggli self.atoms = read_atat_input(structure, pbc=(1, 1, 1), verbosity=self.verbosity, minimize_tilt=to_min_tilt, niggli_reduce=to_niggli) else: parprint("ERROR: No ATAT structure file given")
def _cleanall(basedir): parprint("Clean up {0}".format(basedir)) if rank == 0: p = Path(basedir) plist = [] for type in ["*.com", "*.log", "*.ase", "*.xyz", "*.chk", "lsf*"]: plist = plist + list(p.glob(type)) for f in plist: if f.name != "init.xyz": os.unlink(f)
def permittivity(base_dir="./", mode="df"): curr_dir = os.path.dirname(os.path.abspath(__file__)) es_gpw = os.path.join(base_dir, "es.gpw") param_file = os.path.join(curr_dir, "../parameters.json") if os.path.exists(param_file): params = json.load(open(param_file, "r")) else: raise FileNotFoundError("no parameter file!") if not os.path.exists(es_gpw): raise FileNotFoundError("Excited state not calculated!") if mode not in ("df", "tetra"): raise ValueError("Mode should be df or tetra") data_file = os.path.join(base_dir, "polarizability_{}.npz".format(mode)) if os.path.exists(data_file): parprint("Polarizability file exists!") return 0 df = DielectricFunction(calc=es_gpw, **params[mode]) eps0x, epsx = df.get_dielectric_function( q_c=[0, 0, 0], direction="x", #pbc=[True, True, False], filename=None) eps0y, epsy = df.get_dielectric_function( q_c=[0, 0, 0], direction="y", #pbc=[True, True, False], filename=None) eps0z, epsz = df.get_dielectric_function( q_c=[0, 0, 0], direction="z", #pbc=[True, True, False], filename=None) freq = df.get_frequencies() data = dict( frequencies=freq, eps_x=epsx, eps_y=epsy, eps_z=epsz, eps_x0=eps0x, eps_y0=eps0y, eps_z0=eps0z, ) from ase.parallel import world import numpy if world.rank == 0: numpy.savez_compressed(data_file, **data)
def bb_file(mater): f_name = os.path.join(os.path.curdir, "{}-chi.npz".format(mater)) if os.path.exists(f_name): return f_name else: # Calculate the BB parprint("Chi matrix not calculated, build for now!") df = DielectricFunction(calc=es_wfs(mater), eta=0.1, intraband=False, truncation="2D") bb = BuildingBlock(mater, df, qmax=3) bb.calculate_building_block() return f_name
def do_structure(supercell_atoms, name): with cache.lock(name) as handle: if handle is not None: parprint(f'== computing elph/cache.{name}.json') Vt_sG, dH_all_asp = get_elph_data(supercell_atoms) forces = supercell_atoms.get_forces() if world.rank == 0: handle.write( ElphDataset( Vt_sG=Vt_sG, dH_all_asp=dH_all_asp, forces=forces, ))
def converged(self): """Function that checks the convergence of the min. surrogate model.""" self.list_fmax = get_fmax(np.array([self.list_gradients[-1]])) self.max_abs_forces = np.max(np.abs(self.list_fmax)) if self.max_abs_forces < self.fmax: parprint('Congratulations. Structural optimization has converged.') parprint('All the evaluated structures can be found in:', self.filename) print_cite_mlmin() return True return False
def print_force_summary(self): """Print a detailed summary of forces in the system. """ message = [] message.append("Total forces:") if self.forces is None: message.append(" Not calculated") else: for i, force in enumerate(self.forces): message.append(" " + str(i) + ": " + str(force)) message.append("") # Forces in subsystems for name, subsystem in self.subsystems.iteritems(): message.append("Subsystem \"" + name + "\":") if subsystem.forces is None: message.append(" Not calculated") else: for i, force in enumerate(subsystem.forces): message.append(" " + str(i) + ": " + str(force)) message.append("") # Forces in interactions for pair, interaction in self.subsystem_interactions.iteritems(): message.append("Interaction forces between \""+pair[0]+"\" and \""+pair[1] + ":") # Total interaction force message.append(" Total:") if interaction.interaction_forces is None: message.append(" Not calculated") else: for i, force in enumerate(interaction.interaction_forces): message.append(" " + str(i) + ": " + str(force)) message.append("") # Link atom correction message.append(" Link atom correction:") if interaction.link_atom_correction_forces is None: message.append(" Not calculated") else: for i, force in enumerate(interaction.link_atom_correction_forces): message.append(" " + str(i) + ": " + str(force)) message.append("") str_message = style_message("HYBRIDCALCULATOR FORCE SUMMARY", message) parprint(str_message)
def run(lastres=[]): results = [] # Hirshfeld ---------------------------------------- if 1: hd = HirshfeldDensity(calc) # check for the number of electrons expected = [[None, 10], [[0, 1, 2], 10], [[1, 2], 2], [[0], 8], ] #expected = [[[0, 2], 9], ] #expected = [[None, 10], ] for gridrefinement in [1, 2, 4]: #Test for all gridrefinements for get_all_electron_density parprint('grid refinement', gridrefinement) for result in expected: indicees, result = result full, gd = hd.get_density(indicees, gridrefinement) parprint('indicees', indicees, end=': ') parprint('result, expected:', gd.integrate(full), result) if gridrefinement < 4: #The highest level of gridrefinement gets wrong electron numbers equal(gd.integrate(full), result, 1.e-8) else: equal(gd.integrate(full), result, 1.e-5) hp = HirshfeldPartitioning(calc) vr = hp.get_effective_volume_ratios() parprint('Hirshfeld:', vr) if len(lastres): equal(vr, lastres.pop(0), 1.e-10) results.append(vr) # Wigner-Seitz ---------------------------------------- if 1: ws = WignerSeitz(calc.density.finegd, mol, calc) vr = ws.get_effective_volume_ratios() parprint('Wigner-Seitz:', vr) if len(lastres): equal(vr, lastres.pop(0), 1.e-10) results.append(vr) return results
def initialize(self, paw, allocate=True): BaseInducedField.initialize(self, paw, allocate) assert hasattr(paw, 'time') and hasattr(paw, 'niter'), 'Use TDDFT!' self.time = paw.time self.niter = paw.niter # TODO: remove this requirement assert np.count_nonzero(paw.kick_strength) > 0, \ 'Apply absorption kick before %s' % self.__class__.__name__ # Background electric field self.Fbgef_v = paw.kick_strength # Attach to PAW-type object paw.attach(self, self.interval) # TODO: write more details (folding, freqs, etc) parprint('%s: Attached ' % self.__class__.__name__)
def print_interaction_charge_summary(self): """Print a summary of the atomic charges that are used in the electrostatic interaction between subsystems. """ message = [] for name, subsystem in self.subsystems.iteritems(): message.append("Subsystem \"" + name + "\":") for i_atom, atom in enumerate(subsystem.atoms_for_interaction): symbol = atom.symbol charge = atom.charge message.append(" Number: " + str(i_atom) + ", Symbol: " + symbol + ", Charge: " + str(charge)) message.append("") str_message = style_message("HYBRIDCALCULATOR SUMMARY OF CHARGES USED IN INTERACTIONS", message) parprint(str_message)
def update(self): # Update time self.time = self.paw.time time_step = self.paw.time_step # Complex exponential with envelope f_w = np.exp(1.0j * self.omega_w * self.time) * \ self.envelope(self.time) * time_step # Time-dependent quantities n_G = (-1.0) * self.fdtd.classical_material.charge_density * self.fdtd.classical_material.sign # Update Fourier transforms for w in range(self.nw): self.Fn_wsG[w] += (n_G - self.n0_G) * f_w[w] # Restart file if self.restart_file is not None and \ self.niter % self.paw.dump_interval == 0: self.write(self.restart_file) parprint('%s: Wrote restart file %s' % (self.__class__.__name__, self.restart_file))
def print_energy_summary(self): """Print a detailed summary of the different energies in the system. This includes the energies in the subsystems, interaction energies and possible energy corrections. """ message = [] message.append("Total energy: "+str(self.potential_energy)) message.append("") for name, subsystem in self.subsystems.iteritems(): message.append("Subsystem \"" + name + "\":") if subsystem.potential_energy is None: ss_energy = "Not calculated" else: ss_energy = str(subsystem.potential_energy) message.append(" Potential energy: " + ss_energy) message.append("") for pair, interaction in self.subsystem_interactions.iteritems(): message.append("Interaction between \""+pair[0]+"\" and \""+pair[1] + ":") # Total interaction energy if interaction.interaction_energy is None: b_energy = "Not calculated" else: b_energy = str(interaction.interaction_energy) message.append(" Total interaction energy: "+b_energy) # Link atom correction energy if interaction.link_atom_correction_energy is None: link_atom_correction_energy = "Not calculated" else: link_atom_correction_energy = str(interaction.link_atom_correction_energy) message.append(" Link atom correction energy: "+link_atom_correction_energy) str_message = style_message("HYBRIDCALCULATOR ENERGY SUMMARY", message) parprint(str_message)
def update(self): # Update time self.time = self.paw.time time_step = self.paw.time_step # Complex exponential with envelope f_w = np.exp(1.0j * self.omega_w * self.time) * \ self.envelope(self.time) * time_step # Time-dependent quantities nt_sG = self.density.nt_sG D_asp = self.density.D_asp # Update Fourier transforms for w in range(self.nw): self.Fnt_wsG[w] += (nt_sG - self.n0t_sG) * f_w[w] for a, D_sp in D_asp.items(): self.FD_awsp[a][w] += (D_sp - self.D0_asp[a]) * f_w[w] # Restart file if self.restart_file is not None and \ self.niter % self.paw.dump_interval == 0: self.write(self.restart_file) parprint('%s: Wrote restart file' % self.__class__.__name__)
h = 0.3 s = Cluster(molecule("H2O")) s.minimal_box(3.0, h) gpwname = "H2O_h" + str(h) + ".gpw" try: # XXX check why this fails in parallel calc = GPAW(gpwname + "failsinparallel", txt=None) atoms = calc.get_atoms() calc.density.set_positions(atoms.get_scaled_positions() % 1.0) calc.density.interpolate_pseudo_density() calc.density.calculate_pseudo_charge() except IOError: calc = GPAW(h=h, charge=0, txt=None) calc.calculate(s) calc.write(gpwname) dipole_c = calc.get_dipole_moment() parprint("Dipole", dipole_c) center = np.array([1, 1, 1]) * 50.0 mp = Multipole(center, calc, lmax=2) q_L = mp.expand(-calc.density.rhot_g) parprint("Multipole", q_L) # The dipole moment is independent of the center equal(dipole_c[2], q_L[2], 1e-10) mp.to_file(calc, mode="w")
if 1: # test ZeroKelvin vs FixedOccupations c = GPAW(h=h, nbands=nbands, occupations=ZeroKelvin(True), convergence=convergence, txt=txt) H2.set_calculator(c) E_zk = H2.get_potential_energy() c = GPAW(h=h, nbands=nbands, occupations=FixedOccupations([[2, 0]]), convergence=convergence, txt=txt) H2.set_calculator(c) E_fo = H2.get_potential_energy() parprint(E_zk, E_fo) equal(E_zk, E_fo, 1.e-10) if 1: # test spin-paired vs spin-polarized c = GPAW(h=h, nbands=nbands, occupations=FixedOccupations([[1,1]]), convergence=convergence, txt=txt) H2.set_calculator(c) E_ns = H2.get_potential_energy() if 1: c = GPAW(h=h, nbands=nbands, spinpol=True, occupations=FixedOccupations([[0.5, 0.5]] * 2), convergence=convergence, txt=txt)
print(np.round(crk.C*10)/10) # Get parameter used for fitting crack tip position residual_func = parameter('residual_func', crack.displacement_residual) _residual_func = residual_func tip_tol = parameter('tip_tol', 1e-4) tip_mixing_alpha = parameter('tip_mixing_alpha', 1.0) write_trajectory_during_optimization = parameter('write_trajectory_during_optimization', False) # Get Griffith's k1. k1g = crk.k1g(params.surface_energy) parprint('Griffith k1 = %f' % k1g) # Apply initial strain field. tip_x = parameter('tip_x', cryst.cell.diagonal()[0]/2) tip_y = parameter('tip_y', cryst.cell.diagonal()[1]/2) bondlength = parameter('bondlength', 2.7) a = cryst.copy() a.set_pbc([False, False, True]) ux, uy = crk.displacements(cryst.positions[:,0], cryst.positions[:,1], tip_x, tip_y, params.k1*k1g) a.positions[:ncryst,0] += ux a.positions[:ncryst,1] += uy
def summary(self, omega, gamma=0.1, method='standard', direction='central', intensity_unit='(D/A)2/amu', log=sys.stdout): """Print summary for given omega [eV]""" hnu = self.get_energies(method, direction) s = 0.01 * units._e / units._c / units._hplanck intensities = self.get_intensities(omega, gamma) if isinstance(log, str): log = paropen(log, 'a') parprint('-------------------------------------', file=log) parprint(' excitation at ' + str(omega) + ' eV', file=log) parprint(' gamma ' + str(gamma) + ' eV\n', file=log) parprint(' Mode Frequency Intensity', file=log) parprint(' # meV cm^-1 [a.u.]', file=log) parprint('-------------------------------------', file=log) for n, e in enumerate(hnu): if e.imag != 0: c = 'i' e = e.imag else: c = ' ' e = e.real parprint('%3d %6.1f%s %7.1f%s %9.3g' % (n, 1000 * e, c, s * e, c, intensities[n]), file=log) parprint('-------------------------------------', file=log) parprint('Zero-point energy: %.3f eV' % self.get_zero_point_energy(), file=log)
from gpaw.response.g0w0 import G0W0 # We start by setting up a G0W0 calculator object gw = G0W0('Si_gs.gpw', # Path to groundstate gpw file filename='Si_g0w0_ppa', # filename base for output files kpts=None, # List of quasiparticle k-point indices # or None = all k-points bands=(3, 5), # Range of quasiparticle bands - last # index is NOT included ecut=100., # Plane wave basis cut-off energy ppa=True) # Use Plasmon Pole Approximation # Perform the GW calculation. The results, ie. quasiparticle energies, as # well as original Kohn-Sham eigenvalues, occupation numbers, DFT XC and # self-energy contributions and renormalization factors are returned as a # python dictionary object result = gw.calculate() ks_skn = result['eps'] # Get Kohn-Sham eigenvalues ks_cbmin = np.amin(ks_skn[0, :, 1]) # DFT conduction band minimum ks_vbmax = np.amax(ks_skn[0, :, 0]) # DFT valence band maximum ks_gap = ks_cbmin - ks_vbmax # DFT band gap qp_skn = result['qp'] # GW quasiparticle energies qp_cbmin = np.amin(qp_skn[0, :, 1]) # GW conduction band minimum qp_vbmax = np.amax(qp_skn[0, :, 0]) # GW valence band maximum qp_gap = qp_cbmin - qp_vbmax # GW band gap parprint('Kohn-Sham gap = %.3f' % ks_gap) parprint('G0W0 gap = %.3f' % qp_gap)
cell=(a, a, c)) calc = GPAW(xc='PBE', h=0.25, nbands=3, spinpol=False, txt=txt) H2.set_calculator(calc) xc='LDA' lr = LrTDDFT(calc, xc=xc) # excited state with forces accuracy = 0.015 exst = ExcitedState(lr, 0, d=0.01, parallel=2, txt=sys.stdout, ) t0 = time.time() parprint("########### first call to forces --> calculate") forces = exst.get_forces(H2) parprint("time used:", time.time() - t0) for c in range(2): equal(forces[0,c], 0.0, accuracy) equal(forces[1,c], 0.0, accuracy) equal(forces[0, 2] + forces[1, 2], 0.0, accuracy) parprint("########### second call to potential energy --> just return") t0 = time.time() E = exst.get_potential_energy() parprint("E=", E) parprint("time used:", time.time() - t0) t0 = time.time() E = exst.get_potential_energy(H2)
def get_induced_density(self, from_density='comp', gridrefinement=2): paw = self.paw lr = self.lr omega_w = self.omega_w if gridrefinement == 1: gd = self.gd elif gridrefinement == 2: gd = self.density.finegd else: raise NotImplementedError nkss = len(lr.kss) nexcs = len(lr) omega_I = np.empty((nexcs), dtype=float) # C_Iij: weights for each excitation I and KS-pair ij C_Iij = np.zeros((nexcs, nkss), dtype=float) # Calculate C_Iij FIsqfe_ij = np.zeros((nkss), dtype=float) for I, exc in enumerate(lr): omega_I[I] = exc.energy B = 0.0 for ij, ks in enumerate(lr.kss): FIsqfe_ij[ij] = exc.f[ij] * np.sqrt(ks.fij * ks.energy) B += ks.mur[self.kickdir] * FIsqfe_ij[ij] C_Iij[I] = 2 * B * FIsqfe_ij # Fold C_Iij to C_wij # C_wij: weights for each requested frequency w and KS-pair ij self.omega_w, C_wij = self.folder.fold_values(omega_I, C_Iij, omega_w) assert (self.omega_w == omega_w).all() # TODO: remove Fn_wg = gd.zeros((self.nw), dtype=complex) kpt_u = paw.wfs.kpt_u for ij, ks_ in enumerate(lr.kss): # TODO: better output of progress parprint('%d/%d' % (ij, nkss)) # TODO: speedup: # for each w, check magnitude of C_wij and # take C_wij for those ij that contribute most # Take copy so that memory for pair density is released # after each loop iteration ks = ks_.copy() # Initialize pair density kpt = kpt_u[ks.spin] ks.set_paw(paw) ks.initialize(kpt, ks.i, ks.j) # Get pair density # TODO: gridrefinements yes_finegrid = gridrefinement == 2 if from_density == 'pseudo': nij_g = ks.get(finegrid=yes_finegrid) elif from_density == 'comp': nij_g = ks.with_compensation_charges(finegrid=yes_finegrid) elif from_density == 'ae': nij_g = ks.with_ae_corrections(finegrid=yes_finegrid) # TODO: better to split pair density in pseudo density part # and FD_asp etc. coefficients (like in time-propagation). # Then do gridrefinement and add AE/comp corrections afterwards # -> speedup (no need to do summations on fine grid) # TODO: speedup: check magnitude of C_wij (see above) for w in range(self.nw): Fn_wg[w] += nij_g * C_wij[w, ij] # Return charge density (electrons = negative charge) return - Fn_wg, gd
def solve(self, phi, rho, charge=None, eps=None, maxcharge=1e-6, zero_initial_phi=False): if eps is None: eps = self.eps actual_charge = self.gd.integrate(rho) background = (actual_charge / self.gd.dv / self.gd.get_size_of_global_array().prod()) if charge is None: charge = actual_charge if abs(charge) <= maxcharge: # System is charge neutral. Use standard solver return self.solve_neutral(phi, rho - background, eps=eps) elif abs(charge) > maxcharge and self.gd.pbc_c.all(): # System is charged and periodic. Subtract a homogeneous # background charge if self.charged_periodic_correction is None: parprint("""+-----------------------------------------------------+ | Calculating charged periodic correction using the | | Ewald potential from a lattice of probe charges in | | a homogenous background density | +-----------------------------------------------------+""") self.charged_periodic_correction = madelung(self.gd.cell_cv) parprint("Potential shift will be ", self.charged_periodic_correction , "Ha.") # Set initial guess for potential if zero_initial_phi: phi[:] = 0.0 else: phi -= charge * self.charged_periodic_correction iters = self.solve_neutral(phi, rho - background, eps=eps) phi += charge * self.charged_periodic_correction return iters elif abs(charge) > maxcharge and not self.gd.pbc_c.any(): # The system is charged and in a non-periodic unit cell. # Determine the potential by 1) subtract a gaussian from the # density, 2) determine potential from the neutralized density # and 3) add the potential from the gaussian density. # Load necessary attributes self.load_gauss() # Remove monopole moment q = actual_charge / np.sqrt(4 * pi) # Monopole moment rho_neutral = rho - q * self.rho_gauss # neutralized density # Set initial guess for potential if zero_initial_phi: phi[:] = 0.0 else: axpy(-q, self.phi_gauss, phi) #phi -= q * self.phi_gauss # Determine potential from neutral density using standard solver niter = self.solve_neutral(phi, rho_neutral, eps=eps) # correct error introduced by removing monopole axpy(q, self.phi_gauss, phi) #phi += q * self.phi_gauss return niter else: # System is charged with mixed boundaryconditions msg = 'Charged systems with mixed periodic/zero' msg += ' boundary conditions' raise NotImplementedError(msg)
x1 = 1 - x0 y0 = (atoms.positions[0][1] - 1.0) / atoms.get_cell()[1, 1] y1 = 1 - y0 z0 = atoms.positions[1][2] / atoms.get_cell()[2, 2] z1 = atoms.positions[0][2] / atoms.get_cell()[2, 2] gd = calc.wfs.gd Gx0, Gx1 = gd.N_c[0] * x0, gd.N_c[0] * x1 Gy0, Gy1 = gd.N_c[1] * y0, gd.N_c[1] * y1 Gz0, Gz1 = gd.N_c[2] * z0, gd.N_c[2] * z1 finegd = calc.density.finegd gx0, gx1 = finegd.N_c[0] * x0, finegd.N_c[0] * x1 gy0, gy1 = finegd.N_c[1] * y0, finegd.N_c[1] * y1 gz0, gz1 = finegd.N_c[2] * z0, finegd.N_c[2] * z1 int1 = elf_G[Gx0:Gx1, Gy0:Gy1, Gz0:Gz1].sum() * gd.dv int2 = elf_g[gx0:gx1, gy0:gy1, gz0:gz1].sum() * finegd.dv parprint("Ints", int1, int2) parprint("Min, max G", np.min(elf_G), np.max(elf_G)) parprint("Min, max g", np.min(elf_g), np.max(elf_g)) # The tested values (< r7887) do not seem to be correct # equal(int1, 14.8078, 0.0001) # equal(int2, 13.0331, 0.0001) # check spin-polarized version try: atoms, calc = restart("COspin.gpw", txt=None, parallel={"domain": world.size}) energy_spinpol = atoms.get_potential_energy() except: calc.set(spinpol=True, parallel={"domain": world.size}) energy_spinpol = atoms.get_potential_energy() calc.write("COspin.gpw", "all")
def summary(self, method='standard', direction='central', intensity_unit_ir='(D/A)2/amu', intensity_unit_ram='au', log=stdout): hnu = self.get_energies(method, direction) s = 0.01 * units._e / units._c / units._hplanck iu_ir, iu_string_ir = self.intensity_prefactor(intensity_unit_ir) iu_ram, iu_string_ram = self.intensity_prefactor(intensity_unit_ram) arr = [] if intensity_unit_ir == '(D/A)2/amu': iu_format_ir = '%9.4f ' elif intensity_unit_ir == 'km/mol': iu_string_ir = ' ' + iu_string_ir iu_format_ir = ' %7.1f ' elif intensity_unit_ir == 'au': iu_format_ir = '%.6e ' elif intensity_unit_ir == 'A^4 amu^-1': iu_format_ir = '%9.4f ' if intensity_unit_ram == '(D/A)2/amu': iu_format_ram = '%9.4f' elif intensity_unit_ram == 'km/mol': iu_string_ram = ' ' + iu_string_ram iu_format_ram = ' %7.1f' elif intensity_unit_ram == 'au': iu_format_ram = '%.6e ' elif intensity_unit_ram == 'A^4 amu^-1': iu_format_ram = '%9.4f ' if isinstance(log, str): log = paropen(log, 'a') parprint('---------------------------------------------------------------------------------------------------------------------------', file=log) parprint(' Mode Frequency Intensity IR Intensity Raman (real) Intensity Raman (imag) Raman Ehanced', file=log) parprint(' # meV cm^-1 ' + iu_string_ir + ' ' + iu_string_ram + ' ' + iu_string_ram + ' ' + iu_string_ram, file=log) parprint('---------------------------------------------------------------------------------------------------------------------------', file=log) for n, e in enumerate(hnu): if e.imag != 0: c = 'i' e = e.imag else: c = ' ' e = e.real arr.append([n, 1000 * e, s * e, iu_ir * self.intensities_ir[n], iu_ram * self.intensities_ram[n].real, iu_ram * self.intensities_ram[n].imag]) parprint(('%3d %6.1f%s %7.1f%s ' + iu_format_ir + iu_format_ram + iu_format_ram + iu_format_ram) % (n, 1000 * e, c, s * e, c, iu_ir * self.intensities_ir[n], iu_ram * self.intensities_ram[n].real, iu_ram * self.intensities_ram[n].imag, iu_ram * self.intensities_ram_enh[n].real), file=log) parprint( '-----------------------------------------------------------------------------------------', file=log) parprint('Zero-point energy: %.3f eV' % self.get_zero_point_energy(), file=log) parprint('Static dipole moment: %.3f D' % self.dipole_zero, file=log) parprint('Maximum force on atom in `equilibrium`: %.4f eV/Å' % self.force_zero, file=log) parprint(file=log) np.savetxt('ram-summary.txt', np.array(arr))
# Get crack tip position tip_x, tip_y, tip_z = a.info['fitted_crack_tip'] # Set calculator a.set_calculator(params.calc) # Relax positions del a[np.logical_or(a.numbers == atomic_numbers[ACTUAL_CRACK_TIP], a.numbers == atomic_numbers[FITTED_CRACK_TIP])] g = a.get_array('groups') a.set_constraint(ase.constraints.FixAtoms(mask=g==0)) a.set_calculator(params.calc) parprint('Optimizing positions...') opt = ase.optimize.FIRE(a, logfile=None) opt.run(fmax=params.fmax) parprint('...done. Converged within {0} steps.' \ .format(opt.get_number_of_steps())) # Get atomic strain i, j = neighbour_list("ij", a, cutoff=2.85) deformation_gradient, residual = atomic_strain(a, ref, neighbours=(i, j)) # Get atomic stresses virial = a.get_stresses() # Note: get_stresses returns the virial in Atomistica! strain = full_3x3_to_Voigt_6_strain(deformation_gradient) vol_strain, dev_strain, J3_strain = invariants(strain) a.set_array('strain', strain)
def summary(self, method='standard', direction='central', intensity_unit='(D/A)2/amu', log=stdout): hnu = self.get_energies(method, direction) s = 0.01 * units._e / units._c / units._hplanck iu, iu_string = self.intensity_prefactor(intensity_unit) if intensity_unit == '(D/A)2/amu': iu_format = '%9.4f' elif intensity_unit == 'km/mol': iu_string = ' ' + iu_string iu_format = ' %7.1f' if isinstance(log, str): log = paropen(log, 'a') parprint('-------------------------------------', file=log) parprint(' Mode Frequency Intensity', file=log) parprint(' # meV cm^-1 ' + iu_string, file=log) parprint('-------------------------------------', file=log) for n, e in enumerate(hnu): if e.imag != 0: c = 'i' e = e.imag else: c = ' ' parprint(('%3d %6.1f%s %7.1f%s ' + iu_format) % (n, 1000 * e, c, s * e, c, iu * self.intensities[n]), file=log) parprint('-------------------------------------', file=log) parprint('Zero-point energy: %.3f eV' % self.get_zero_point_energy(), file=log) parprint('Static dipole moment: %.3f D' % self.dipole_zero, file=log) parprint('Maximum force on atom in `equilibrium`: %.4f eV/Å' % self.force_zero, file=log) parprint(file=log)
if 1: c = GPAW(xc="PBE", nbands=-1, h=h) s = Cluster([Atom("H")]) s.minimal_box(box, h=h) c.calculate(s) c.write(gpwname, "all") else: c = GPAW(gpwname) s = c.get_atoms() c.converge_wave_functions() cm = s.get_center_of_mass() Ekin = 1.0 ekin = Ekin / Ha for form, title in [("L", "length form"), ("V", "velocity form")]: parprint("--", title) ds = [] for analytic in [True, False]: if analytic: initial = H1s(c.density.gd, cm) else: initial = BoundState(c, 0, 0) initial.set_energy(-Ha / 2.0) csb = CrossSectionBeta(initial=initial, final=None, r0=cm, ngauss=ngauss, form=form) if analytic: ds.append(initial.get_ds(Ekin, form)) parprint("analytic 1s energy, beta, ds %5.3f" % (Ekin + Ha / 2.0), end="") parprint("%8.4f %12.5f" % (2, ds[-1])) ds.append(csb.get_ds(Ekin)) parprint("numeric 1s energy, beta, ds %5.3f" % (Ekin + Ha / 2.0), end="")
def summary(self, method='standard', direction='central', intensity_unit='(D/A)2/amu'): hnu = self.get_energies(method, direction) s = 0.01 * units._e / units._c / units._hplanck if intensity_unit == '(D/A)2/amu': iu = 1.0 iu_string = '(D/Å)^2 amu^-1' iu_format = '%9.4f' elif intensity_unit == 'km/mol': # conversion factor from Porezag PRB 54 (1996) 7830 iu = 42.255 iu_string = ' km/mol' iu_format = ' %7.1f' else: raise RuntimeError('Intensity unit >' + intensity_unit + '< unknown.') parprint('-------------------------------------') parprint(' Mode Frequency Intensity') parprint(' # meV cm^-1 ' + iu_string) parprint('-------------------------------------') for n, e in enumerate(hnu): if e.imag != 0: c = 'i' e = e.imag else: c = ' ' parprint(('%3d %6.1f%s %7.1f%s ' + iu_format) % (n, 1000 * e, c, s * e, c, iu * self.intensities[n])) parprint('-------------------------------------') parprint('Zero-point energy: %.3f eV' % self.get_zero_point_energy()) parprint('Static dipole moment: %.3f D' % self.dipole_zero) parprint('Maximum force on atom in `equilibrium`: %.4f eV/Å' % self.force_zero) parprint()
# Wigner-Seitz ---------------------------------------- if 1: ws = WignerSeitz(calc.density.finegd, mol, calc) vr = ws.get_effective_volume_ratios() parprint('Wigner-Seitz:', vr) if len(lastres): equal(vr, lastres.pop(0), 1.e-10) results.append(vr) return results # calculate parprint('fresh:') mol = Cluster(molecule('H2O')) mol.minimal_box(3, h=h) calc = GPAW(nbands=6, h = h, txt=None) calc.calculate(mol) calc.write(gpwname) lastres = run() # load previous calculation parprint('reloaded:') calc = GPAW(gpwname, txt=None) mol = calc.get_atoms() run(lastres)
xco = HybridXC(xc) cocc = GPAW(h=0.3, eigensolver="rmm-diis", xc=xco, nbands=nbands, convergence={"eigenstates": 1e-4}, txt=txt) cocc.calculate(loa) else: cocc = GPAW(fname) cocc.converge_wave_functions() fo_n = 1.0 * cocc.get_occupation_numbers() eo_n = 1.0 * cocc.get_eigenvalues() if unocc: # apply Fock opeartor also to unoccupied orbitals xcu = HybridXC(xc, unocc=True) cunocc = GPAW(h=0.3, eigensolver="rmm-diis", xc=xcu, nbands=nbands, convergence={"eigenstates": 1e-4}, txt=txt) cunocc.calculate(loa) parprint(" HF occ HF unocc diff") parprint( "Energy %10.4f %10.4f %10.4f" % ( cocc.get_potential_energy(), cunocc.get_potential_energy(), cocc.get_potential_energy() - cunocc.get_potential_energy(), ) ) equal(cocc.get_potential_energy(), cunocc.get_potential_energy(), 1.0e-4) fu_n = cunocc.get_occupation_numbers() eu_n = cunocc.get_eigenvalues() parprint("Eigenvalues:") for eo, fo, eu, fu in zip(eo_n, fo_n, eu_n, fu_n):
h = 0.3 s = Cluster(molecule('H2O')) s.minimal_box(3., h) gpwname = 'H2O_h' + str(h) + '.gpw' try: # XXX check why this fails in parallel calc = GPAW(gpwname + 'failsinparallel', txt=None) atoms = calc.get_atoms() calc.density.set_positions(atoms.get_scaled_positions() % 1.0) calc.density.interpolate_pseudo_density() calc.density.calculate_pseudo_charge() except IOError: calc = GPAW(h=h, charge=0, txt=None) calc.calculate(s) calc.write(gpwname) dipole_c = calc.get_dipole_moment() parprint('Dipole', dipole_c) center = np.array([1,1,1]) * 50. mp = Multipole(center, calc, lmax=2) q_L = mp.expand(-calc.density.rhot_g) parprint('Multipole', q_L) # The dipole moment is independent of the center equal(dipole_c[2], q_L[2], 1e-10) mp.to_file(calc, mode='w')
c = GPAW(gpwname) s = c.get_atoms() c.converge_wave_functions() cm = s.get_center_of_mass() Ekin = 1. ekin = Ekin / Ha for form in ['L', 'V']: ds = [] for analytic in [True, False]: if analytic: initial = H1s(c.density.gd, cm) else: initial = BoundState(c, 0, 0) initial.set_energy(-Ha / 2.) csb = CrossSectionBeta( initial=initial, final=None, r0=cm, ngauss=ngauss, form=form) if analytic: ds.append(initial.get_ds(Ekin, form)) parprint('%5.3f' % (Ekin + Ha / 2.), end='') parprint('%7.4f %12.5f' % (2, ds[-1])) ds.append(csb.get_ds(Ekin)) parprint('%5.3f' % (Ekin + Ha / 2.), end='') parprint('%7.4f %12.5f' % (csb.get_beta(Ekin), ds[-1])) parprint('error analytic GS:', int(100 * abs(ds[1] / ds[0] - 1.) + .5), '%') assert (abs(ds[1] / ds[0] - 1.) < 0.31) parprint('error numeric GS:', int(100 * abs(ds[2] / ds[0] - 1.) + .5), '%') assert (abs(ds[2] / ds[0] - 1.) < 0.2)
import matscipy.fracture_mechanics.crack as crack ### sys.path += [ "." ] import params ### crack = crack.CubicCrystalCrack(params.C11, params.C12, params.C44, params.crack_surface, params.crack_front) # Get Griffith's k1. k1g = crack.k1g(params.surface_energy) parprint('Griffith k1 = %f' % k1g) # Compute crack tip position. if hasattr(params, 'tip_x0'): tip_x0 = params.tip_x0 else: tip_x0 = params.cryst.cell.diagonal()[0]/2 if hasattr(params, 'tip_y0'): tip_y0 = params.tip_y0 else: tip_y0 = params.cryst.cell.diagonal()[2]/2 cryst = params.cryst.copy() a = cryst.copy() old_k1 = params.k1[0] ux, uy = crack.displacements(cryst.positions[:,0], cryst.positions[:,1],
# split the structures s1 = ss.find_connected(0) s2 = ss.find_connected(-1) assert len(ss) == len(s1) + len(s2) c = GPAW(xc='PBE', h=h, nbands=-6, occupations=FermiDirac(width=0.1), txt=None) cdf = GPAW(xc='vdW-DF', h=h, nbands=-6, occupations=FermiDirac(width=0.1), txt=None) for s in [s1, s2, ss]: s.set_calculator(c) s.minimal_box(box, h=h) Energy['PBE'].append(s.get_potential_energy()) cc = vdWTkatchenko09prl(HirshfeldPartitioning(c), vdWradii(s.get_chemical_symbols(), 'PBE')) s.set_calculator(cc) Energy['TS09'].append(s.get_potential_energy()) s.set_calculator(cdf) Energy['vdW-DF'].append(s.get_potential_energy()) parprint('Coupled cluster binding energy', -data[molecule]['interaction energy CC'] * 1000, 'meV') for xc in ['PBE', 'vdW-DF', 'TS09']: ene = Energy[xc] # print xc, 'energies', ene parprint(xc, 'binding energy', (ene[0] + ene[1] - ene[2]) * 1000, 'meV')
xc='LDA' # without spin lr = LrTDDFT(calc, xc=xc) lr.diagonalize() t1 = lr[0] lr_calc = lr ex = ExcitedState(lr, 0) den = ex.get_pseudo_density() * Bohr**3 # course grids for finegrid in [1,0]: lr = LrTDDFT(calc, xc=xc, finegrid=finegrid) lr.diagonalize() t3 = lr[0] parprint('finegrid, t1, t3=', finegrid, t1 ,t3) equal(t1.get_energy(), t3.get_energy(), 5.e-4) # with spin lr_vspin = LrTDDFT(calc, xc=xc, nspins=2) singlet, triplet = lr_vspin.singlets_triplets() lr_vspin.diagonalize() # the triplet is lower, so that the second is the first singlet # excited state t2 = lr_vspin[1] ex_vspin = ExcitedState(lr_vspin, 1) den_vspin = ex_vspin.get_pseudo_density() * Bohr**3 parprint('with virtual/wo spin t2, t1=', t2.get_energy(), t1 .get_energy())
name = 'zero bc' calc = GPAW(h=0.25, nbands=4, mode=mode, eigensolver=eigensolver, txt=txt) Be.set_calculator(calc) Be.get_potential_energy() kss = KSSingles(calc) # all s->p transitions at the same energy [Ha] and # oscillator_strength for ks in kss: equal(ks.get_energy(), kss[0].get_energy(), 1.e-4) equal(ks.get_oscillator_strength()[0], kss[0].get_oscillator_strength()[0], 1.e-3) energy[name] = np.array( [ks.get_energy() * Hartree for ks in kss]).mean() osz[name] = np.array( [ks.get_oscillator_strength()[0] for ks in kss]).sum() parprint(kss) # I/O kss.write('kss.dat') mpi.world.barrier() kss = KSSingles('kss.dat') kss1 = KSSingles('kss.dat', jend=1) assert(len(kss1) == 1) # periodic and non-periodic should be roughly equal equal(energy['zero bc'], energy['periodic'], 1.e-2) equal(osz['zero bc'], osz['periodic'], 1.e-3)