def test_magnetism_setup(): from jarvis.db.figshare import get_jid_data from jarvis.core.atoms import get_supercell_dims atoms = Atoms.from_dict( get_jid_data(jid="JVASP-78681", dataset="dft_3d")["atoms"] ) dim = get_supercell_dims(atoms) print("dim=", dim) dim = [2, 2, 2] symm_list, ss = get_unique_magnetic_structures( atoms, supercell_dim=dim, magnetic_ions=["Mn"] ) print("dim=", dim, len(symm_list)) assert len(symm_list)==5 assert ss.num_atoms == 16
def basic_data(data={}, source="JARVIS-FF-LAMMPS"): """Get basic data for table.""" info = {} info["id"] = data["jid"] info["source_folder"] = data["source_folder"] info["tmp_source_folder"] = "'" + data["source_folder"] + "'" info["tmp_id"] = "'" + data["jid"] + "'" ref = data["source_folder"].split("/")[-1].split("@")[1].split("_")[0] info["ref"] = "'" + ref + "'" info["jvid"] = get_jvid(ref) final_atoms = data["bulk_data"]["final_str"] initial_atoms = data["bulk_data"]["initial_str"] info["formula"] = final_atoms.composition.reduced_formula info["tmp_formula"] = "'" + final_atoms.composition.reduced_formula + "'" info["elements"] = ",".join(final_atoms.uniq_species) info["tmp_elements"] = "'" + ",".join(final_atoms.uniq_species) + "'" info["number_uniq_species"] = len(final_atoms.uniq_species) info["data_source"] = source info["tmp_data_source"] = "'" + source + "'" info["pair_style"] = data["bulk_data"]["pair_style"] info["pair_coeff"] = data["bulk_data"]["pair_coeff"] # info["pair_coeff"] = ( # '<a href="http://www.ctcms.nist.gov/~knc6/DOWNLOADS/' # + data["bulk_data"]["pair_coeff"] # + '.zip">' # + data["bulk_data"]["pair_coeff"] # + "</a>" # ) info["energy_per_atom"] = round( float(data["bulk_data"]["energy_per_atom"]), 3) info["pressure"] = round(float(data["bulk_data"]["system_pressure"]), 3) initial_spg = Spacegroup3D(initial_atoms) final_spg = Spacegroup3D(final_atoms) info["initial_spacegroup_number"] = initial_spg.space_group_number info["initial_spacegroup_symbol"] = initial_spg.space_group_symbol info["initial_pointgroup_symbol"] = initial_spg.point_group_symbol info["initial_crystal_system"] = initial_spg.crystal_system initial_lat_params = initial_atoms.lattice.parameters info["initial_a"] = round(initial_lat_params[0], 2) info["initial_b"] = round(initial_lat_params[1], 2) info["initial_c"] = round(initial_lat_params[2], 2) info["initial_alpha"] = round(initial_lat_params[3], 2) info["initial_beta"] = round(initial_lat_params[4], 2) info["initial_gamma"] = round(initial_lat_params[5], 2) info["initial_density"] = round(initial_atoms.density, 3) dim = get_supercell_dims(final_atoms) info["xyz"] = ( '"' + str(final_atoms.make_supercell_matrix(dim).get_xyz_string).replace( "\n", "\\n") + '"') info["final_str"] = ('"' + str(final_atoms.get_string()).replace("\n", "\\n") + '"') info["initial_str"] = ( '"' + str(initial_atoms.get_string()).replace("\n", "\\n") + '"') final_lat_params = final_atoms.lattice.parameters info["final_a"] = round(final_lat_params[0], 2) info["final_b"] = round(final_lat_params[1], 2) info["final_c"] = round(final_lat_params[2], 2) info["final_alpha"] = round(final_lat_params[3], 2) info["final_beta"] = round(final_lat_params[4], 2) info["final_gamma"] = round(final_lat_params[5], 2) info["final_density"] = round(final_atoms.density, 3) info["final_spacegroup_number"] = final_spg.space_group_number info["final_spacegroup_symbol"] = final_spg.space_group_symbol info["final_pointgroup_symbol"] = final_spg.point_group_symbol info["final_crystal_system"] = final_spg.crystal_system et = "" # print(data["bulk_data"]["elastic_tensor"]["raw_et_tensor"]) try: if data["bulk_data"]["elastic_tensor"] != "": cij = np.round( (data["bulk_data"]["elastic_tensor"]["raw_et_tensor"]), 2) et = ( '<cij>"' + ";".join([",".join(map(str, cij[:, i])) for i in range(0, 6)]) + '"</cij>') except Exception as exp: print("Cannot obtain elastic tensor data.", info["source_folder"], exp) pass info["elastic_tensor"] = et vacancy_line = "" if len(data["vacancy_info"]) != 0: for i in data["vacancy_info"]: vacancy_line += i[0] + "," + i[1] + "," + str(round(i[2], 3)) + ";" info["vacancy_info"] = '"' + vacancy_line + '"' surf_line = "" if len(data["surface_info"]) != 0: for i in data["surface_info"]: surf_line += i[0] + "," + str(round(i[1], 3)) + ";" info["surface_info"] = '"' + surf_line + '"' phonon_band_line = "" try: # Band frequencies = data["band_frequencies"] distances = data["band_distances"] labels = data["band_labels"] label_points = data["band_label_points"] tmp = "" for i in range(np.array(frequencies).shape[1]): tmp += ",".join(map(str, np.array(frequencies)[:, i])) + ";" phonon_band_line += ("<phonon_bandstructure_distances>'" + ",".join(map(str, distances)) + "'</phonon_bandstructure_distances>") phonon_band_line += ("<phonon_bandstructure_frequencies>'" + tmp + "'</phonon_bandstructure_frequencies>") phonon_band_line += ("<phonon_bandstructure_labels>'" + ",".join(map(str, labels)) + "'</phonon_bandstructure_labels>") phonon_band_line += ("<phonon_bandstructure_label_points>'" + ",".join(map(str, label_points)) + "'</phonon_bandstructure_label_points>") except Exception as exp: print("Cannot obtain phonon band data.", exp) # Comment until 4 MB text size error info["phonon_band_line"] = phonon_band_line phonon_dos_line = "" try: freq = data["dos_freq"] pdos = data["dos_intensity"] phonon_dos_line += ("<phonon_dos_frequencies>'" + ",".join(map(str, freq)) + "'</phonon_dos_frequencies>") phonon_dos_line += ("<phonon_dos_intensity>'" + ",".join(map(str, pdos)) + "'</phonon_dos_intensity>") except Exception: print("Cannot obtain phonon dod data.") pass info["phonon_dos_line"] = phonon_dos_line return info
def from_atoms( atoms=None, get_prim=False, zero_diag=False, node_atomwise_angle_dist=False, node_atomwise_rdf=False, features="basic", enforce_c_size=10.0, max_n=100, max_cut=5.0, verbose=False, make_colormap=True, ): """ Get Networkx graph. Requires Networkx installation. Args: atoms: jarvis.core.Atoms object. rcut: cut-off after which distance will be set to zero in the adjacency matrix. features: Node features. 'atomic_number': graph with atomic numbers only. 'cfid': 438 chemical descriptors from CFID. 'basic':10 features 'atomic_fraction': graph with atomic fractions in 103 elements. array: array with CFID chemical descriptor names. See: jarvis/core/specie.py enforce_c_size: minimum size of the simulation cell in Angst. """ if get_prim: atoms = atoms.get_primitive_atoms dim = get_supercell_dims(atoms=atoms, enforce_c_size=enforce_c_size) atoms = atoms.make_supercell(dim) adj = np.array(atoms.raw_distance_matrix.copy()) # zero out edges with bond length greater than threshold adj[adj >= max_cut] = 0 if zero_diag: np.fill_diagonal(adj, 0.0) nodes = np.arange(atoms.num_atoms) if features == "atomic_number": node_attributes = np.array( [[np.array(Specie(i).Z)] for i in atoms.elements], dtype="float", ) if features == "atomic_fraction": node_attributes = [] fracs = atoms.composition.atomic_fraction_array for i in fracs: node_attributes.append(np.array([float(i)])) node_attributes = np.array(node_attributes) elif features == "basic": feats = [ "Z", "coulmn", "row", "X", "atom_rad", "nsvalence", "npvalence", "ndvalence", "nfvalence", "first_ion_en", "elec_aff", ] node_attributes = [] for i in atoms.elements: tmp = [] for j in feats: tmp.append(Specie(i).element_property(j)) node_attributes.append(tmp) node_attributes = np.array(node_attributes, dtype="float") elif features == "cfid": node_attributes = np.array( [np.array(Specie(i).get_descrp_arr) for i in atoms.elements], dtype="float", ) elif isinstance(features, list): node_attributes = [] for i in atoms.elements: tmp = [] for j in features: tmp.append(Specie(i).element_property(j)) node_attributes.append(tmp) node_attributes = np.array(node_attributes, dtype="float") else: print("Please check the input options.") if node_atomwise_rdf or node_atomwise_angle_dist: nbr = NeighborsAnalysis(atoms, max_n=max_n, verbose=verbose, max_cut=max_cut) if node_atomwise_rdf: node_attributes = np.concatenate( (node_attributes, nbr.atomwise_radial_dist()), axis=1) node_attributes = np.array(node_attributes, dtype="float") if node_atomwise_angle_dist: node_attributes = np.concatenate( (node_attributes, nbr.atomwise_angle_dist()), axis=1) node_attributes = np.array(node_attributes, dtype="float") # construct edge list uv = [] edge_features = [] for ii, i in enumerate(atoms.elements): for jj, j in enumerate(atoms.elements): bondlength = adj[ii, jj] if bondlength > 0: uv.append((ii, jj)) edge_features.append(bondlength) edge_attributes = edge_features if make_colormap: sps = atoms.uniq_species color_dict = random_colors(number_of_colors=len(sps)) new_colors = {} for i, j in color_dict.items(): new_colors[sps[i]] = j color_map = [] for ii, i in enumerate(atoms.elements): color_map.append(new_colors[i]) return Graph( nodes=nodes, edges=uv, node_attributes=np.array(node_attributes), edge_attributes=np.array(edge_attributes), color_map=color_map, )
def test_basic_atoms(): box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]] coords = [[0, 0, 0], [0.25, 0.2, 0.25]] elements = ["Si", "Si"] Si = Atoms(lattice_mat=box, coords=coords, elements=elements) dim = get_supercell_dims(Si) assert dim == [3, 3, 3] polar = Si.check_polar Si.props = ["a", "a"] vac_pad = VacuumPadding(Si) den_2d = round(vac_pad.get_effective_2d_slab().density, 2) den_0d = round(vac_pad.get_effective_molecule().density, 2) den_lll_red = round(Si.get_lll_reduced_structure().density, 2) strng = Si.get_string() scell_nat = Si.make_supercell([2, 2, 2]).num_atoms scell_nat2 = Si.make_supercell_matrix([[2, 0, 0], [0, 2, 0], [0, 0, 2]]).num_atoms # print("scell_nat,scell_nat2", scell_nat, scell_nat2) # print(Si.make_supercell([2, 2, 2])) # print() # print(Si.make_supercell_matrix([[2, 0, 0], [0, 2, 0], [0, 0, 2]])) com = round(Si.get_center_of_mass()[0], 3) rem = (Si.make_supercell([2, 2, 2]).remove_site_by_index(site=0)).num_atoms prim = Si.get_primitive_atoms print(prim.cart_coords) assert round(prim.cart_coords[0][0], 2) == round(4.37815150, 2) # print ('raw_distance_matrix', prim.raw_distance_matrix) # print ('raw_distance_matrix', Si.raw_distance_matrix) # print ('distance_matrix', Si.pymatgen_converter().distance_matrix) assert round(prim.raw_distance_matrix[0][1], 2) == round(4.42386329832851, 2) print(prim.raw_angle_matrix) d = Si.to_dict() new_at = Atoms.from_dict(d) angs_a = d["angles"][0] Si_2_den = Atoms( lattice_mat=d["lattice_mat"], coords=d["coords"], elements=d["elements"], ).density Si_xyz = Si.get_xyz_string Si.write_xyz(filename="atoms.xyz") tmp = Atoms.from_xyz(filename="atoms.xyz") cmd = 'rm atoms.xyz' os.system(cmd) Si.center_around_origin() # print ('scell_nat', Si_2) assert ( round(Si.volume, 2), Si.atomic_numbers, Si.num_atoms, Si.frac_coords[0][0], Si.cart_coords[0][0], round(Si.density, 2), Si.spacegroup(), Si.pymatgen_converter() != {}, polar, Si.props[0], den_2d, den_0d, round(Si.packing_fraction, 2), Si.composition.to_dict(), strng != "", den_lll_red, scell_nat, com, rem, angs_a, round(Si_2_den, 2), ) == ( 40.03, [14, 14], 2, 0, 0.0, 2.33, "C2/m (12)", True, False, "a", 0.35, 0.01, 0.28, { "Si": 2 }, True, 2.33, 16, 0.679, 15, 60.0, 2.33, ) cc = Si.center() cc = Si.center(axis=[0, 0, 1]) m1 = Atoms.from_dict(get_jid_data("JVASP-6640")["atoms"]) assert m1.check_polar == True print("Strain test") print(m1) m1.apply_strain(0.1) print(m1) assert m1.lattice_mat[2][2] == 32.8717576 m1.apply_strain([0, 0, 0.1]) assert m1.lattice_mat[2][2] == 36.158933360000006 filename = "atoms.cif" m1.write_cif(filename) a = Atoms.from_cif(filename) filename = "POSCAR" m1.write_poscar(filename) m2 = Atoms.from_poscar(filename) filename = "atoms.xyz" m1.write_xyz(filename) m3 = Atoms.from_xyz(filename) cmd = "rm atoms.xyz POSCAR atoms.cif" os.system(cmd)
def all_props_eam_alloy( self, atoms=None, ff_path="", lammps_cmd="", enforce_conventional_structure=True, enforce_c_size=0, extend=1, ): """ Provide generic function for LAMMPS calculations using eam/alloy. Must provide Atoms class and path to force-field. Args: atoms : Atoms object ff_path : inter-atomic potential path lammps_cmd : LAMMPS executable path enforce_conventional_structure : whether to enforce conventional cell enforce_c_size : minimum cell-sizes extend : used for round-off during making supercells """ if enforce_conventional_structure: atoms = Spacegroup3D(atoms).conventional_standard_structure if enforce_c_size is not None: dim = get_supercell_dims(atoms, enforce_c_size=enforce_c_size) atoms = atoms.make_supercell([dim[0], dim[1], dim[2]]) self.pair_style = "eam/alloy" self.pair_coeff = ff_path parameters = { "pair_style": self.pair_style, "atom_style": "charge", "pair_coeff": self.pair_coeff, } parameters["control_file"] = "inelast.mod" en, final_str, forces = LammpsJob( atoms=atoms, jobname="ELASTIC", parameters=parameters, lammps_cmd=lammps_cmd, ).runjob() print("en, final_str, forces", en, final_str, forces) indices = symmetrically_distinct_miller_indices(max_index=1, cvn_atoms=atoms) for i in indices: surf = Surface(atoms=final_str, indices=i).make_surface() jobname = str("Surf-") + str("_".join(map(str, i))) en2, final_str2, forces2 = LammpsJob( atoms=surf, jobname=jobname, parameters=parameters, lammps_cmd=lammps_cmd, ).runjob() # sys.exit() v = Vacancy(atoms=final_str).generate_defects(enforce_c_size=5) print("vacs=", v) for i, ii in enumerate(v): jobname = (str("symbol-") + str(ii._symbol) + str("-") + str("Wycoff-") + str(ii._wyckoff_multiplicity)) print("ii._defect_structure", ii._atoms) en2, final_str2, forces2 = LammpsJob( atoms=ii._defect_structure, jobname=jobname, parameters=parameters, lammps_cmd=lammps_cmd, ).runjob() self.phonons(atoms=atoms, lammps_cmd=lammps_cmd, parameters=parameters)
def phonons(self, atoms=None, lammps_cmd="", enforce_c_size=15.0, parameters={}): """Make Phonon calculation setup.""" from phonopy import Phonopy from phonopy.file_IO import ( # parse_FORCE_CONSTANTS, write_FORCE_CONSTANTS, ) bulk = atoms.phonopy_converter() dim = get_supercell_dims(atoms, enforce_c_size=enforce_c_size) atoms = atoms.make_supercell([dim[0], dim[1], dim[2]]) Poscar(atoms).write_file("POSCAR") atoms = atoms.make_supercell_matrix([dim[0], dim[1], dim[2]]) Poscar(atoms).write_file("POSCAR-Super.vasp") phonon = Phonopy(bulk, [[dim[0], 0, 0], [0, dim[1], 0], [0, 0, dim[2]]]) print("[Phonopy] Atomic displacements1:", bulk) print("[Phonopy] Atomic displacements2:", phonon, dim[0], dim[1], dim[2]) phonon.generate_displacements(distance=0.03) disps = phonon.get_displacements() print("[Phonopy] Atomic displacements3:", disps) for d in disps: print("[Phonopy]", d[0], d[1:]) supercells = phonon.get_supercells_with_displacements() # Force calculations by calculator set_of_forces = [] disp = 0 from ase import Atoms as AseAtoms for scell in supercells: ase_atoms = AseAtoms( symbols=scell.get_chemical_symbols(), scaled_positions=scell.get_scaled_positions(), cell=scell.get_cell(), pbc=True, ) j_atoms = ase_to_atoms(ase_atoms) disp = disp + 1 parameters["control_file"] = "run0.mod" a, b, forces = LammpsJob( atoms=j_atoms, lammps_cmd=lammps_cmd, parameters=parameters, jobname="disp-" + str(disp), ).runjob() print("forces=", forces) drift_force = forces.sum(axis=0) print("drift forces=", drift_force) # Simple translational invariance for force in forces: force -= drift_force / forces.shape[0] set_of_forces.append(forces) phonon.produce_force_constants(forces=set_of_forces) write_FORCE_CONSTANTS(phonon.get_force_constants(), filename="FORCE_CONSTANTS") print() print("[Phonopy] Phonon frequencies at Gamma:")