def test_get_eigenvalues(file_path): """ Test get eigenvalues function """ base_path = file_path("/gec-2d/") factory = Vasp() eigenvalues = factory.get_eigenvalues(base_path=base_path) assert np.isclose(eigenvalues[4][3], -5.397776)
def test_get_runner(): """ Test get vasp runner class """ command = ['mpirun', '-np', '4', 'vasp-FEB2016'] factory = Vasp() runner = factory.get_runner(command) assert isinstance(runner, VaspRunner)
def test_get_number_of_bands(file_path): """ Test get number of bands function """ base_path = file_path("/gec-2d/") factory = Vasp() bands_num = factory.get_number_of_bands(base_path=base_path) assert bands_num == 16
def test_get_number_of_kpoints(file_path): """ Test get number of kpoints function """ base_path = file_path("/gec-2d/") factory = Vasp() kpoints_num = factory.get_number_of_kpoints(base_path=base_path) assert kpoints_num == 12
def test_get_fermi_energy(file_path): """ Test get fermi energy function """ base_path = file_path("/gec-2d/") factory = Vasp() fermi_energy = factory.get_fermi_energy(base_path=base_path) assert np.isclose(-3.17131785, fermi_energy)
def test_get_potential_class(file_path): """ Test get potential class function """ base_path = file_path("/H/") factory = Vasp() potential_class = factory.get_potential_class(base_path=base_path) assert isinstance(potential_class, Potcar)
def test_get_nearest_neighbor_distance(file_path): """ Test get nearest neighbor distance function """ base_path = file_path("/sic-2d/") factory = Vasp() distance = factory.get_nearest_neighbor_distance(ion_index="1", base_path=base_path) assert np.isclose(distance, 1.78)
def test_get_band_projection_class(file_path): """ Test get band projection class function """ base_path = file_path("/gec-2d/") factory = Vasp() band_projection_class = factory.get_band_projection_class( base_path=base_path) assert isinstance(band_projection_class, Procar)
def test_get_atoms_map(file_path): """ Test get atoms map function """ base_path = file_path("/gec-2d/") factory = Vasp() atoms_map = factory.get_atoms_map(base_path=base_path) assert atoms_map["1"] == "Ge" assert atoms_map["2"] == "C"
def test_get_number_of_equal_neighbors(file_path): """ Test get number of equal neighbors """ base_path = file_path("/sic-2d/") factory = Vasp() fake_atoms_map = {"1": "Si", "2": "Si"} real_atoms_map = {"1": "Si", "2": "C"} assert factory.get_number_of_equal_neighbors(fake_atoms_map, symbol="Si", base_path=base_path) == 1 assert factory.get_number_of_equal_neighbors(real_atoms_map, symbol="Si", base_path=base_path) == 0
def band_gap(software: str, base_path: str) -> None: """Uses output files from softwares that perform ab initio calculations to provide the locations of VBM, CBM and the Gap value in electronvolts.The names of the files required for each software are listed below, it is worth mentioning that their names cannot be modified. VASP: PROCAR, EIGENVAL, vasprun.xml """ welcome_message("minushalf") softwares = {"VASP": Vasp()} factory = softwares[software.upper()] eigenvalues = factory.get_eigenvalues(base_path=base_path) fermi_energy = factory.get_fermi_energy(base_path=base_path) atoms_map = factory.get_atoms_map(base_path=base_path) num_bands = factory.get_number_of_bands(base_path=base_path) band_projection_file = factory.get_band_projection_class( base_path=base_path) band_structure = BandStructure(eigenvalues, fermi_energy, atoms_map, num_bands, band_projection_file) gap_report = band_structure.band_gap() click.echo(gap_report["vbm"]) click.echo(gap_report["cbm"]) click.echo("Gap: {:.3f}eV".format(gap_report["gap"])) end_message()
def cbm_character(software: str, base_path: str) -> None: """Uses output files from softwares that perform ab initio calculations to discover the first conduction band (CBM) and extract, in percentage, its character corresponding to each orbital type (s, p, d, ... ). The names of the files required for each software are listed below, it is worth mentioning that their names cannot be modified. VASP: PROCAR, EIGENVAL, vasprun.xml """ welcome_message("minushalf") softwares = {"VASP": Vasp()} factory = softwares[software.upper()] eigenvalues = factory.get_eigenvalues(base_path=base_path) fermi_energy = factory.get_fermi_energy(base_path=base_path) atoms_map = factory.get_atoms_map(base_path=base_path) num_bands = factory.get_number_of_bands(base_path=base_path) band_projection_file = factory.get_band_projection_class( base_path=base_path) band_structure = BandStructure(eigenvalues, fermi_energy, atoms_map, num_bands, band_projection_file) cbm_projection = band_structure.cbm_projection() normalized_df = projection_to_df(cbm_projection) click.echo(normalized_df.to_markdown()) end_message()
def test_create_bandstrutcture_gan_3d(file_path): """ Tests create method for GaN 3d """ software_module = Vasp() band_structure = BandStructure.create(software_module, file_path("/gan-3d/")) assert isinstance(band_structure, BandStructure) assert band_structure.is_metal() is False
def test_create_bandstrutcture_bn_2d(file_path): """ Tests create method for BN 2d """ softare_module = Vasp() kpoint_vbm = 24 band_vbm = 4 band_structure = BandStructure.create(softare_module, file_path("/bn-2d/")) vbm_index = band_structure.vbm_index() assert isinstance(band_structure, BandStructure) assert vbm_index[0] == kpoint_vbm assert vbm_index[1] == band_vbm
def correct_potfile( quiet: bool, base_potfile_path: str, vtotal_path: str, vtotal_occupied_path: str, software: str, correction: str, cut: str, amplitude: float, ) -> None: """Generate the occupied atomic potential file used for ab initio calculations. Requires: VTOTAL.ae: potential of the atom with all electrons VTOTAL_OCC: potential of the occupied atom INP_OCC: Input file for the run-atomic command of the occupied atom The command also needs the potential files used by the chosen software: VASP: POTCAR (This name can't be changed) Generates: POTFILEcut${CUT_VALUE} (If amplitude is equal to 1.0) POTFILEcut${CUT_VALUE}A${AMPLITUDE_VALUE} (If amplitude is different from 1.0) """ welcome_message("minushalf") if quiet: logger.remove() logger.add(sys.stdout, level="ERROR") softwares = {"VASP": Vasp()} factory = softwares[software.upper()] vtotal = Vtotal.from_file(vtotal_path) vtotal_occ = Vtotal.from_file(vtotal_occupied_path) potential_file = factory.get_potential_class(base_path=base_potfile_path) atomic_potential = AtomicPotential(vtotal, vtotal_occ, potential_file) cut_numbers = parse_cut(cut) is_conduction = False if correction.upper() == "CONDUCTION": is_conduction = True for new_cut in cut_numbers: logger.info("Correcting POTFILE for cut = {:.2f} a.u".format(new_cut)) new_potential = atomic_potential.correct_potential( new_cut, amplitude, is_conduction) atomic_potential.correct_file(new_potential, new_cut, amplitude, is_conduction) end_message()
def execute(quiet: bool): """ Uses the Nelder-Mead method to find the optimal values for the CUT(S) and, finally, find the corrected Gap value. This command uses external software to perform ab initio calculations, so it must be installed in order to perform the command. Check the docs for an list of the softwares supported by the CLI. Requires: minushalf.yaml : Parameters file. Check the docs for a more detailed description. ab_initio_files: Files needed to perform the ab initio calculations. They must be in the same directory as the input file minushalf.yaml potential_folder: Folder with the potential files for each atom in the crystal. The files must be named in the following pattern ${POTENTIAL_FILE_NAME}.${LOWERCASE_CHEMICAL_SYMBOL} Returns: minushalf_results.dat : File that contains the optimal values of the cuts and the final value of the Gap. corrected_valence_potfiles: Potential files corrected with opti-mum valence cuts. corrected_conduction_potfiles: Potential files corrected with optimum conduction cuts. """ welcome_message("minushalf") if quiet: logger.remove() logger.add(sys.stdout, level="ERROR") ## Read yaml file logger.info("Reading minushalf.yaml file") minushalf_yaml = MinushalfYaml.from_file() correction_factory_chooser = {Softwares.vasp.value: DFTCorrection} software_factory_chooser = {Softwares.vasp.value: Vasp()} software_name = minushalf_yaml.get_software_name() correction = correction_factory_chooser[software_name] software_factory = software_factory_chooser[software_name] ## Makes abinition calculation logger.info("Running ab initio calculations") software_configurations = minushalf_yaml.get_software_configurations_params( ) runner = software_factory.get_runner(**software_configurations) runner.run() ## Makes root folder logger.info("Make potfiles folder") root_folder = "mkpotfiles" if os.path.exists(root_folder): shutil.rmtree(root_folder) os.mkdir(root_folder) ## get atoms list logger.info("Get atoms list") atoms = get_atoms_list(software_factory) ## amplitude logger if not np.isclose(minushalf_yaml.get_amplitude(), CorrectionDefaultParams.amplitude.value): logger.warning( "Amplitude value is different from 1.0. This is not recommended unless you know exactly what you are doing." ) valence_options = get_valence_correction_params(minushalf_yaml, software_factory, atoms=atoms, runner=runner, root_folder=root_folder) conduction_options = get_conduction_correction_params( minushalf_yaml, software_factory, atoms=atoms, runner=runner, root_folder=root_folder) correction_code = minushalf_yaml.get_correction_code() logger.info("Doing corrections") gap = None valence_cuts = None conduction_cuts = None if "v" in correction_code: valence_correction = correction(**valence_options) valence_cuts, valence_gap = valence_correction.execute() gap = valence_gap make_minushalf_results(valence_cuts=valence_cuts, gap=valence_gap) if "c" in correction_code: conduction_correction = correction(**conduction_options) conduction_cuts, conduction_gap = conduction_correction.execute() gap = conduction_gap make_minushalf_results(valence_cuts=valence_cuts, gap=gap, conduction_cuts=conduction_cuts) end_message()