def is_executing(self): """Returns True if the most recently added configurations are in process of being executed. """ is_executing = False if len(self.configs) != self.nconfigs: # There have been configurations added to the database # that haven't been setup yet. return False else: # check if the last iteration is empty. if self.last_config_atoms is None: return False # We only want to know if the last iteration's files are # being executed, the old iterations don't matter. for config in self.last_iteration.values(): try: atoms = Atoms(path.join(config, "pre_comp_atoms.h5")) except: atoms = Atoms(path.join(config, "atoms.h5")) is_executing = atoms.calc.is_executing(config) if is_executing: break return is_executing
def test_Atoms_copy_from_aseAtoms(): """Tests the mothed Atoms.copy_from() to copy from an ase.atoms """ from ase.atoms import Atoms as aseAtoms from matdb.atoms import Atoms from numpy import array_equal at1 = aseAtoms("Co3W2V3",positions=[[0,0,0],[0.25,0.25,0.25],[0.5,0.5,0],[1.75,1.75,1.25], [1.5,1,1.5],[2.75,2.25,2.75],[2,2.5,2.5],[2.25,2.75,2.75]], cell=[5.43,5.43,5.43]) at1.info['nneightol'] = 1112 at1.info['cutoff'] = 521 at1.info['cutoff_break'] = 1042 at2 = Atoms() at2.copy_from(at1) assert at2.info["params"]['nneightol'] == at1.info['nneightol'] assert at2.info["params"]['cutoff'] == at1.info['cutoff'] assert at2.info["params"]['cutoff_break'] == at1.info['cutoff_break'] # make sure the symbols and positions are still match assert at1.get_chemical_symbols() == at2.get_chemical_symbols() assert array_equal(at1.positions, at2.positions) assert array_equal(at1.cell, at2.cell)
def test_recursive_convert_atom_list(): """Tests the recursive unit conversion. """ from matdb.atoms import _recursively_convert_units, Atoms import numpy at1 = Atoms("Si8",positions=[[0,0,0],[0.25,0.25,0.25],[0.5,0.5,0],[0.75,0.75,0.25], [0.5,0,0.5],[0.75,0.25,0.75],[0,0.5,0.5],[0.25,0.75,0.75]], cell=[5.43,5.43,5.43],info={"rand":10}) at2 = Atoms("S6",positions=[[0,0,0],[0.25,0.25,0.25],[0.5,0.5,0],[0.75,0.75,0.25], [0.5,0,0.5],[0.75,0.25,0.75]], cell=[6.43,5.43,4.43],info={"rand":10}) at3 = Atoms("CNi",positions=[[0,0,0],[0.5,0.5,0.5]], info={"rand":8}) dict_in = {"a":10, "b":[at1, at2, at3]} test = _recursively_convert_units(dict_in, True) assert len(test["b"]) == 3 assert isinstance(test["b"], dict) test = _recursively_convert_units(dict_in) assert len(test["b"]) == 3 assert isinstance(test["b"], numpy.ndarray)
def test_objupdate(): """Tests the obj_update method in utility. """ from matdb.atoms import Atoms from matdb.utility import obj_update al = Atoms("Si",positions=[[0,0,0]]) k = "positions" al = obj_update(al,k,[[0.5,0.5,0.5]]) assert np.allclose(al.positions,[[0.5,0.5,0.5]]) al = Atoms("Si",positions=[[0,0,0]]) c = Atoms("C",positions=[[0,0,0]]) k = "Si.positions" temp = [{"Si":al},{"c":c}] temp = obj_update(temp,k,[[0.5,0.5,0.5]]) assert np.allclose(temp[0]["Si"].positions,[[0.5,0.5,0.5]]) al = Atoms("Si",positions=[[0,0,0]]) temp = {"Si":[[0,0,0]]} k = "Si" temp = obj_update(temp,k,[[0.5,0.5,0.5]],copy=False) assert np.allclose(temp["Si"],[[0.5,0.5,0.5]])
def test_Atoms_get_energy(): """Tests get_energy method. """ from matdb.atoms import Atoms at1 = Atoms("Si8",positions=[[0,0,0],[0.25,0.25,0.25],[0.5,0.5,0],[0.75,0.75,0.25], [0.5,0,0.5],[0.75,0.25,0.75],[0,0.5,0.5],[0.25,0.75,0.75]], cell=[5.43,5.43,5.43]) at1.add_param("vasp_energy", 4532) assert at1.get_energy() == 4532
def test_make_supercell(): """Tests make_supercell method. """ from matdb.atoms import Atoms supercell=(1, 1, 1) atSi = Atoms("Si8",positions=[[0,0,0],[0.25,0.25,0.25],[0.5,0.5,0],[0.75,0.75,0.25], [0.5,0,0.5],[0.75,0.25,0.75],[0,0.5,0.5],[0.25,0.75,0.75]], cell=[5.43,5.43,5.43]) scell = atSi.make_supercell(supercell) assert scell is not None assert isinstance(scell, Atoms)
def vasp_to_xyz(folder, outfile="output.xyz", recalc=0, properties=["species", "pos", "z", "dft_force"], parameters=["dft_energy", "dft_virial"], config_type=None): """Creates an extended XYZ file for the calculated structure in OUTCAR for the given folder. Args: folder (str): path to the folder to convert. outfile (str): name of the XYZ file to create. The file will be created in the same folder as the original if no absolute path is given. recalc (bool): when True, re-convert the OUTCAR file, even if the target XYZ file already exists. """ from matdb.atoms import Atoms if not path.isabs(outfile): #Convert to absolute path if one wasn't given. outfile = path.join(folder, outfile) if (path.isfile(outfile) and stat(outfile).st_size > 100 and recalc <= 0): return True p = ','.join(properties) P = ','.join(parameters) renames = [("energy", "vasp_energy"), ("force", "vasp_force"), ("virial", "vasp_virial")] sargs = ["convert.py", "-I", "vasprun.xml", "-p", p, "-P", P, "-f", "xyz"] for s, d in renames: sargs.append("-n") sargs.append(s) sargs.append(d) sargs.extend(["-o", outfile, "vasprun.xml"]) from matdb.utility import execute execute(sargs, folder, errignore="OMP_STACKSIZE") if config_type is not None: #We need to load the XYZ file, add the config_type parameter and then #save it again. The -e parameter of convert.py should save this, but in #our experiments, it doesn't :(. a = Atoms(outfile) a.params["config_type"] = config_type a.write(outfile) return path.isfile(outfile) and stat(outfile).st_size > 100
def test_remote_read(tmpdir): """Tests the reading in of a atoms.h5 file from another directory.""" from matdb.atoms import Atoms from matdb.utility import _set_config_paths, reporoot from os import path _set_config_paths("AgPd_Enumerated", str(tmpdir)) target = str(tmpdir.join("to_hdf5")) globals_setup(target) at = Atoms() at.read(target=path.join(reporoot, "tests", "files", "test.h5")) assert isinstance(at, Atoms)
def test_safeupdate(): """Tests the safe_update method in utility. """ from matdb.atoms import Atoms from matdb.utility import safe_update al = Atoms("Si",positions=[[0,0,0]]) al.add_param("energy",None) kv = {"positions":[[0.5,0.5,0.5]],"energy":10} safe_update(al,kv) assert np.allclose(al.positions,[[0,0,0]]) assert al.energy == 10
def _setup_configs(self, rerun): """Displaces the seed configuration preparatory to calculating the force sets for phonon spectra. .. note:: This method *appears* to be VASP-specific. However, the configurations that are generated by `phonopy` as VASP `POSCAR` files are turned into :class:`~matdb.atoms.Atoms` objects before they are passed to the super class that sets up the actual calculations. So, it is quite general. Args: rerun (int): when > 1, recreate the folders even if they already exist. If > 0, recreate the jobfile. """ #We also don't want to setup again if we have the results already. if self.ready() and rerun == 0: return if not self.is_setup() or rerun > 1: from ase.io import write write(path.join(self.phonodir, "POSCAR"), self.atoms, "vasp") scell = ' '.join(map(str, self.supercell)) sargs = ["phonopy", "-d", '--dim="{}"'.format(scell)] pres = execute(sargs, self.phonodir, venv=True) #Make sure that phonopy produced the supercell. If it didn't, it #should have printed an error to *stdout* because it doesn't know #about stderr... if not path.isfile(path.join(self.phonodir, "SPOSCAR")): msg.err('\n'.join(pres["output"])) from matdb.atoms import Atoms if not self.dfpt: #Frozen phonons, create a config execution folder for each of #the displacements. from glob import glob with chdir(self.phonodir): for dposcar in glob("POSCAR-*"): dind = int(dposcar.split('-')[1]) datoms = Atoms(dposcar, format="vasp") self.create(datoms) else: #Pull the perfect supercell and set it up for executing with #DFPT parameters. with chdir(self.phonodir): datoms = Atoms("SPOSCAR", format="vasp") self.create(datoms) # Last of all, create the job file to execute the job array. self.jobfile(rerun)
def test_can_execute(tmpdir): """Tests the can_execute method. """ from matdb.utility import _set_config_paths _set_config_paths("AgPd_Enumerated", str(tmpdir)) target = str(tmpdir.join("Vasp")) globals_setup(target) atm = Atoms("Si", positions=[[0, 0, 0]], cell=[[1, 0, 0], [0, 1, 0], [0, 0, 1]]) kwargs = { "kpoints": { "method": "mueller", "mindistance": 50 }, "potcars": { "directory": "./tests/vasp", "xc": "pbe", "versions": { "Si": '05Jan2001' } } } calc = Vasp(atm, target, str(tmpdir), 0, **kwargs) assert not calc.can_execute(target) calc.write_input(atm, directory=target) assert not calc.can_execute("def") assert calc.can_execute(target)
def setup(self, rerun=False): """Sets up a DFT folder for each of the subsampled configurations in the base MD database. Args: rerun (bool): when True, recreate the job file. If the folders don't exist yet, they will still be created. """ if not self.mdbase.ready(): return folders_ok = super(LiquidGroup, self).setup() if folders_ok and not rerun: return #We also don't want to setup again if we have the results already. if self.ready(): return if not folders_ok: from matdb.atoms import Atoms from tqdm import tqdm with open(self.mdbase.subsamples) as f: for line in tqdm(f): config = line.strip() datoms = Atoms(config, format="POSCAR") self.create(datoms) # Last of all, create the job file to execute the job array. self.jobfile(rerun)
def add_configs(db, iteration): configs = [] atSi = Atoms("Si8",positions=[[0,0,0],[0.25,0.25,0.25],[0.5,0.5,0],[0.75,0.75,0.25], [0.5,0,0.5],[0.75,0.25,0.75],[0,0.5,0.5],[0.25,0.75,0.75]], cell=[5.43,5.43,5.43]) configs.append(atSi) atSi = Atoms("Si6",positions=[[0,0,0],[0.25,0.25,0.25],[0.5,0.5,0],[0.75,0.75,0.25], [0.5,0,0.5],[0.75,0.25,0.75]], cell=[5.5, 5.5, 5.5]) configs.append(atSi) atSi = Atoms("Si4",positions=[[0,0,0],[0.25,0.25,0.25],[0.5,0.5,0],[0.75,0.75,0.25]], cell=[5.4,5.4,5.4]) configs.append(atSi) db.add_configs(configs, iteration)
def test_AtomsList_io(tmpdir): """Tests the AtomsList writing and reading from file. """ from matdb.atoms import Atoms, AtomsList at1 = Atoms("Si8",positions=[[0,0,0],[0.25,0.25,0.25],[0.5,0.5,0],[0.75,0.75,0.25], [0.5,0,0.5],[0.75,0.25,0.75],[0,0.5,0.5],[0.25,0.75,0.75]], cell=[5.43,5.43,5.43],info={"rand":10}) at2 = Atoms("S6",positions=[[0,0,0],[0.25,0.25,0.25],[0.5,0.5,0],[0.75,0.75,0.25], [0.5,0,0.5],[0.75,0.25,0.75]], cell=[6.43,5.43,4.43],info={"rand":10}) at3 = Atoms("CNi",positions=[[0,0,0],[0.5,0.5,0.5]]) at4 = Atoms() at4.copy_from(at3) al1 = AtomsList([at1,at2,at3,at4]) target = str(tmpdir.join("atomList_to_hdf5")) if not path.isdir(target): mkdir(target) al1.write(path.join(target,"temp.h5")) aR = AtomsList() aR.read(path.join(target,"temp.h5")) assert len(aR) == len(al1) alpos = aR.positions assert any([np.allclose(alpos[i],at1.positions) for i in range(4) if len(alpos[i])==len(at1.positions)]) assert any([np.allclose(alpos[i],at2.positions) for i in range(4) if len(alpos[i])==len(at2.positions)]) assert any([np.allclose(alpos[i],at3.positions) for i in range(4) if len(alpos[i])==len(at3.positions)]) assert any([np.allclose(alpos[i],at4.positions) for i in range(4) if len(alpos[i])==len(at4.positions)]) al1.write(path.join(target,"temp.xyz")) aR = AtomsList() aR.read(path.join(target,"temp.xyz")) assert len(aR) == len(al1) aR.read(path.join(target,"temp.xyz")) assert len(aR) == 2*len(al1) # Test reading in of a single atoms object. aR1 = Atoms(path.join(target,"temp.h5")) assert isinstance(aR1,Atoms) assert any([np.allclose(alpos[i],at1.positions) for i in range(4) if len(alpos[i])==len(at1.positions)])
def test_extract(tmpdir): """Tests the extract method and cleanup method. """ from matdb.utility import symlink, relpath, touch from matdb.utility import _set_config_paths _set_config_paths("AgPd_Enumerated", str(tmpdir)) target = str(tmpdir.join("Vasp")) globals_setup(target) atm = Atoms("Si", positions=[[0, 0, 0]], cell=[1, 1, 1]) kwargs = { "ibrion": 5, "nsw": 1, "kpoints": { "method": "mueller", "mindistance": 50 }, "potcars": { "directory": "./tests/vasp", "xc": "pbe", "versions": { "Si": '05Jan2001' } } } calc = Vasp(atm, target, str(tmpdir), 0, **kwargs) calc.write_input(atm, target) symlink(path.join(calc.folder, "OUTCAR"), relpath("tests/files/VASP/OUTCAR_complete")) symlink(path.join(calc.folder, "CONTCAR"), path.join(calc.folder, "POSCAR")) calc.extract(target) assert hasattr(calc.atoms, calc.force_name) assert hasattr(calc.atoms, calc.virial_name) assert hasattr(calc.atoms, calc.energy_name) assert calc.atoms.vasp_energy is not None assert calc.atoms.vasp_virial is not None assert calc.atoms.vasp_force is not None touch(path.join(calc.folder, "CHG")) calc.cleanup(target, clean_level="light") assert not path.isfile(path.join(calc.folder, "CHG")) touch(path.join(calc.folder, "CHGCAR")) calc.cleanup(target) assert not path.isfile(path.join(calc.folder, "CHGCAR")) touch(path.join(calc.folder, "vasprun.xml")) calc.cleanup(target, clean_level="aggressive") assert not path.isfile(path.join(calc.folder, "OUTCAR")) assert not path.isfile(path.join(calc.folder, "vasprun.xml")) symlink(path.join(calc.folder, "CONTCAR"), path.join(calc.folder, "POSCAR")) symlink(path.join(calc.folder, "OUTCAR"), relpath("tests/files/VASP/OUTCAR_incomplete")) assert not calc.extract(target)
def test_Atoms_copy(): """Tests the mothed Atoms.copy to copy from an matdb.atoms """ from matdb.atoms import Atoms from numpy import array_equal at1 = Atoms("Co3W2V3",positions=[[0,0,0],[0.25,0.25,0.25],[0.5,0.5,0],[1.75,1.75,1.25], [1.5,1,1.5],[2.75,2.25,2.75],[2,2.5,2.5],[2.25,2.75,2.75]], cell=[5.43,5.43,5.43],info={"rand":10, "params":{"vasp_energy": 1234}, "properties":{}}) at2 = at1.copy() assert at1.info["params"] == at2.info["params"] assert at1.info["properties"] == at2.info["properties"] # make sure the symbols and positions are still match assert at1.get_chemical_symbols() == at2.get_chemical_symbols() assert array_equal(at1.positions, at2.positions) assert array_equal(at1.cell, at2.cell)
def test_decompress(): """Tests that the decompression algorithm works. """ from matdb.atoms import Atoms from matdb.database.utility import make_primitive, decompress from phenum.grouptheory import _is_equiv_lattice atm = Atoms(cell=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]], positions=[[0, 0, 0]], symbols="Pd") new_vecs, unique_pos, unique_types, hnf = make_primitive(atm) unique_types = 1 hnf_vec = [ hnf[0][0], hnf[1][0], hnf[1][1], hnf[2][0], hnf[2][1], hnf[2][2] ] hnf_int = "".join(["{0}0".format(i + 1) for i in hnf_vec]) lat_vecs, new_basis, new_types = decompress(new_vecs, unique_pos, unique_types, hnf_int) assert _is_equiv_lattice(atm.cell, lat_vecs, 1E-3) assert np.allclose(atm.positions, new_basis) assert new_types == [1] atm = Atoms(cell=[[0, 0, -1], [0, 1, 0], [1, -0.5, 0.5]], positions=[[0, 0, 0], [0.5, 0, -0.5], [0, 0.5, -0.5], [0.5, 0.5, 0]], numbers=[41, 41, 41, 41]) new_vecs, unique_pos, unique_types, hnf = make_primitive(atm) unique_types = 1 hnf_vec = [ hnf[0][0], hnf[1][0], hnf[1][1], hnf[2][0], hnf[2][1], hnf[2][2] ] hnf_int = "".join(["{0}0".format(i + 1) for i in hnf_vec]) lat_vecs, new_basis, new_types = decompress(new_vecs, unique_pos, unique_types, hnf_int) assert _is_equiv_lattice(np.transpose(atm.cell), np.transpose(lat_vecs), 1E-3) assert np.allclose([[0.0, 0.0, 0.0], [0.5, -0.5, -1.0], [0.0, 0.0, -1.0], [-0.5, 0.5, -1.0]], new_basis) assert new_types == [1, 1, 1, 1]
def rset(self): """Returns a :class:`~matdb.atoms.AtomsList`, one for each config in the latest result set. """ from matdb.atoms import Atoms, AtomsList result = AtomsList() for apath in self.fitting_configs: result.append(Atoms(apath)) return result
def phonopy_to_matdb(patoms): """Converts a :class:`phonopy.structure.atoms.Atoms` to :class:`matdb.atoms.Atoms`. See also :func:`matdb_to_phonopy`. """ #We hard-code the pbc here because phonons only make sense for solids. return Atoms(numbers=patoms.get_atomic_numbers(), positions=patoms.get_positions(), magmoms=patoms.get_magnetic_moments(), cell=patoms.get_cell(), pbc=[True, True, True])
def __init__(self, name=None, root=None, controller=None, splits=None, folder=None, pattern=None, config_type=None, energy="dft_energy", force="dft_force", virial="dft_virial", limit=None): self.name = name self.root = path.join(root, self.name) if not path.isdir(self.root): from os import mkdir mkdir(self.root) self.controller = controller self.splits = {} if splits is None else splits self.folder = folder if self.controller is None: self.ran_seed = 0 else: self.ran_seed = self.controller.ran_seed self._dbfile = path.join(self.root, "legacy-{}.h5".format(limit)) """str: path to the combined legacy database, with limits included. """ self._dbfull = path.join(self.root, "legacy.h5") """str: path to the combined legacy database, *without* limits. """ self.dbfiles = [] self.config_type = config_type from matdb.database.utility import dbconfig config = dbconfig(self._dbfull) if path.isfile(self._dbfile) and len(config) > 0: self.dbfiles = [db[0] for db in config["sources"]] self.config_type = config["config_type"] self.folder = folder else: from matdb.utility import dbcat if not path.isfile(self._dbfull): self._create_dbfull(folder, pattern, energy, force, virial, config_type) if limit is not None: msg.std("Slicing limit subset of full {} db.".format(self.name)) full = AtomsList(self._dbfull) N = np.arange(len(full)) np.random.shuffle(N) ids = N[0:limit] part = full[ids] part.write(self._dbfile) dbcat([self._dbfull], self._dbfile, docat=False, limit=limit, ids=ids) else: from matdb.utility import symlink symlink(self._dbfile, self._dbfull) #The rest of matdb expects each database to have an atoms object that is #representative. Just take the first config in the combined database. self.atoms = Atoms(self._dbfile)
def test_write_input(tmpdir): """Tests the writing of the input files. """ from matdb.utility import _set_config_paths _set_config_paths("AgPd_Enumerated", str(tmpdir)) target = str(tmpdir.join("Vasp")) globals_setup(target) atm = Atoms("Si", positions=[[0, 0, 0]], cell=[[1, 0, 0], [0, 1, 0], [0, 0, 1]]) kwargs = { "kpoints": { "method": "mueller", "mindistance": 50 }, "potcars": { "directory": "./tests/vasp", "xc": "pbe", "versions": { "Si": '05Jan2001' } } } calc = Vasp(atm, target, str(tmpdir), 0, **kwargs) calc.write_input(atm, directory=target) assert path.isfile(path.join(calc.folder, "POTCAR")) assert path.isfile(path.join(calc.folder, "INCAR")) assert path.isfile(path.join(calc.folder, "POSCAR")) assert path.isfile(path.join(calc.folder, "KPOINTS")) kwargs = { "potcars": { "directory": "./tests/vasp", "xc": "pbe", "versions": { "Si": '05Jan2001' } } } calc = Vasp(atm, target, str(tmpdir), 0, **kwargs) calc.write_input(atm, directory=target) assert path.isfile(path.join(calc.folder, "POTCAR")) assert path.isfile(path.join(calc.folder, "INCAR")) assert path.isfile(path.join(calc.folder, "POSCAR")) assert path.isfile(path.join(calc.folder, "KPOINTS")) calc.create() assert path.isfile(path.join(calc.folder, "POTCAR")) assert path.isfile(path.join(calc.folder, "INCAR")) assert path.isfile(path.join(calc.folder, "POSCAR")) assert path.isfile(path.join(calc.folder, "KPOINTS"))
def rset(self): """Returns a :class:`~matdb.atoms.AtomsList`, one for each config in the latest result set. """ #Return the configurations from this group; it is at the #bottom of the stack result = AtomsList() for epath in self.fitting_configs: result.append(Atoms(epath)) return result
def test_extract(tmpdir): """Tests the extract method and cleanup method. """ target = str(tmpdir.join("Qe")) atm = Atoms("AlPd", positions=[[0, 0, 0], [0.5, 0.5, 0.5]]) kwargs = { "potcars": { "directory": path.join(reporoot, "tests/qe"), "potentials": { "Al": "Al.pbe-n-kjpaw_psl.1.0.0.UPF", "Pd": "Pd_ONCV_PBE-1.0.upf" }, "versions": { "Al": ["2.0.1", ".5.1"], "Pd": ["2.0.1", "2.1.1"] } }, "kpoints": { "method": "kspacing", "spacing": 0.1, "offset": 1 }, "input_data": { "control": { "calculation": "relax", "prefix": "test" } } } calc = Qe(atm, target, '.', 0, **kwargs) calc.create() symlink(path.join(calc.folder, "test.xml"), relpath("tests/qe/complete.xml")) mkdir(path.join(calc.folder, "test.save")) calc.extract(target) assert hasattr(calc.atoms, "qe_force") assert hasattr(calc.atoms, "qe_stress") assert hasattr(calc.atoms, "qe_energy") assert calc.atoms.qe_energy is not None assert calc.atoms.qe_stress is not None assert calc.atoms.qe_force is not None touch(path.join(calc.folder, "test.save", "paw.txt")) calc.cleanup(target, clean_level="light") assert not path.isfile(path.join(calc.folder, "test.save", "paw.txt")) touch(path.join(calc.folder, "test.save", "charge-density.dat")) calc.cleanup(target) assert not path.isfile( path.join(calc.folder, "test.save", "charge-density.dat")) calc.cleanup(target, clean_level="aggressive") assert not path.isfile(path.join(calc.folder, "test.xml")) assert not path.isdir(path.join(calc.folder, "test.save"))
def test_rename(rendb): """Tests renaming of properties to meet `matdb` conventions. """ first = Atoms(rendb._dbfile) assert "ref_energy" in first.params assert "ref_force" in first.properties assert "ref_virial" in first.params assert first.params["config_type"] == "re" al = AtomsList(rendb._dbfile) assert len(al) == 80
def test_getattrs(): """Tetsts the getting of attributes from a chain of attributes. """ from matdb.utility import getattrs obj = {"a":{"b":20}} assert 20 == getattrs(obj,'a.b') from matdb.atoms import Atoms at = Atoms("C4") assert np.allclose(np.array([[ 0., 0., 0.], [ 0., 0., 0.], [ 0., 0., 0.]]), getattrs(at,'cell'))
def _prot_to_cfg(source, species, relax_file, type_map, root, min_atoms, max_atoms): """Corrects the POSCAR so that it has the correct lattice parameter and title string for the system to be read into ASE. Args: source (str): the path to the prototype POSCAR. species (list): a list of the species to be used for this POSCAR. relax_file (str): the full path to the to-relax.cfg file being written. type_map (dict): the type mapping to apply to the cfg file. root (str): the root directory where the cfg needs to be stored. min_atoms (int): the smallest number of atoms wanted. max_atoms (int): the largest number of atoms wanted. """ f_lines = [] lat_vecs = [] # read in the original POSCAR with open(source, "r") as f: for i, line in enumerate(f): f_lines.append(line) if i in [2, 3, 4]: lat_vecs.append([float(j) for j in line.strip().split()]) if i == 5: concs = [int(j) for j in line.strip().split()] # If this prototype has more or less atoms in the cell than the # user wants then if (sum(concs) < min_atoms) or (max_atoms is not None and sum(concs) > max_atoms): return # fix the title. f_lines[0] = "{0} : {1}".format(" ".join(species), f_lines[0]) # fix the lattice parameter lat_param, ttl = get_lattice_parameter(species, concs, lat_vecs, sum(concs), " ") f_lines[1] = "{} \n".format(lat_param) target = path.join(root, "PROT") with open(target, "w+") as f: for line in f_lines: f.write(line) atm = Atoms(target, format="vasp") atoms_to_cfg(atm, path.join(root, "prot.cfg"), type_map=type_map) cat([relax_file, path.join(root, "prot.cfg")], path.join(root, "temp.cfg")) rename(path.join(root, "temp.cfg"), relax_file) config_id = "{0}_{1}".format("".join(species), source.split("/")[-1]) remove(path.join(root, "prot.cfg")) remove(target)
def test_to_dict(tmpdir): """Tests the conversion of atoms to dictionaries. """ from matdb.calculators import Vasp from matdb.atoms import Atoms as Atoms from matdb.utility import _set_config_paths _set_config_paths("AgPd_Enumerated", str(tmpdir)) target = str(tmpdir.join("atoms_dict")) globals_setup(target) if not path.isdir(target): mkdir(target) atSi = Atoms("Si8",positions=[[0,0,0],[0.25,0.25,0.25],[0.5,0.5,0],[0.75,0.75,0.25], [0.5,0,0.5],[0.75,0.25,0.75],[0,0.5,0.5],[0.25,0.75,0.75]], cell=[5.43,5.43,5.43]) kwargs = {"encut":400, "kpoints": {"rmin": 50}, "potcars":{"xc": "pbe", "directory": "./tests/vasp", "versions": {"Si": "05Jan2001"}}} calc = Vasp(atSi, target, '.', 0, **kwargs) atSi.set_calculator(calc) atSi.group_uuid = "123456" Sidict = atSi.to_dict() assert "calc" in Sidict assert "calc_kwargs" in Sidict assert Sidict["calc_kwargs"]["encut"] == 400 assert Sidict["group_uuid"] == "123456" assert "potcars" in Sidict["calc_kwargs"] assert "kpoints" in Sidict["calc_kwargs"]
def test_Atoms__getattr__(): """Tests the mothed Atoms.__getattr__ """ from matdb.atoms import Atoms at1 = Atoms("Co3W2V3",positions=[[0,0,0],[0.25,0.25,0.25],[0.5,0.5,0],[1.75,1.75,1.25], [1.5,1,1.5],[2.75,2.25,2.75],[2,2.5,2.5],[2.25,2.75,2.75]], cell=[5.43,5.43,5.43],info={"params":{"vasp_energy": 1234}, "properties":{}}) assert at1.__getattr__("params") == {"vasp_energy": 1234} assert at1.__getattr__("properties") == {} assert np.allclose(at1.__getattr__("cell"), [[5.43, 0. , 0. ], [0. , 5.43, 0. ], [0. , 0. , 5.43]]) assert np.allclose(at1.__getattr__("positions"), [[0,0,0],[0.25,0.25,0.25],[0.5,0.5,0],[1.75,1.75,1.25], [1.5,1,1.5],[2.75,2.25,2.75],[2,2.5,2.5],[2.25,2.75,2.75]]) at2 = Atoms("Co3W2V3", cell=[5.43,5.43,5.43]) del at2.__dict__["info"] assert not hasattr(at2,"info") assert np.allclose(at2.__getattr__("cell"), [[5.43, 0. , 0. ], [0. , 5.43, 0. ], [0. , 0. , 5.43]])
def test_can_extract(tmpdir): """Tests the can_extract method. We'll also test is_executing at the same time. """ target = str(tmpdir.join("Qe")) atm = Atoms("AlPd", positions=[[0, 0, 0], [0.5, 0.5, 0.5]]) kwargs = { "potcars": { "directory": path.join(reporoot, "tests/qe"), "potentials": { "Al": "Al.pbe-n-kjpaw_psl.1.0.0.UPF", "Pd": "Pd_ONCV_PBE-1.0.upf" }, "versions": { "Al": ["2.0.1", ".5.1"], "Pd": ["2.0.1", "2.1.1"] } }, "kpoints": { "method": "kspacing", "spacing": 0.1, "offset": 1 }, "input_data": { "control": { "calculation": "relax", "prefix": "test" } } } calc = Qe(atm, target, '.', 0, **kwargs) calc.create() assert not calc.can_extract("def") assert not calc.can_extract(target) assert not calc.is_executing(target) touch(path.join(calc.folder, "CRASH")) assert not calc.can_extract(target) remove(path.join(calc.folder, "CRASH")) symlink(path.join(calc.folder, "pwscf.xml"), relpath("tests/qe/complete.xml")) mkdir(path.join(calc.folder, "pwscf.save")) assert calc.can_extract(target) remove(path.join(calc.folder, "test.xml")) mkdir(path.join(calc.folder, "pwscf.save")) symlink(path.join(calc.folder, "pwscf.xml"), relpath("tests/qe/fail.xml")) assert not calc.can_extract(target)
def test_read(tmpdir): """Tests the read function of the QE calculator. """ target = str(tmpdir.join("Qe")) atm = Atoms("AlPd", positions=[[0, 0, 0], [0.5, 0.5, 0.5]]) kwargs = { "potcars": { "directory": path.join(reporoot, "tests/qe"), "potentials": { "Al": "Al.pbe-n-kjpaw_psl.1.0.0.UPF", "Pd": "Pd_ONCV_PBE-1.0.upf" }, "versions": { "Al": ["2.0.1", ".5.1"], "Pd": ["2.0.1", "2.1.1"] } }, "kpoints": { "method": "kspacing", "spacing": 0.1, "offset": 1 }, "input_data": { "control": { "calculation": "relax", "prefix": "test" } } } calc = Qe(atm, target, '.', 0, **kwargs) symlink(path.join(calc.folder, "test.xml"), relpath("tests/qe/complete.xml")) output = calc._read(path.join(calc.folder, "test.xml")) assert output["convergence"] == 4.068079462655824e-7 assert np.allclose(output["atoms"], [0, 0, 0]) assert np.allclose(output["cell"], [[-3.75, 0, 3.75], [0, 3.75, 3.75], [-3.75, 3.75, 0]]) assert output["etot"] == -1.975055613913407e1 assert np.allclose(output["forces"], [0, 0, 0]) assert np.allclose(output["stress"], [[ 1.578434139006113e-4, -1.219727444046192e-19, -9.486769009248164e-20 ], [ -1.490777987167569e-19, 1.578434139006113e-4, 9.486769009248164e-20 ], [-6.776263578034403e-20, 1.219727444046192e-19, 1.578434139006113e-4]]) assert calc.version == '6.2 (svn rev. 14038)'