def test_can_extract(tmpdir): """Tests the can_extract method. We'll also test is_executing at the same time. """ from matdb.utility import symlink, relpath 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]]) 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_extract("def") assert not calc.can_extract(target) symlink(path.join(calc.folder, "OUTCAR"), relpath("tests/files/VASP/OUTCAR_incomplete")) assert not calc.can_extract(target) assert calc.is_executing(target) symlink(path.join(calc.folder, "OUTCAR"), relpath("tests/files/VASP/OUTCAR_complete")) assert calc.can_extract(target) assert not calc.is_executing(target)
def test_Atoms__setattr__(): """Tests the mothed Atoms.__setattr__ """ from matdb.atoms import Atoms at1 = Atoms("Co3W2V3") at1.__setattr__("params", {"vasp_energy": 1234}) at1.__setattr__("properties", {"rank": 21}) at1.__setattr__("cell", [[5.43, 0. , 0. ], [0. , 5.43, 0. ], [0. , 0. , 5.43]]) at1.__setattr__("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]]) assert at1.__getattr__("params") == {"vasp_energy": 1234} assert at1.__getattr__("properties") == {"rank": 21} 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]]) at1.__setattr__("rank", 22) assert at1.__getattr__("rank") == 22 at1.__setattr__("vasp_energy", 4321) assert at1.__getattr__("vasp_energy") == 4321
def _setup_configs(self, rerun): """Loops over the choosen prototype structures and possible occupations for those structures, i.e., A:B and B:A, to generate all the configurations needed for th calculation. Args: rerun (bool): when True, recreate the folders even if they already exist. """ #We also don't want to setup again if we have the results already. if self.ready() and not rerun: return if self.puuids is None: self.puuids = [] if not self.is_setup(): from itertools import product # Loop over the sizes in the saved structures for k, v in self.structures.items(): perms = self._get_perms(k) for fpath, perm in product(v, perms): hash_str = "{0}-{1}".format( fpath.split("/")[-1], "".join(perm)) hash_str = str(sha1(hash_str.encode()).hexdigest()) if hash_str not in self.puuids: self.puuids.append(hash_str) self._correct_poscar(fpath, path.join(self.root, "POSCAR"), perm) datoms = Atoms(path.join(self.root, "POSCAR"), format="vasp") self.create(datoms) remove(path.join(self.root, "POSCAR")) # Last of all, create the job file to execute the job array. self.save_pkl(self.puuids, self.puuid_file) self.jobfile(rerun)
def test_kpath(): """Performs a simple test to extract the kpath for an alloy. """ from matdb.atoms import Atoms from matdb.kpoints import parsed_kpath from matdb.utility import relpath filepath = relpath("tests/files/POSCAR-AgPd-50") at0 = Atoms(filepath, format="vasp") model = { 'band': [[0.0, 0.0, 0.0], [0.0, 0.0, 0.5], [0.25, 0.25, 0.25], [0.0, 0.5, 0.0], [0.0, 0.0, 0.0], [0.5, 0.5, -0.5], [0.3126058432665583, 0.6873941567334416, -0.3126058432665583], [0.0, 0.0, 0.0], [-0.12521168653311662, 0.12521168653311662, 0.5], [0.5, 0.5, -0.5]], 'labels': [ '\\Gamma', 'X', 'P', 'N', '\\Gamma', 'M', 'S|S_0', '\\Gamma|X', 'R|G', 'M' ] } labels, band = parsed_kpath(at0) assert labels == model["labels"] assert band == model["band"]
def test_make_primitive(): """Tests the make_primitive routine. """ from matdb.atoms import Atoms from matdb.database.utility import make_primitive 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) assert np.allclose(new_vecs, atm.cell) assert np.allclose(unique_pos, unique_pos) assert np.allclose(hnf, np.identity(3)) assert unique_types[0] == "Pd" 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) new_lat = np.matmul(np.transpose(new_vecs), hnf) assert _is_equiv_lattice(new_lat, np.transpose(atm.cell), 1E-3) assert np.allclose(new_vecs, [[0.5, 0, -0.5], [0, 0.5, -0.5], [0.5, 0.5, 0]]) assert np.allclose(unique_pos, [[0, 0, 0]]) assert np.allclose(np.linalg.det(hnf), 4) assert unique_types[0] == "Nb" atm = Atoms(cell=[[0.5, 0.5, 0], [0, 0.5, 0.5], [1.5, -1, 1.5]], positions=[[0, 0, 0], [0.5, 0, 0.5], [1, 0, 1], [1.5, 0, 1.5]], symbols="Pd3Ag") new_vecs, unique_pos, unique_types, hnf = make_primitive(atm) new_lat = np.matmul(new_vecs, hnf) assert _is_equiv_lattice(new_lat, atm.cell, 1E-3) assert np.allclose(new_vecs, atm.cell) assert np.allclose(unique_pos, atm.positions) 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]], symbols="AlPdAlPd") new_vecs, unique_pos, unique_types, hnf = make_primitive(atm) new_lat = np.matmul(np.transpose(new_vecs), hnf) assert _is_equiv_lattice(new_lat, np.transpose(atm.cell), 1E-3) assert np.allclose(new_vecs, [[0, 0.5, -0.5], [0, 0, -1], [1, -0.5, 0.5]]) assert np.allclose(unique_pos, [[0, 0, 0], [0.5, 0, -0.5]]) assert np.allclose(np.linalg.det(hnf), 2) assert "Al" in unique_types assert "Pd" in unique_types atm = Atoms(cell=[[1, 0, 0], [0.5, 0.8660254, 0], [0, 0, 1.6329932]], positions=[[0, 0, 0], [0.5, 0.2886751, 0.8164966]], symbols="Al2") new_vecs, unique_pos, unique_types, hnf = make_primitive(atm) assert np.allclose(new_vecs, atm.cell) assert np.allclose(unique_pos, atm.positions) assert np.allclose(np.linalg.det(hnf), 1) with pytest.raises(ValueError): atm = Atoms(cell=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]], positions=[[0, 0, 0]]) stuff = make_primitive(atm)
def band_raw(primitive, bandfiles=None, pots=None, supercell=None, npts=100, title="{} Phonon Spectrum", save=None, figsize=(10, 8), nbands=4, line_names=None, delta=0.01, quick=True, **kwargs): """Plots the phonon bands from raw `band.yaml` files. Args: primitive (str): path to the atoms file for the *primitive* to plot bands for. Use the ASE format string as a prefix, e.g. `vasp-xml:vasprun.xml` or `extxyz:atoms.xyz`. Default assumes `vasp:{}` if no format is specified. bandfiles (list): list of `str` file paths to the plain `band.yaml` files. supercell (list): list of `int`; supercell dimensions for the phonon calculations. npts (int): number of points to sample along the special path in k-space. title (str): Override the default title for plotting; use `{}` for formatting chemical formula. save (str): name of a file to save the plot to; otherwise the plot is shown in a window. figsize (tuple): tuple of `float`; the size of the figure in inches. nbands (int): number of bands to plot. delta (float): size of displacement for finite difference derivative. quick (bool): when True, use symmetry to speed up the Hessian calculation for the specified potentials. kwargs (dict): additional "dummy" arguments so that this method can be called with arguments to other functions. """ nlines = len(bandfiles) + (0 if pots is None else len(pots)) colors = plt.cm.nipy_spectral(np.linspace(0, 1, nlines)) bands, style = {}, {} #Handle DSL format import on the file path for the primitive cell. if ':' not in primitive: atoms = Atoms(primitive, format="vasp") else: fmt, atpath = primitive.split(':') atoms = Atoms(atpath, format=fmt) names, kpath = parsed_kpath(atoms) #matplotlib needs the $ signs for latex if we are using special #characters. We only get names out from the first configuration; all #the others have to use the same one. names = ["${}$".format(n) if '\\' in n or '_' in n else n for n in names] for ifile, fpath in enumerate(bandfiles): if line_names is not None: key = line_names[ifile] else: key = "File {}".format(ifile) bands[key] = from_yaml(fpath) style[key] = {"color": colors[ifile], "lw": 2} if pots is not None: for fiti, fit in enumerate(tqdm(pots)): gi = len(bandfiles) + fiti atoms.set_calculator(fit) H = phon_calc(atoms, supercell=supercell, delta=delta, quick=quick) bands[line_names[gi]] = _calc_bands(atoms, H, supercell) style[line_names[gi]] = {"color": colors[gi], "lw": 2} title = title.format(atoms.get_chemical_formula()) savefile = None if save: savefile = save bandplot(bands, names, title=title, outfile=savefile, figsize=figsize, style=style, nbands=nbands)
def test_qe_setup(tmpdir): """Tests QE calculator initialization. """ target = str(tmpdir.join("Qe")) atm = Atoms("AlPd", positions=[[0, 0, 0], [0.5, 0.5, 0.5]]) kwargs = { "potcars": { "directory": "./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": "MP", "divisions": "3 3 3" }, "input_data": { "control": { "calculation": "relax", "prefix": "test" } } } calc = Qe(atm, target, 'def', 0, **kwargs) assert isinstance(calc, Qe) assert calc.parameters["input_data"]["control"]["calculation"] == "relax" assert "kpts" in calc.parameters assert calc.out_file == "test" 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", "outdir": "temp" } } } calc = Qe(atm, target, '.', 0, **kwargs) calc.write_input(atm) assert calc.parameters["koffset"] == 1 assert "kspacing" in calc.parameters assert calc.out_file == "temp/test" 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 } } calc = Qe(atm, target, '.', 0, **kwargs) calc.write_input(atm) assert "input_data" not in calc.in_kwargs
def test_set_static(tmpdir): """Tests the set static method. """ 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, '$control$/Qe', '$control$', 0, **kwargs) stat = calc.set_static(kwargs) assert stat["input_data"]["control"]["calculation"] == "scf" 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": {} } stat = calc.set_static(kwargs) assert stat["input_data"]["control"]["calculation"] == "scf" 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 } } stat = calc.set_static(kwargs) assert stat["input_data"]["control"]["calculation"] == "scf"
def test_to_dict(tmpdir): """Tests the calculator to_dict method. """ from matdb.utility import _set_config_paths _set_config_paths("AgPd_Enumerated", str(tmpdir)) target = str(tmpdir.join("Qe")) globals_setup(target) atm = Atoms("AlPd", positions=[[0, 0, 0], [0.5, 0.5, 0.5]]) kwargs = { "potcars": { "directory": "./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, '$control$/Qe', '$control$', 0, **kwargs) symlink(path.join(calc.folder, "test.xml"), relpath("tests/qe/complete.xml")) calc.extract(target) calc_dict = calc.to_dict() kwargs = { "potcars": { "directory": "156def0ed29f1a908d5a7b4eae006c672e7b0ff1", "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" }, 'tprnfor': True, 'tstress': True } } out = { "folder": '$control$/Qe', "ran_seed": 0, "contr_dir": '$control$', "kwargs": kwargs, "args": (), "version": "6.2 (svn rev. 14038)" } assert compare_nested_dicts(calc_dict, out)
def trimer(pot, atoms, elements, folder=None, base64=False, index=None, nsamples=50): """Plots the potential behavior as the angle between three atoms changes in a trimer. .. note:: This produces a *dict* of all possible 3-body interactions between distinct element types. Args: elements (list): list of chemical symbols in the system. pot (matdb.calculators.basic.AsyncCalculator): IP to calculate properties with. atoms (matdb.atoms.AtomsList): list of atoms from which to calculate correlations. folder (str): path to the folder where the saved image should be stored. base64 (bool): when True, use a base-64 encoded `src` for the output of this image; otherwise, the image is saved to `folder` and only its name is returned. index (int): integer index of this plot in the parent collection. nsamples (int): number of samples to take along the trajectory. Returns: dict: keys are concatenated element names (e.g. `AgPd`) and values are :class:`PointDetailImage` instances. """ #First, determine the set of unique element pairs in the list. from itertools import product possible = list(product(elements, repeat=3)) target = list(set(map(lambda l: tuple(sorted(l)), possible))) subplot_kw = {"xlabel": "Angle (Rad)", "ylabel": "IP Energy (eV)"} result = {} for elements in target: #Look up the lattice parameters for each of the elements. Use Vegard's #law to get a decent domain to plot the energy over. from matdb.data import vegard uelements = list(set(elements)) concdict = [elements.count(e) / 3. for e in uelements] rvegard = vegard(uelements, concdict) trimer = Atoms(positions=np.zeros((3, 3)), cell=np.eye(3) * 100) trimer.positions = 0. trimer.set_chemical_symbols(elements) trimer.set_calculator(pot) #Set the position of the second atom to be at equilibrium with respect #to the Vegard's law calculation. trimer.positions[1, 2] = rvegard #Now, vary the angle of the third atom with respect to the original two #and see how the angle changes. theta = np.linspace(np.pi / 6, np.pi, nsamples) energy = [] for t in theta: x = rvegard * np.cos(t) y = rvegard * np.sin(t) trimer.positions[1, 2] = x trimer.positions[1, 2] = y energy.append(trimer.get_potential_energy()) elemstr = trimer.get_chemical_formula() img = PDI(theta, np.array(energy), "plot", subplot_kw=subplot_kw, index=index, base64=base64, name=elemstr, imgtype=elemstr, folder=folder) result[elemstr] = img return result
def test_train_setup(mtpdb): """Tests the mtp training setup. """ #test make_train_cfg #first build the database directory. from matdb.utility import copyonce, _get_reporoot from os import path, mkdir, remove from matdb.atoms import Atoms seed_root = path.join(mtpdb.root, "seed") mkdir(seed_root) templates = path.join(_get_reporoot(), "tests", "mtp", "training") for i in range(1,11): target = path.join(seed_root, "vasp.{0}".format(i)) source = path.join(templates, "POSCAR{0}".format(i)) copyonce(source, target) mtpfit = mtpdb.trainers.fits['CoWV_mtp'].sequences['CoWV_mtp'].steps['mtp'] cntrl_root = mtpdb.root db_root = path.join(cntrl_root, "Manual", "test.manual") mtpdb.setup() files = ["OUTCAR{}", "CONTCAR{}"] for i in range(1,11): target = path.join(db_root, "vasp.{0}".format(i), "S1.1") for f in files: copyonce(path.join(templates, f.format(i)), path.join(target, f.format(''))) mtpdb.extract() mtpfit._make_train_cfg(1) assert path.isfile(path.join(mtpfit.root, "train.cfg")) struct_count = 0 with open(path.join(mtpfit.root, "train.cfg"),"r") as f: for line in f: if "BEGIN_CFG" in line: struct_count += 1 assert struct_count == 10 new_configs = [] for i in range(1,11): source = path.join(templates, "POSCAR{0}".format(i)) new_configs.append(Atoms(source)) mtpfit.active.add_configs(new_configs, 2) mtpfit.active.setup() act_root = path.join(mtpdb.root, "Active", "active.CoWV_mtp") files = ["OUTCAR{}", "CONTCAR{}"] for i in range(1,11): target = path.join(act_root, "Ac.{0}".format(i)) for f in files: copyonce(path.join(templates, f.format(i)), path.join(target, f.format(''))) # This is trying to manipulate an NOT extractable structure target = path.join(act_root, "Ac.{0}".format(3), "OUTCAR") remove(target) source = path.join(_get_reporoot(), "tests", "files", "VASP", "OUTCAR_incomplete") copyonce(source, target) mtpfit.active.last_iteration = None mtpfit._make_train_cfg(2) assert path.isfile(path.join(mtpfit.root, "train.cfg")) struct_count = 0 with open(path.join(mtpfit.root, "train.cfg"),"r") as f: for line in f: if "BEGIN_CFG" in line: struct_count += 1 assert struct_count == 19 mtpfit.active.last_iteration = None remove(mtpfit.active.iter_file) with pytest.raises(IOError): mtpfit._make_train_cfg(2)
def test_AtomsList_creation(tmpdir): """Tests the creation of the AtomsList object. """ from matdb.calculators import Vasp from matdb.atoms import Atoms, AtomsList from matdb.utility import _set_config_paths _set_config_paths("AgPd_Enumerated", str(tmpdir)) target = str(tmpdir.join("make_AtomsList")) globals_setup(target) if not path.isdir(target): mkdir(target) kwargs = {"kpoints":{"rmin":50}, "potcars": {"directory":"./tests/vasp", "versions":{"Si": '05Jan2001'}}, "xc":"pbe"} 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}) potSW = Vasp(at1, target, str(tmpdir), 0, **kwargs) at1.set_calculator(potSW) at1.add_property("vasp_force", [[-18057.59589857, -18057.59589857, -18057.59589857], [ -2997.55626529, -2997.55626529, -2997.55626529], [ 3044.17916471, 3044.17916471, -34130.71583118], [ 18969.1757571 , 18969.1757571 , 11159.15815145], [ 3044.17916471, -34130.71583118, 3044.17916471], [ 18969.1757571 , 11159.15815145, 18969.1757571 ], [-34130.71583118, 3044.17916471, 3044.17916471], [ 11159.15815145, 18969.1757571 , 18969.1757571 ]]) at1.add_param("vasp_energy", 1234) 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},calculator=potSW) kwargs = {"kpoints":{"rmin":50}, "potcars": {"directory":"./tests/vasp", "versions":{"S": '06Sep2000'}}, "xc":"pbe"} potSW = Vasp(at2, target, str(tmpdir), 0, **kwargs) at2.set_calculator(potSW) at2.add_property("vasp_force", np.random.randint(0, 100, (6,3))) at2.add_param("vasp_energy", 4321) al1 = AtomsList([at1,at2]) assert len(al1) == 2 at1.write(target=path.join(target,"temp1.h5")) at2.write(target=path.join(target,"temp2.h5")) al2 = AtomsList([path.join(target,"temp1.h5"),path.join(target,"temp2.h5")]) assert len(al2) == 2 assert isinstance(al2[0],Atoms) empty_list = AtomsList([]) assert len(empty_list) == 0 al3 = AtomsList(at1) assert al3[0] == at1 al4 = AtomsList(path.join(target,"temp1.h5")) assert len(al4) == 1 assert isinstance(al4[0],Atoms) assert al4[0].vasp_energy == at1.vasp_energy
def test_to_dict(tmpdir): """Tests the calculator to_dict 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("AgPd", positions=[[0, 0, 0], [0.25, 0.25, 0.25]], cell=[1, 1, 1]) kwargs = { "ibrion": 5, "xc": "pbe", "nsw": 1, "kpoints": { "method": "mueller", "mindistance": 30 }, "potcars": { "directory": '156def0ed29f1a908d5a7b4eae006c672e7b0ff1', "xc": "pbe", "versions": { "Ag": '09Dec2005', "Pd": '04Jan2005' }, "setups": { "Ag": "_pv" } }, "exec_path": None } calc = Vasp(atm, '$control$/Vasp', '$control$', 0, **kwargs) calc_dict = calc.to_dict() kwargs1 = { "ibrion": 5, "xc": "pbe", "nsw": 1, "kpoints": { "method": "mueller", "mindistance": 30 }, "potcars": { "directory": '156def0ed29f1a908d5a7b4eae006c672e7b0ff1', "xc": "pbe", "versions": { "Ag": '09Dec2005', "Pd": '04Jan2005' }, "setups": { "Ag": "_pv" } } } kwargs2 = { "ibrion": 5, "xc": "pbe", "nsw": 1, "kpoints": { "method": "mueller", "mindistance": 30 }, "potcars": { "directory": '03526af4c062e11236b794c0b260a2571cfe12d6', "xc": "pbe", "versions": { "Ag": '09Dec2005', "Pd": '04Jan2005' }, "setups": { "Ag": "_pv" } } } out1 = { "folder": '$control$/Vasp', "ran_seed": 0, "contr_dir": '$control$', "kwargs": kwargs1, "args": () } #, "version": "vasp.4.6.35"} out2 = { "folder": '$control$/Vasp', "ran_seed": 0, "contr_dir": '$control$', "kwargs": kwargs2, "args": () } #, "version": "vasp.4.6.35"} # "version" appears in calc_dict on local device if "version" in calc_dict: out1["version"] = calc_dict["version"] out2["version"] = calc_dict["version"] assert compare_nested_dicts(calc_dict, out1) or compare_nested_dicts( calc_dict, out2) calc_dict = calc.to_dict() out1 = { "folder": '$control$/Vasp', "ran_seed": 0, "contr_dir": '$control$', "kwargs": kwargs1, "args": (), "version": "" } out2 = { "folder": '$control$/Vasp', "ran_seed": 0, "contr_dir": '$control$', "kwargs": kwargs2, "args": (), "version": "" } assert compare_nested_dicts(calc_dict, out1) or compare_nested_dicts( calc_dict, out2)
def dimer(pot, atoms, elements, folder=None, base64=False, index=None, nsamples=50, zoom=False): """Plots the potential behavior as the distance between two atoms in a dimer. .. note:: This produces a **dict** of all possible 2-body interaction between distinct element types. Args: elements (list): list of chemical symbols in the system. pot (matdb.calculators.basic.AsyncCalculator): IP to calculate properties with. atoms (matdb.atoms.AtomsList): list of atoms from which to calculate correlations. folder (str): path to the folder where the saved image should be stored. base64 (bool): when True, use a base-64 encoded `src` for the output of this image; otherwise, the image is saved to `folder` and only its name is returned. index (int): integer index of this plot in the parent collection. nsamples (int): number of samples to take along the trajectory. zoom (bool): when True, show a zoomed in view of the potential. Returns: dict: keys are concatenated element names (e.g. `AgPd`) and values are :class:`PointDetailImage` instances. """ #First, determine the set of unique element pairs in the list. from itertools import product possible = list(product(elements, repeat=2)) target = list(set(map(lambda l: tuple(sorted(l)), possible))) subplot_kw = {"xlabel": "Distance (Ang)", "ylabel": "IP Energy (eV)"} result = {} for elements in target: #Look up the lattice parameters for each of the elements. Use Vegard's #law to get a decent domain to plot the energy over. rmin, rvegard, rmax = _dimer_range(elements) dimer = Atoms(positions=np.zeros((2, 3)), cell=np.eye(3) * 100) dimer.positions = 0. dimer.set_calculator(pot) dimer.set_chemical_symbols(elements) if zoom: rs = np.linspace(0.7 * rmin, pot.cutoff(), nsamples) else: rs = np.linspace(0.4 * rmin, pot.cutoff(), nsamples) energy = [] for r in rs: dimer.positions[1, 2] = r energy.append(dimer.get_potential_energy()) elemstr = ''.join(elements) + ('z' if zoom else "") img = PDI(rs, np.array(energy), "plot", subplot_kw=subplot_kw, index=index, base64=base64, name=elemstr, imgtype=elemstr, folder=folder) result[elemstr] = img return result
def test_write_potcar(tmpdir): """Tests the writing of the POTCAR file. """ from matdb.utility import _set_config_paths from hashlib import sha1 _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": { "rmin": 50 }, "potcars": { "directory": "./tests/vasp", "xc": "pbe", "versions": { "Si": '05Jan2001' } } } calc = Vasp(atm, target, str(tmpdir), 0, **kwargs) calc._write_potcar() this_potcar = str( sha1("{0}{1}".format("Si", "05Jan2001").encode()).hexdigest()) assert path.isfile(path.join(calc.contr_dir, "POTCARS", this_potcar)) assert path.isfile(path.join(calc.folder, "POTCAR")) remove(path.join(calc.contr_dir, "POTCARS", this_potcar)) 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_potcar() assert path.isfile(path.join(calc.contr_dir, "POTCARS", this_potcar)) calc._write_potcar() assert path.isfile(path.join(calc.folder, "POTCAR")) # check POTCAR reuse calc = Vasp(atm, target, str(tmpdir), 0, **kwargs) with pytest.raises(SpeciesError): kwargs = { "kpoints": { "rmin": 50 }, "potcars": { "directory": "./tests/vasp", "xc": "pbe", "versions": { "Si": '05Jan2001' } } } symlink( path.join(calc.contr_dir, "POTCARS", calc.this_potcar), path.join(reporoot, "tests", "vasp", "potpaw_PBE", "Ag", "POTCAR")) calc = Vasp(atm, '.', str(tmpdir), 0, **kwargs) with pytest.raises(VersionError): kwargs = { "kpoints": { "rmin": 50 }, "potcars": { "directory": "./tests/vasp", "xc": "pbe", "versions": { "Si": '05Jan2001' } } } symlink( path.join(calc.contr_dir, "POTCARS", calc.this_potcar), path.join(reporoot, "tests", "vasp", "potpaw_PBE", "Si_sv_GW", "POTCAR")) atm = Atoms("Si", positions=[[0, 0, 0]], cell=[[1, 0, 0], [0, 1, 0], [0, 0, 1]]) calc = Vasp(atm, '.', str(tmpdir), 0, **kwargs)
def _enumerate(self, dind, recurse, home): """Performs the enumeration using phenum and creates the files in the correct folder for each system enumerated. Args: dind (int): The number of configs found so far. recurse (int): The number of times we've attempted to find a unique set of enumerations over the same range. home (str): The home directory. """ _enum_out({ "input": "enum.in", "outfile": "enum.out", "seed": self.ran_seed if self.ran_seed is None else self.ran_seed + dind + recurse, "lattice": "lattice.in", "distribution": ["all", str(self.nconfigs)], "super": self.keep_supers, "sizes": None, "savedist": None, "filter": None, "acceptrate": None }) remove("enum.in") [remove(f) for f in listdir('.') if f.startswith("polya.")] # extract the POSCARS euids = _make_structures( { "structures": None, "input": "enum.out", "species": self.species, "rattle": self.rattle, "mink": "t", "outfile": "vasp.{}", "displace": self.displace, "config": "f", "remove_zeros": "f" }, return_euids=True) # Now we need to create the folder for each system we've enumerated if self.euids is None: self.euids = [] for count, dposcar in enumerate(glob("vasp.*")): if dind == self.nconfigs: break elif euids[count].hexdigest() not in self.euids: dind += 1 datoms = Atoms(dposcar, format="vasp") with chdir(home): self.create(datoms, cid=dind) copyonce(dposcar, path.join(self.configs[dind], "POSCAR_orig")) self.index[str(euids[count].hexdigest())] = self.configs[dind] self.euids.append(str(euids[count].hexdigest())) [remove(f) for f in listdir('.') if f.startswith("vasp.")] return dind
def test_split(Act): """Tests the split function. """ 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]], info={"rand": 8}) at4 = Atoms("CoV", positions=[[0, 0, 0], [0.25, 0.5, 0.25]], info={"rand": 8}) at1.add_param("vasp_energy", 25361.504084423999) at2.add_param("vasp_energy", 25362.504084423999) at3.add_param("vasp_energy", 25363.504084423999) at4.add_param("vasp_energy", 25364.504084423999) al = [at4, at2, at1, at3] splits = {'A': 0.4, 'B': 0.2} splitroot = path.join(Act.root, "split") mkdir(splitroot) file_targets = { "train": Act.database.train_file, "holdout": Act.database.holdout_file, "super": Act.database.super_file } # the split directory should be empty assert len(listdir(splitroot)) == 0 # split with an empty splits split(al, {}, file_targets, splitroot, ran_seed=1, recalc=1) # the split directory should still be empty assert len(listdir(splitroot)) == 0 # split with an empty atom list split([], splits, file_targets, splitroot, ran_seed=1, recalc=1) # the split directory should have 2 entries assert len(listdir(splitroot)) == 2 # split split(al, splits, file_targets, splitroot, ran_seed=1) # now we should have all the splitted files assert path.exists(path.join(splitroot, Act.database.train_file('A'))) assert path.exists(path.join(splitroot, Act.database.holdout_file('A'))) assert path.exists(path.join(splitroot, Act.database.super_file('A'))) assert path.exists(path.join(splitroot, Act.database.train_file('B'))) assert path.exists(path.join(splitroot, Act.database.holdout_file('B'))) assert path.exists(path.join(splitroot, Act.database.super_file('B'))) # the split directory should have 2 entries assert len(listdir(splitroot)) == 2 # split again with recalc split(al, splits, file_targets, splitroot, ran_seed=1, recalc=1) assert glob( path.join(Act.database.root, "splits", "active", "A_*-train.h5")) assert glob( path.join(Act.database.root, "splits", "active", "A_*-holdout.h5")) assert glob( path.join(Act.database.root, "splits", "active", "A_*-super.h5")) assert glob( path.join(Act.database.root, "splits", "active", "B_*-train.h5")) assert glob( path.join(Act.database.root, "splits", "active", "B_*-holdout.h5")) assert glob( path.join(Act.database.root, "splits", "active", "B_*-super.h5")) # the split directory should have 2 entries assert len(listdir(splitroot)) == 2
def test_reading_multiple_files(tmpdir): """Tests the reading in of multiple atoms objects to an AtomsList. """ from matdb.calculators import Vasp from matdb.atoms import Atoms as Atoms, AtomsList from matdb.io import save_dict_to_h5 import h5py from matdb.utility import _set_config_paths _set_config_paths("AgPd_Enumerated", str(tmpdir)) target = str(tmpdir.join("read_atoms2")) 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) temp = path.join(target,"temp.h5") atSi.write(temp) atSi2 = 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=[6.43,6.43,6.43]) kwargs = {"encut":600, "kpoints": {"rmin": 50}, "potcars":{"xc": "pbe", "directory": "./tests/vasp", "versions": {"Si": "05Jan2001"}}} calc = Vasp(atSi2, target, '.', 0, **kwargs) atSi2.set_calculator(calc) temp2 = path.join(target,"temp2.h5") atSi2.write(temp2) atRL = AtomsList([temp,temp2]) assert len(atRL) == 2 assert atRL[0].calc.kwargs["encut"] != atRL[1].calc.kwargs["encut"] assert atRL[1].calc.kwargs["encut"] in [400,600] assert atRL[0].calc.kwargs["encut"] in [400,600] atom_dict = {"atom_1":temp, "atom_2": temp2} temp3 = path.join(target,"temp3.h5") with h5py.File(temp3,"w") as hf: save_dict_to_h5(hf,atom_dict,'/') atRL = AtomsList(temp3) assert len(atRL) == 2 assert atRL[0].calc.kwargs["encut"] != atRL[1].calc.kwargs["encut"] assert atRL[1].calc.kwargs["encut"] in [400,600] assert atRL[0].calc.kwargs["encut"] in [400,600]
def test_vasp_setup(tmpdir): """Tests Vasp calculator initialization. """ 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]]) kwargs = { "kpoints": { "rmin": 50 }, "potcars": { "directory": "./tests/vasp", "versions": { "Si": '05Jan2001' } }, "xc": "pbe" } calc = Vasp(atm, target, str(tmpdir), 0, **kwargs) assert calc.potcars["xc"] == "pbe" kwargs = { "kpoints": { "rmin": 50 }, "potcars": { "directory": "./tests/vasp", "xc": "pbe", "versions": { "Si": '05Jan2001' } } } calc = Vasp(atm, target, str(tmpdir), 0, **kwargs) assert calc.kwargs["xc"] == "pbe" stat = calc.set_static(kwargs) assert "nsw" in stat and stat["nsw"] == 0 calc.asis = True assert calc.read_convergence() with pytest.raises(VersionError): kwargs = { "kpoints": { "rmin": 50 }, "potcars": { "directory": "./tests/vasp", "xc": "pbe" } } calc = Vasp(atm, '.', str(tmpdir), 0, **kwargs) with pytest.raises(VersionError): kwargs = { "kpoints": { "rmin": 50 }, "potcars": { "directory": "./tests/vasp", "xc": "pbe", "versions": { "Si": '04Jan2001' } } } calc = Vasp(atm, '.', str(tmpdir), 0, **kwargs) with pytest.raises(VersionError): kwargs = { "kpoints": { "rmin": 50 }, "potcars": { "directory": "./tests/vasp", "xc": "pbe", "versions": { "Si": '04Jan2001' } } } atm = Atoms("Al", positions=[[0, 0, 0]]) calc = Vasp(atm, '.', str(tmpdir), 0, **kwargs) with pytest.raises(ValueError): kwargs = { "kpoints": { "rmin": 50 }, "potcars": { "directory": "./tests/vasp" } } calc = Vasp(atm, '.', str(tmpdir), 0, **kwargs)
def test_atoms_to_cfg(tmpdir): """Tests the writing of an atoms object to cfg format. """ from matdb.io import atoms_to_cfg from matdb.atoms import Atoms from os import path, remove from ase.calculators.singlepoint import SinglePointCalculator from matdb.calculators import Vasp from matdb.utility import _set_config_paths 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]) target = "train.cfg" atoms_to_cfg(atSi, target) assert path.isfile(target) remove(target) energy = 10.0 forces = [[1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4], [5, 5, 5], [6, 6, 6], [7, 7, 7], [8, 8, 8]] virial = [[0, 1, 2], [3, 4, 5], [6, 7, 8]] atSi.calc = SinglePointCalculator(atSi, energy=energy, forces=np.array(forces), stress=virial) atSi.add_property("energy", energy) atSi.add_property("virial", virial) atSi.add_param("force", forces) atoms_to_cfg(atSi, target) assert path.isfile(target) remove(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]) type_map = {0: 1} kwargs = { "kpoints": { "rmin": 50 }, "potcars": { "directory": "./tests/vasp", "versions": { "Si": "05Jan2001" } }, "xc": "pbe" } _set_config_paths("test", tmpdir) atSi.calc = Vasp(atSi, str(tmpdir.join("Vasp")), str(tmpdir), 0, **kwargs) atoms_to_cfg(atSi, target, type_map=type_map, config_id="test") assert path.isfile(target) remove(target)
def test_AtomsList_attributes(): """Tests the atoms lists attributes. """ 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]], info={"rand":8}) at4 = Atoms(info={"rand":7}) at4.copy_from(at3) al1 = AtomsList([at1,at2,at3,at4]) alpos = al1.positions assert np.allclose(alpos[0],at1.positions) assert np.allclose(alpos[1],at2.positions) assert np.allclose(alpos[2],at3.positions) assert np.allclose(alpos[3],at4.positions) with pytest.raises(AttributeError): al1.__getattr__('__dict__') assert al1.energy is None alslice = al1[0:2] assert len(alslice) == 2 assert alslice[0] == at1 assert alslice[1] == at2 alitems = al1[[0,1,3]] assert len(alitems) == 3 assert alitems[0] == at1 assert alitems[1] == at2 assert alitems[2] == at4 with pytest.raises(IndexError): al1[[0,2.3]] alitems = al1[[True,True,False,True]] assert len(alitems) == 3 for i in al1.iterframes(): assert isinstance(i,Atoms) for i in al1.iterframes(reverse=True): assert isinstance(i,Atoms) assert al1.random_access def get_pos(atoms): return atoms.positions alpos=al1.apply(get_pos) assert np.allclose(alpos[0],at1.positions) assert np.allclose(alpos[1],at2.positions) assert np.allclose(alpos[2],at3.positions) assert np.allclose(alpos[3],at4.positions) al1.sort(reverse=True) al1.sort(attr='rand') with pytest.raises(ValueError): al1.sort(attr='positions',key=2)
def command(self): """Returns the command that is needed to train the GAP potentials specified by this object. .. note:: This method also configures the directory that the command will run in so that it has the relevant files. """ self._set_root() if not path.isfile(path.join(self.root, "status.txt")): self.iter_status = "train" self.iter_count = 1 self.cell_iter = 0 else: with open(path.join(self.root, "status.txt"), "r") as f: for line in f: old_status = line.strip().split() if old_status[0] == "done": self.iter_status = "train" # iter_count is the total iteration number for the whole process, not limited to one cell self.iter_count = int(old_status[1]) + 1 self.cell_iter = int(old_status[2]) if int(old_status[3]) <= self.next_cell_threshold: self.cell_iter = int(old_status[2]) + 1 if len(self.cell_sizes) > self.cell_iter: self.relax_max_atoms = self.cell_sizes[self.cell_iter] else: #pragma: no cover msg.err( "The MTP process has finished for the cell sizes " "specified in the YML file.") target1 = path.join(self.root, "unrelaxed.cfg") target2 = path.join(self.root, "to-relax.cfg") if path.isfile(target1): remove(target1) if path.isfile(target2): remove(target2) if self.iter_count >= self.iter_threshold: #pragma: no cover msg.err( "The number of iterations has exceeded " "the allowed number of {0}. To increase this limit " "use the iteration_threshold aption in the YML " "file.".format(self.iter_threshold)) else: self.iter_status = old_status[0] self.iter_count = int(old_status[1]) self.cell_iter = int(old_status[2]) #if we're at the start of a training iteration use the command to train the potential if self.iter_status == "train": self._make_train_cfg(self.iter_count) #remove the selected.cfg and rexaed.cfg from the last iteration if they exist if path.isfile(path.join(self.root, "new_training.cfg")): remove(path.join(self.root, "new_training.cfg")) if path.isfile(path.join(self.root, "relaxed.cfg")): remove(path.join(self.root, "relaxed.cfg")) if not path.isfile(path.join(self.root, "relax.ini")): self._make_relax_ini() if not path.isfile(path.join(self.root, "pot.mtp")): self._make_pot_initial() template = self._train_template() with open(path.join(self.root, "status.txt"), "w+") as f: f.write("relax_setup {0} {1}".format(self.iter_count, self.cell_iter)) if self.iter_status == "relax_setup": # If pot has been trained if path.isfile(path.join(self.root, "Trained.mtp_")): rename(path.join(self.root, "Trained.mtp_"), path.join(self.root, "pot.mtp")) # Calculate the grad of the training configurations. calc_grade = self._calc_grade_template() execute(calc_grade.split(), self.root) if path.isfile(path.join(self.root, "temp1.cfg")): remove(path.join(self.root, "temp1.cfg")) if not path.isfile(path.join(self.root, "state.mvs")): #pragma: no cover raise MlpError( "mlp failed to produce the 'state.mvs` file with command " "'mlp calc-grade pot.mtp train.cfg train.cfg temp1.cfg'") # if the unrelaxed.cfg file exists we need to move it to # replace the existing 'to-relax.cfg' otherwise we need to # create the 'to-relax.cfg' file. if path.isfile(path.join(self.root, "unrelaxed.cfg")) and self.use_unrelaxed: rename(path.join(self.root, "unrelaxed.cfg"), path.join(self.root, "to-relax.cfg")) self.iter_status = "relax" elif not path.isfile(path.join(self.root, "to-relax.cfg")): self._setup_to_relax_cfg() template = "matdb_mtp_to_relax.py > create-to-relax.txt" with open(path.join(self.root, "status.txt"), "w+") as f: f.write("relax {0} {1}".format(self.iter_count, self.cell_iter)) else: self.iter_status = "relax" if self.iter_status == "relax": # command to relax structures if path.isfile(path.join(self.root, "candidate.cfg")): remove(path.join(self.root, "candidate.cfg")) template = self._relax_template() with open(path.join(self.root, "status.txt"), "w+") as f: f.write("select {0} {1}".format(self.iter_count, self.cell_iter)) # if relaxation is done if self.iter_status == "select": cand_files = glob(path.join(self.root, "candidate.cfg_*")) cat(cand_files, path.join(self.root, "candidate.cfg")) for cfile in cand_files: remove(cfile) # command to select next training set. template = self._select_template() with open(path.join(self.root, "status.txt"), "w+") as f: f.write("add {0} {1}".format(self.iter_count, self.cell_iter)) if self.iter_status == "add": with chdir(self.root): # Now add the selected atoms to the Active database. # input filename sould always be entered before output filename execute([ "mlp", "convert-cfg", "new_training.cfg", "POSCAR", "--output-format=vasp-poscar" ], self.root) if path.isfile("new_training.cfg"): rename("new_training.cfg", "new_training.cfg_iter_{}".format(self.iter_count)) if path.isfile("relaxed.cfg"): rename("relaxed.cfg", "relaxed.cfg_iter_{}".format(self.iter_count)) new_configs = [] new_POSCARS = glob("POSCAR*") # Here We need to re-write the POSCARs so that they # have the correct species. for POSCAR in new_POSCARS: # We need to put the correct species into the # title of the POSCAR so that ASE can read it pos_file = [] with open(POSCAR, 'r') as f: for line in f: pos_file.append(line) pos_file[0] = "{0} : {1}".format(" ".join(self.species), pos_file[0]) with open(POSCAR, 'w+') as f: for line in pos_file: f.write(line) new_configs.append(Atoms(POSCAR, format="vasp")) remove(POSCAR) self.active.add_configs(new_configs, self.iter_count) self.active.setup() if len(self.active.configs ) != self.active.nconfigs: #pragma: no cover raise LogicError( "The active database failed to setup the calculations " "for iteration {0}".format(self.iter_count)) self.active.execute() with open(path.join(self.root, "status.txt"), "w+") as f: f.write("done {0} {1} {2}".format(self.iter_count, self.cell_iter, len(new_configs))) template = '' return template
def _cfgd_to_atoms(cfgd, species=None): """Converts a CFG dictionary to an atoms object. Args: cfgd (dict): dict of a single config extracted by :func:`cfg_to_xyz`. species (list): list of element names corresponding to the integer species in the CFG dictionary. """ from matdb.atoms import Atoms lattice = np.array(cfgd["Supercell"]["vals"]) natoms = cfgd["Size"]["vals"][0][0] stressdict = cfgd["PlusStress"] stress = {k: v for k, v in zip(stressdict["cols"], stressdict["vals"][0])} energy = cfgd["Energy"]["vals"][0][0] alabels = cfgd["AtomData"]["cols"] positions = [] forces = [] types = [] for entry in cfgd["AtomData"]["vals"]: vals = {k: v for k, v in zip(alabels, entry)} pos = [] force = [] types.append(species[vals["type"]]) for poslabel in _cfg_pos: pos.append(vals[poslabel]) positions.append(pos) for flabel in _cfg_force: force.append(vals[flabel]) forces.append(force) aseatoms = ase.Atoms(symbols=types, positions=np.array(positions), cell=lattice) aseatoms.calc = SinglePointCalculator(aseatoms, energy=energy, forces=np.array(forces), stress=order_stress(**stress)) aseatoms.get_total_energy() aseatoms.get_forces() aseatoms.get_stress() result = Atoms() result.copy_from(aseatoms) result.pbc = True prefix = "" if "EFS_by" in cfgd["features"]: prefix = "{}_".format(cfgd["features"]["EFS_by"][0].lower()) force_name, energy_name, virial_name = [ "{}{}".format(prefix, l) for l in ["force", "energy", "virial"] ] result.properties[force_name] = aseatoms.calc.results["forces"].T result.params[energy_name] = energy result.params[virial_name] = symmetrize(*aseatoms.calc.results["stress"]) assert result.n == natoms return result
def test_all_active(Act): """Tetsts the setup of the Active database. """ assert (Act.last_iteration is None) or (len(Act.last_iteration) == 0) assert (Act.last_config_atoms is None) or (len(Act.last_config_atoms) == 0) add_configs(Act, 1) assert not Act.can_extract() assert Act.iter_file == path.join(Act.root, "iter_1.pkl") assert Act.nconfigs == 3 assert not Act.is_executing() Act.setup() assert len(Act.last_iteration) == 3 folders = { "__files__": ["compute.pkl", "auids.pkl", "jobfile.sh", "index.json", "iter_1.pkl", "active_Ac_uuid.txt"], "Ac.1": { "__files__": ["INCAR", "PRECALC", "POSCAR", "POTCAR", "pre_comp_atoms.h5", "uuid.txt"] }, "Ac.2": { "__files__": ["INCAR", "PRECALC", "POSCAR", "POTCAR", "pre_comp_atoms.h5", "uuid.txt"] }, "Ac.3": { "__files__": ["INCAR", "PRECALC", "POSCAR", "POTCAR", "pre_comp_atoms.h5", "uuid.txt"] } } dbfolder = Act.root compare_tree(dbfolder,folders) assert Act.is_setup() assert not Act.ready() # We need to fake some VASP output so that we can cleanup the # database and get the rset src = relpath("./tests/data/Pd/complete/OUTCAR__DynMatrix_phonon_Pd_dim-2.00") dbfolder = Act.root for j in range(1,4): dest = path.join(dbfolder,"Ac.{}".format(j),"OUTCAR") symlink(src,dest) dbfolder = Act.root for j in range(1,4): src = path.join(dbfolder,"Ac.{}".format(j),"POSCAR") dest = path.join(dbfolder,"Ac.{}".format(j),"CONTCAR") symlink(src,dest) remove(path.join(Act.root, "Ac.1", "pre_comp_atoms.h5")) Act.extract() assert len(Act.config_atoms) == 3 assert len(Act.configs) == 3 assert len(Act.last_config_atoms) == 3 assert len(Act.rset) == 3 assert not Act.is_executing() remove(path.join(Act.root, "Ac.1", "OUTCAR")) dest = path.join(Act.root, "Ac.1", "OUTCAR") src = relpath("./tests/data/Pd/basic_fail/S.4/OUTCAR") symlink(src,dest) assert Act.is_executing() # should not be executable, because it's been executing assert not Act.execute() # test the addition of a second set of new configs # first config is to test if the exclusion of duplicates works. 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("Si",positions=[[0,0,0]], cell=[3,3,3]) configs.append(atSi) atSi = Atoms("Si2",positions=[[0,0,0], [0.5,0.75,0.25]], cell=[3.43,3.43,3.43]) configs.append(atSi) Act.add_configs(configs, 2) assert Act.iter_file == path.join(Act.root, "iter_2.pkl") assert Act.nconfigs == 6 assert not Act.is_executing() Act.setup() for cfg in Act.iconfigs: assert "Si" in cfg.get_chemical_symbols() assert Act.nconfigs == 5 assert len(Act.last_config_atoms) == 2 Act.iter_file = path.join(Act.root, "iter_1.pkl") Act._load_last_iter() assert len(Act.last_iteration) == 3