def test_mgo_sto3g_scf(): content = read_resource_text("crystal", "mgo_sto3g_scf", "INPUT") output_dict, basis_sets, atom_props = extract_data(content) assert len(basis_sets) == 2 assert atom_props == {} assert output_dict == {"scf": {"k_points": (8, 8)}, "title": "MgO bulk"}
def stdin(input_file, keys, fmt): """Parse an existing stdin (d12) file, created from a crystal run.""" from aiida_crystal17.parsers.raw.inputd12_read import extract_data with io.open(input_file) as handle: data, bases, atom_props = extract_data(handle.read()) if keys is not None: data = {k: v for k, v in data.items() if k in keys} options.echo_dictionary(data, fmt=fmt)
def test_mgo_sto3g_opt(): content = read_resource_text("crystal", "mgo_sto3g_opt", "INPUT") output_dict, basis_sets, atom_props = extract_data(content) assert len(basis_sets) == 2 assert atom_props == {} assert output_dict == { "geometry": { "optimise": { "type": "FULLOPTG" } }, "scf": { "k_points": (8, 8) }, "title": "MgO bulk", }
def test_nio_sto3g_afm(): content = read_resource_text("crystal", "nio_sto3g_afm_scf", "INPUT") output_dict, basis_sets, atom_props = extract_data(content) assert len(basis_sets) == 2 assert atom_props == {"spin_alpha": [1], "spin_beta": [2]} assert output_dict == { "scf": { "single": "UHF", "numerical": { "FMIXING": 30 }, "post_scf": ["PPAN"], "spinlock": { "SPINLOCK": [0, 15] }, "k_points": (8, 8), }, "title": "NiO Bulk with AFM spin", }
def populate_builder(remote_data, code=None, metadata=None): """create ``crystal17.main`` input nodes from an existing run NB: none of the nodes are stored, also existing basis will be retrieved if availiable Parameters ---------- folder: aiida.common.folders.Folder or str folder containing the input and output files remote_data: aiida.orm.RemoteData containing the input and output files required for parsing code: str or aiida.orm.nodes.data.code.Code or None metadata: dict or None calculation metadata Returns ------- aiida.engine.processes.ProcessBuilder """ calc_cls = CalculationFactory("crystal17.main") basis_cls = DataFactory("crystal17.basisset") struct_cls = DataFactory("structure") symmetry_cls = DataFactory("crystal17.symmetry") kind_cls = DataFactory("crystal17.kinds") # get files in_file_name = calc_cls.spec_options.get("input_file_name").default out_file_name = calc_cls.spec_options.get("output_main_file_name").default if metadata and "options" in metadata: in_file_name = metadata["options"].get("input_file_name", in_file_name) out_file_name = metadata["options"].get("output_main_file_name", out_file_name) remote_files = remote_data.listdir() if in_file_name not in remote_files: raise IOError( "The input file '{}' is not contained in the remote_data folder. " "If it has a different name, change " "metadata['options]['input_file_name']".format(in_file_name)) if out_file_name not in remote_files: raise IOError( "The output file '{}' is not contained in the remote_data folder. " "If it has a different name, change " "metadata['options]['output_main_file_name']".format( out_file_name)) with SandboxFolder() as folder: remote_data.getfile(in_file_name, os.path.join(folder.abspath, in_file_name)) with folder.open(in_file_name, mode="r") as handle: param_dict, basis_sets, atom_props = extract_data(handle.read()) remote_data.getfile(out_file_name, os.path.join(folder.abspath, out_file_name)) with folder.open(out_file_name, mode="r") as handle: try: data = crystal_stdout.read_crystal_stdout(handle.read()) except IOError as err: raise OutputParsingError( "Error in CRYSTAL 17 run output: {}".format(err)) # we retrieve the initial primitive geometry and symmetry atoms = _create_atoms(data, "initial_geometry") # convert fragment (i.e. unfixed) to fixed if "fragment" in atom_props: frag = atom_props.pop("fragment") atom_props["fixed"] = [ i + 1 for i in range(atoms.get_number_of_atoms()) if i + 1 not in frag ] atoms.set_tags(_create_tags(atom_props, atoms)) structure = struct_cls(ase=atoms) if atom_props: kind_names = structure.get_kind_names() kinds_dict = {"kind_names": kind_names} for key, atom_indexes in atom_props.items(): kv_map = { kn: i + 1 in atom_indexes for i, kn in enumerate(structure.get_site_kindnames()) } kinds_dict[key] = [kv_map[kn] for kn in kind_names] kinds = kind_cls(data=kinds_dict) else: kinds = None symmetry = symmetry_cls( data={ "operations": data["initial_geometry"]["primitive_symmops"], "basis": "fractional", "hall_number": None, }) bases = {} for bset in basis_sets: bfile = tempfile.NamedTemporaryFile(delete=False) try: with open(bfile.name, "w") as f: f.write(bset) bdata, _ = basis_cls.get_or_create(bfile.name, use_first=False, store_basis=False) # TODO report if bases created or retrieved finally: os.remove(bfile.name) bases[bdata.element] = bdata builder = calc_cls.create_builder( param_dict, structure, bases, symmetry=symmetry, kinds=kinds, code=code, metadata=metadata, ) return builder
def test_full_read(cry_stdin_str): output_dict, basis_sets, atom_props = extract_data(cry_stdin_str) assert len(basis_sets) == 2 assert atom_props == { "fragment": [1, 3], "ghosts": [5, 6], "spin_alpha": [1, 3], "spin_beta": [2, 4], } expected = { "title": "a title", "geometry": { "info_print": ["ATOMSYMM", "SYMMOPS"], "info_external": ["STRUCPRT"], "ROTCRY": [[1.0, 0, 0], [0, 1, 0], [0, 0, -1]], "optimise": { "type": "FULLOPTG", "hessian": "HESSIDEN", "gradient": "NUMGRATO", "info_print": ["PRINTOPT", "PRINTFORCES"], "convergence": { "TOLDEG": 0.0003, "TOLDEX": 0.0012, "TOLDEE": 7, "MAXCYCLE": 50, "FINALRUN": 4, }, }, }, "basis_set": { "CHARGED": True, }, "scf": { "dft": { "xc": ["LDA", "PZ"], # or # "xc": "HSE06", # or # "xc": { # "LSRSH-PBE": [0.11, 0.25, 0.00001] # }, "SPIN": True, "grid": "XLGRID", "grid_weights": "BECKE", "numerical": { "TOLLDENS": 6, "TOLLGRID": 14, "LIMBEK": 400 }, }, # or # "single": "UHF", "k_points": [8, 8], "numerical": { "BIPOLAR": [18, 14], "BIPOSIZE": 4000000, "EXCHSIZE": 4000000, "EXCHPERM": True, "ILASIZE": 6000, "INTGPACK": 0, "MADELIND": 50, "POLEORDR": 4, "TOLINTEG": [6, 6, 6, 6, 12], "TOLPSEUD": 6, "FMIXING": 0, "MAXCYCLE": 50, "TOLDEE": 6, "LEVSHIFT": [2, 1], "SMEAR": 0.1, }, "fock_mixing": "DIIS", # or # "fock_mixing": ["BROYDEN", 0.0001, 50, 2], "spinlock": { "SPINLOCK": [1, 10] }, "post_scf": ["GRADCAL", "PPAN"], }, } assert edict.diff(output_dict, expected) == {}
def test_read_fail(cry_stdin_str): cry_stdin_str = cry_stdin_str.replace("PPAN", "WRONG") with pytest.raises(NotImplementedError): extract_data(cry_stdin_str)