diff --git a/dev-requirements.txt b/dev-requirements.txt index 24318802..b4042d17 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -49,7 +49,7 @@ Jinja2==3.0.3 joblib==1.1.0 jsonschema==4.3.1 julia==0.5.6 -keras==2.7.0 +keras Keras-Preprocessing==1.1.2 kiwisolver==1.3.2 libclang==12.0.0 @@ -63,7 +63,7 @@ mpmath==1.2.1 multitasking==0.0.10 networkx==2.6.3 ntlm-auth==1.5.0 -numpy==1.21.0 +numpy==1.20.0 oauthlib==3.1.1 opencv-python==4.5.4.60 opt-einsum==3.3.0 @@ -72,7 +72,7 @@ pandas==1.3.5 pbr==5.8.0 PennyLane==0.14.1 phonopy==2.10.0 -Pillow==9.0.0 +Pillow==9.0.1 pluggy==1.0.0 ply==3.11 protobuf==3.19.1 @@ -125,10 +125,10 @@ sphinxcontrib-serializinghtml==1.1.5 stevedore==3.5.0 symengine==0.8.1 sympy==1.9 -tensorboard==2.7.0 +tensorboard tensorboard-data-server==0.6.1 tensorboard-plugin-wit==1.8.0 -tensorflow==2.7.0 +tensorflow==2.8.0 tensorflow-estimator==2.7.0 tensorflow-io-gcs-filesystem==0.23.1 termcolor==1.1.0 @@ -148,4 +148,4 @@ Werkzeug==2.0.2 wrapt==1.13.3 xmltodict==0.12.0 yfinance==0.1.67 -zipp==3.6.0 +zipp==3.6.0 \ No newline at end of file diff --git a/docs/requirements.txt b/docs/requirements.txt index 01630a2f..c4f22595 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -50,7 +50,7 @@ Jinja2==3.0.3 joblib==1.1.0 jsonschema==4.3.1 julia==0.5.6 -keras==2.7.0 +keras Keras-Preprocessing==1.1.2 kiwisolver==1.3.2 libclang==12.0.0 @@ -64,7 +64,7 @@ mpmath==1.2.1 multitasking==0.0.10 networkx==2.6.3 ntlm-auth==1.5.0 -numpy==1.21.0 +numpy==1.20.0 oauthlib==3.1.1 opencv-python==4.5.4.60 opt-einsum==3.3.0 @@ -73,7 +73,7 @@ pandas==1.3.5 pbr==5.8.0 PennyLane==0.14.1 #phonopy==2.10.0 -Pillow==9.0.0 +Pillow==9.0.1 pluggy==1.0.0 ply==3.11 protobuf==3.19.1 @@ -127,7 +127,7 @@ sphinxcontrib-serializinghtml==1.1.5 stevedore==3.5.0 symengine==0.8.1 sympy==1.9 -tensorboard==2.7.0 +tensorboard tensorboard-data-server==0.6.1 tensorboard-plugin-wit==1.8.0 tensorflow==2.7.0 @@ -150,4 +150,4 @@ Werkzeug==2.0.2 wrapt==1.13.3 xmltodict==0.12.0 yfinance==0.1.67 -zipp==3.6.0 +zipp==3.6.0 \ No newline at end of file diff --git a/docs/source/publications.rst b/docs/source/publications.rst index ba77b38a..fd04b087 100644 --- a/docs/source/publications.rst +++ b/docs/source/publications.rst @@ -58,8 +58,28 @@ JARVIS-ML related [23. Enhancing materials property prediction by leveraging computational and experimental data using deep transfer learning, Nature Commun.](https://www.nature.com/articles/s41467-019-13297-w) -[24. Atomistic Line Graph Neural Network for Improved Materials Property Predictions.](https://arxiv.org/abs/2106.01829) +[24. Atomistic Line Graph Neural Network for Improved Materials Property Predictions, npj Computational Materials 7, 1 (2021)](https://www.nature.com/articles/s41524-021-00650-1) + +[25. Recent advances and applications of deep learning methods in materials science, npj Computational Materials 8, 1 (2022)](https://www.nature.com/articles/s41524-022-00734-6) + + +[26. Graph neural network predictions of metal organic framework CO2 adsorption properties, Comp. Mat. Sci., 210, 111388 (2022)](https://www.sciencedirect.com/science/article/pii/S092702562200163X) + +[27. Data-Driven Multi-Scale Modeling and Optimization for Elastic Properties of Cubic Microstructures](https://link.springer.com/article/10.1007/s40192-022-00258-3) + +[28. Uncertainty Prediction for Machine Learning Models of Material Properties](https://pubs.acs.org/doi/abs/10.1021/acsomega.1c03752) + +[29. Cross-property deep transfer learning framework for enhanced predictive analytics on small materials data](https://www.nature.com/articles/s41467-021-26921-5) + +[30. Prediction of the Electron Density of States for Crystalline Compounds with Atomistic Line Graph Neural Networks (ALIGNN)](https://link.springer.com/article/10.1007/s11837-022-05199-y) + +[31. Designing High-Tc Superconductors with BCS-inspired Screening, Density Functional Theory and Deep-learning](https://arxiv.org/abs/2205.00060) JARVIS-QC related ----------------------------------------------------- -[25. Quantum Computation for Predicting Electron and Phonon Properties of Solids., J. Phys.: Cond. Matt.](https://iopscience.iop.org/article/10.1088/1361-648X/ac1154) +[32. Quantum Computation for Predicting Electron and Phonon Properties of Solids., J. Phys.: Cond. Matt.](https://iopscience.iop.org/article/10.1088/1361-648X/ac1154) + + +JARVIS-QETB related +----------------------------------------------------- +[33. Quantum Computation for Predicting Electron and Phonon Properties of Solids., J. Phys.: Cond. Matt.](https://iopscience.iop.org/article/10.1088/1361-648X/ac1154) diff --git a/jarvis/__init__.py b/jarvis/__init__.py index 0ea93eab..49ec1ddb 100644 --- a/jarvis/__init__.py +++ b/jarvis/__init__.py @@ -1,5 +1,5 @@ """Version number.""" -__version__ = "2022.01.10" +__version__ = "2022.05.05" import os diff --git a/jarvis/analysis/elastic/tensor.py b/jarvis/analysis/elastic/tensor.py index b902920a..39723475 100644 --- a/jarvis/analysis/elastic/tensor.py +++ b/jarvis/analysis/elastic/tensor.py @@ -44,6 +44,49 @@ def reuss_modulus(self): ) return [Kr, Gr] + def long_velocity(self, atoms=None): + """Longitudinal velocity using Navier equation.""" + # density = atoms.density + weight = float(atoms.composition.weight) + volume = atoms.volume + mass_density = 1.6605e3 * weight / volume + avg_mod = self.average_modulus + k_vrh = avg_mod[0] + g_vrh = avg_mod[1] + # 1e9:= GPa to Pascal (kg/ms^2) + vel = np.sqrt(1e9 * (k_vrh + 4.0 / 3.0 * g_vrh) / mass_density) + return vel + + def trans_velocity(self, atoms=None): + """Transverse velocity.""" + avg_mod = self.average_modulus + g_vrh = avg_mod[1] + volume = atoms.volume + weight = float(atoms.composition.weight) + mass_density = 1.6605e3 * weight / volume + vel = np.sqrt(1e9 * g_vrh / mass_density) + return vel + + def velocity_average(self, atoms=None): + """Average velocity.""" + vt = self.trans_velocity(atoms=atoms) + vl = self.long_velocity(atoms=atoms) + return 1.0 / ( + np.cbrt( + (1.0 / 3.0) * (2.0 / (vt * vt * vt) + 1.0 / (vl * vl * vl)) + ) + ) + + def debye_temperature(self, atoms=None): + """Debye temperature.""" + const = 1.05457e-34 / 1.38065e-23 # (h/kb) + v0 = atoms.volume * 1e-30 / atoms.num_atoms + vl = self.long_velocity(atoms=atoms) + vt = self.trans_velocity(atoms=atoms) + vm = 3 ** (1.0 / 3.0) * (1 / vl ** 3 + 2 / vt ** 3) ** (-1.0 / 3.0) + theta = const * vm * (6 * np.pi ** 2 / v0) ** (1.0 / 3.0) + return theta + @property def average_modulus(self): """Get average modulus.""" @@ -51,6 +94,44 @@ def average_modulus(self): np.array(self.voigt_modulus) + np.array(self.reuss_modulus) ) / 2 + @property + def pugh_ratio_voigt(self): + """Get Voigt Pugh ratio.""" + Kv, Gv = self.voigt_modulus + return Gv / Kv + + @property + def pettifor_criteria(self): + """Get Pettifor criteria.""" + c = self.et_tensor + return c[0][1] - c[3][3] + + @property + def is_brittle(self): + """Check if brittle material.""" + return self.pugh_ratio_voigt > 0.571 and self.pettifor_criteria < 0 + + @property + def is_ductile(self): + """Check if ductile material.""" + return self.pugh_ratio_voigt < 0.571 and self.pettifor_criteria > 0 + + @property + def melting_temperature_metals(self): + """Get crude Melting temp. estimate.""" + # https://doi.org/10.1016/0036-9748(84)90267-9 + avg_mod = self.average_modulus + k_vrh = avg_mod[0] + return 607 + 9.3 * k_vrh + + @property + def cauchy_pressure(self): + """Get Cauchy pressure.""" + # >0 ionic bonding + # <0 covalent bonding + c = self.et_tensor + return c[0][1] - c[3][3] + @property def poisson_ratio(self): """Get poisson's ratio.""" diff --git a/jarvis/core/atoms.py b/jarvis/core/atoms.py index 866ce9c0..d7dcfd59 100644 --- a/jarvis/core/atoms.py +++ b/jarvis/core/atoms.py @@ -870,7 +870,9 @@ def atomwise_angle_and_radial_distribution( and nbor_info["dist"][in1][i] * nbor_info["dist"][in2][i] != 0 ] ang_hist, ang_bins = np.histogram( - angles, bins=np.arange(1, nbins + 2, 1), density=False, + angles, + bins=np.arange(1, nbins + 2, 1), + density=False, ) for jj, j in enumerate(angles): actual_pangs[i, jj] = j @@ -1648,13 +1650,13 @@ def pmg_to_atoms(pmg=""): ) -def ase_to_atoms(ase_atoms=""): +def ase_to_atoms(ase_atoms="", cartesian=True): """Convert ase structure to Atoms.""" return Atoms( lattice_mat=ase_atoms.get_cell(), elements=ase_atoms.get_chemical_symbols(), coords=ase_atoms.get_positions(), - # pbc=True, + cartesian=cartesian, ) diff --git a/jarvis/core/utils.py b/jarvis/core/utils.py index 385bab60..a777f3dd 100644 --- a/jarvis/core/utils.py +++ b/jarvis/core/utils.py @@ -17,6 +17,15 @@ def xml_to_dict(fname): return data +def get_factors(x, start=2): + """Get factors of a number.""" + facts = [] + for i in range(start, x + 1): + if x % i == 0: + facts.append(i) + return facts + + def get_counts(array=["W", "W", "Mo", "Mo", "S", "S"]): """ Get number of unique elements and their counts. @@ -266,14 +275,7 @@ def digitize_array(values=[], max_len=10): def bond_angle( - dist1, - dist2, - bondx1, - bondx2, - bondy1, - bondy2, - bondz1, - bondz2, + dist1, dist2, bondx1, bondx2, bondy1, bondy2, bondz1, bondz2, ): """Get an angle.""" nm = dist1 * dist2 diff --git a/jarvis/io/qe/inputs.py b/jarvis/io/qe/inputs.py index d344cc68..d0e124ef 100644 --- a/jarvis/io/qe/inputs.py +++ b/jarvis/io/qe/inputs.py @@ -4,6 +4,8 @@ import requests import tarfile from jarvis.core.specie import Specie +import numpy as np +# from jarvis.analysis.structure.spacegroup import Spacegroup3D class QEinfile(object): @@ -16,7 +18,14 @@ class QEinfile(object): """ def __init__( - self, atoms=None, kpoints=None, psp_dir=None, input_params={}, url=None + self, + atoms=None, + kpoints=None, + psp_dir=None, + input_params={}, + url=None, + sanitize=True, + sanitize_tol=2e-4, ): """Initialize input parameters for qunatum espresso.""" if input_params == {}: @@ -47,6 +56,8 @@ def __init__( self.input_params = input_params self.atoms = atoms self.kpoints = kpoints + self.sanitize = sanitize + self.sanitize_tol = sanitize_tol if "system" in input_params: self.system_params = input_params["system"] if ( @@ -93,6 +104,11 @@ def __init__( else: self.control_params = {} + if "inputa2f" in input_params: + self.inputa2f = input_params["inputa2f"] + else: + self.inputa2f = {} + if "ions" in input_params: self.ion_params = input_params["ions"] else: @@ -187,33 +203,86 @@ def atomic_species_string(self): ) return line + def check_frac(self, n): + """Check fractional coordinates or lattice parameters.""" + items = [ + 0.0, + 0.3333333333333333, + 0.25, + 0.5, + 0.75, + 0.6666666666666667, + 1.0, + 1.5, + 2.0, + -0.5, + -2.0, + -1.5, + -1.0, + 1.0 / 2.0 ** 0.5, + -1.0 / 2.0 ** 0.5, + 3.0 ** 0.5 / 2.0, + -(3.0 ** 0.5) / 2.0, + 1.0 / 3.0 ** 0.5, + -1.0 / 3.0 ** 0.5, + 1.0 / 2.0 / 3 ** 0.5, + -1.0 / 2.0 / 3 ** 0.5, + 1 / 6, + 5 / 6, + ] + items = items + [(-1) * i for i in items] + for f in items: + if abs(f - n) < self.sanitize_tol: + return f + return n + def atomic_pos(self): """Obtain string for QE atomic positions.""" line = "" - for i, j in zip(self.atoms.elements, self.atoms.frac_coords): + # self.atoms = Spacegroup3D(self.atoms).refined_atoms + coords = np.array(self.atoms.frac_coords) + ntot = self.atoms.num_atoms + + if self.sanitize: + for i in range(ntot): + for j in range(3): # neatin + coords[i, j] = self.check_frac(coords[i, j]) + + for i, j in zip(self.atoms.elements, coords): line = line + str(i) + " " + " ".join(map(str, j)) + "\n" return line def atomic_cell_params(self): """Obtain string for QE atomic lattice parameters.""" + lat_mat = np.array(self.atoms.lattice_mat) + if self.sanitize: + print("Sanitizing Atoms.") + a_lat = np.linalg.norm(lat_mat[0, :]) + at = lat_mat / a_lat + for i in range(3): + for j in range(3): + at[i, j] = self.check_frac(at[i, j]) + + lat_mat = at * a_lat + line = ( - str(self.atoms.lattice_mat[0][0]) + str(lat_mat[0][0]) + " " - + str(self.atoms.lattice_mat[0][1]) + + str(lat_mat[0][1]) + " " - + str(self.atoms.lattice_mat[0][2]) + + str(lat_mat[0][2]) + "\n" - + str(self.atoms.lattice_mat[1][0]) + + str(lat_mat[1][0]) + " " - + str(self.atoms.lattice_mat[1][1]) + + str(lat_mat[1][1]) + " " - + str(self.atoms.lattice_mat[1][2]) + + str(lat_mat[1][2]) + "\n" - + str(self.atoms.lattice_mat[2][0]) + + str(lat_mat[2][0]) + " " - + str(self.atoms.lattice_mat[2][1]) + + str(lat_mat[2][1]) + " " - + str(self.atoms.lattice_mat[2][2]) + + str(lat_mat[2][2]) ) return line @@ -226,6 +295,7 @@ def to_string(self): cell = "" input = "" inputph = "" + inputa2f = "" spec = "" if self.control_params: control = ( @@ -276,6 +346,13 @@ def to_string(self): + "/" + "\n" ) + if self.inputa2f: + inputa2f = ( + "\n&inputa2F\n\n" + + self.dictionary_to_string(self.inputa2f) + + "/" + + "\n" + ) if self.species: spec = "ATOMIC_SPECIES\n\n" + self.atomic_species_string() + "\n" line = ( @@ -286,6 +363,7 @@ def to_string(self): + cell + input + inputph + + inputa2f + spec # + "ATOMIC_SPECIES\n\n" # + self.atomic_species_string() diff --git a/jarvis/io/vasp/outputs.py b/jarvis/io/vasp/outputs.py index 3d47e7fd..84cbc390 100644 --- a/jarvis/io/vasp/outputs.py +++ b/jarvis/io/vasp/outputs.py @@ -36,6 +36,7 @@ def __init__( augdiff=None, dim=None, nsets=1, + lines="", ): """ Contain CHGCAR data. @@ -65,9 +66,19 @@ def __init__( self.aug = aug self.augdiff = augdiff self.nsets = nsets + self.lines = lines if self.atoms is None: - chg = self.read_file() - self.chg = chg + if self.filename != "": + f = open(self.filename, "r") + lines = f.read() + chg = self.read_file(lines=lines) + self.chg = chg + f.close() + elif self.lines != "": + chg = self.read_file(lines=self.lines) + self.chg = chg + else: + raise ValueError("Check inputs.") def to_dict(self): """Convert to a dictionary.""" @@ -147,11 +158,11 @@ def modify_grid( f.write(line) return chg - def read_file(self): + def read_file(self, lines=""): """Read CHGCAR.""" - f = open(self.filename, "r") - lines = f.read() - f.close() + # f = open(self.filename, "r") + # lines = f.read() + # f.close() self.atoms = Poscar.from_string(lines).atoms volume = self.atoms.volume text = lines.splitlines() @@ -1537,9 +1548,16 @@ def elements(self): raise ValueError("Unknown element type") if len(elements) != self.num_atoms: ValueError("Number of atoms is not equal to number of elements") - elements = [str(i) for i in elements] - # print ('elements',elements) - return elements + final_elements = [] + for i in elements: + el = str(i) + if el == "X": + el = "Xe" + if el == "r": + el = "Zr" + final_elements.append(el) + + return final_elements def vrun_structure_to_atoms(self, s={}): """Convert structure to Atoms object.""" diff --git a/jarvis/tasks/qe/master_super.py b/jarvis/tasks/qe/master_super.py new file mode 100644 index 00000000..28a6b57d --- /dev/null +++ b/jarvis/tasks/qe/master_super.py @@ -0,0 +1,108 @@ +"""Run multiple jobs.""" +from jarvis.tasks.qe.super import SuperCond +from jarvis.core.utils import get_factors +from jarvis.core.atoms import Atoms +from jarvis.db.figshare import data +from jarvis.core.kpoints import Kpoints3D +from jarvis.tasks.queue_jobs import Queue +from jarvis.db.jsonutils import dumpjson +import os +from jarvis.analysis.structure.spacegroup import Spacegroup3D + +# import glob +# from jarvis.db.jsonutils import loadjson + +my_data = data("dft_3d") + + +def get_jid_data(jid="JVASP-667", dataset="dft_2d"): + """Get info for a jid and dataset.""" + # d = data(dataset) + d = my_data + for i in d: + if i["jid"] == jid: + return i + + +qe_cmd = "mpirun -np 16 /home/kfg/codes/q-e-qe-6.5/bin/pw.x" + +run_dir = "/wrk/knc6/Super" + + +def non_prime_kpoints(kpts=[]): + mem = [] + for i in kpts: + facts = get_factors(i) + if len(facts) == 1: + val = i + 1 + else: + val = i + mem.append(val) + return mem + + +def write_qejob(pyname="job.py", job_json=""): + """Write template job.py with VaspJob.to_dict() job.json.""" + f = open(pyname, "w") + f.write("from jarvis.tasks.qe.super import SuperCond\n") + f.write("from jarvis.db.jsonutils import loadjson\n") + f.write('d=loadjson("' + str(job_json) + '")\n') + f.write("v=SuperCond.from_dict(d)\n") + f.write("v.runjob()\n") + f.close() + + +submit_job = True +jids = ["JVASP-19821"] +for i in jids: + try: + print("jid", i) + dir_name = os.path.join(run_dir, i + "_SUPER") + if not os.path.exists(dir_name): + os.makedirs(dir_name) + os.chdir(dir_name) + dat = get_jid_data(jid=i, dataset="dft_3d") + a_atoms = Atoms.from_dict(dat["atoms"]) + atoms = Spacegroup3D(a_atoms).refined_atoms.get_primitive_atoms + # print (atoms) + kp = Kpoints3D().automatic_length_mesh( + # lattice_mat=atoms.lattice_mat, + # length=10 + lattice_mat=atoms.lattice_mat, + length=dat["kpoint_length_unit"], + ) + kpts = kp._kpoints[0] + kpts = non_prime_kpoints(kpts) + kp = Kpoints3D(kpoints=[kpts]) + print("kpts", kpts) + + nq1 = get_factors(kpts[0])[0] + nq2 = get_factors(kpts[1])[0] + nq3 = get_factors(kpts[2])[0] + qp = Kpoints3D(kpoints=[[nq1, nq2, nq3]]) + + sup = SuperCond(atoms=atoms, kp=kp, qp=qp, qe_cmd=qe_cmd).to_dict() + dumpjson(data=sup, filename="sup.json") + write_qejob(job_json=os.path.abspath("sup.json")) + path = ( + "echo hello" + + " \n module load intel/2015\nmodule load " + + "openmpi/2.1.0/intel-15\nsource activate qe \npython " + + os.getcwd() + + "/job.py" + ) + + if submit_job: + Queue.slurm( + job_line=path, + jobname=i, + directory=os.getcwd(), + queue="mml", + walltime="330:0:0", + submit_cmd=["sbatch", "submit_job"], + ) + + os.chdir("..") + except Exception as exp: + print(exp) + pass diff --git a/jarvis/tasks/qe/super.py b/jarvis/tasks/qe/super.py index 7bd78199..4af8000a 100644 --- a/jarvis/tasks/qe/super.py +++ b/jarvis/tasks/qe/super.py @@ -1,201 +1,281 @@ """Module to run Tc calculation.""" +# Ref: https://arxiv.org/abs/2205.00060 from jarvis.io.qe.outputs import DataFileSchema +from jarvis.core.atoms import Atoms +from jarvis.core.kpoints import Kpoints3D from jarvis.tasks.qe.qe import QEjob +import numpy as np +import os +# from jarvis.core.utils import get_factors -def supercond_workflow(atoms=None, kp=None): - """Calculate Tc using QE.""" - # Still under development, - relax = { - "control": { - "calculation": "'vc-relax'", - "restart_mode": "'from_scratch'", - "prefix": "'QE'", - "outdir": "'./'", - "tstress": ".true.", - "tprnfor": ".true.", - "disk_io": "'low'", - "wf_collect": ".true.", - "pseudo_dir": None, - "verbosity": "'high'", - "nstep": 100, - }, - "system": { - "ibrav": 0, - "nat": None, - "ntyp": None, - "ecutwfc": 45, - "ecutrho": 250, - "q2sigma": 1, - "ecfixed": 44.5, - "qcutz": 800, - "occupations": "'smearing'", - "degauss": 0.01, - "lda_plus_u": ".false.", - "force_symmorphic": ".true.", - "nosym": ".false.", - "noinv": ".false.", - }, - "electrons": { - "diagonalization": "'david'", - "mixing_mode": "'local-TF'", - "mixing_beta": 0.3, - "conv_thr": "1d-9", - }, - "ions": {"ion_dynamics": "'bfgs'"}, - "cell": {"cell_dynamics": "'bfgs'", "cell_dofree": "'all'"}, - } - - qejob_relax = QEjob( - atoms=atoms, - input_params=relax, - output_file="relax.out", - qe_cmd="/users/knc6/Software/QE/q-e/bin/pw.x", - jobname="relax", - kpoints=kp, - input_file="arelax.in", + +def calc_Tc(wlog=300, lamb=1.0, mu=0.1): + """Calculate Tc.""" + tc = (wlog / 1.2) * np.exp( + -1.04 * (1 + lamb) / (lamb * (1 - 0.62 * mu) - mu) ) + return tc + + +def parse_lambda(filename="lambda"): + """Parse lambda file.""" + f = open(filename, "r") + lines = f.read().splitlines() + f.close() + for i in lines: + if "Broadening" in i: + tmp = i.split() + print(i.split()) + wlog = float(tmp[-1]) + lamb = float(tmp[3]) + Tc = calc_Tc(wlog=wlog, lamb=lamb) + print("Tc", Tc) + print() - info = qejob_relax.runjob() - xml_path = info["xml_path"] - xml_dat = DataFileSchema(xml_path) - final_strt = xml_dat.final_structure - - print("final_strt", final_strt) - - scf = { - "control": { - "calculation": "'scf'", - "restart_mode": "'from_scratch'", - "prefix": "'QE'", - "outdir": "'./'", - "tstress": ".true.", - "tprnfor": ".true.", - "disk_io": "'low'", - "pseudo_dir": None, - "verbosity": "'high'", - "nstep": 100, - "etot_conv_thr": "1.0d-5", - "forc_conv_thr": "1.0d-4", - }, - "system": { - "ibrav": 0, - "degauss": 0.01, - "nat": None, - "ntyp": None, - "ecutwfc": 45, - "ecutrho": 250, - "occupations": "'smearing'", - "smearing": "'mp'", - "la2F ": ".true.", - }, - "electrons": { - "diagonalization": "'david'", - "mixing_mode": "'plain'", - "mixing_beta": 0.7, - "conv_thr": "1d-9", - }, - } - - qejob_scf = QEjob( - atoms=final_strt, - input_params=scf, - output_file="scf.out", - qe_cmd="/users/knc6/Software/QE/q-e/bin/pw.x", - jobname="scf", - kpoints=kp, - input_file="ascf.in", + +def very_clean(): + """Clean files.""" + cmd = ( + "rm -r elph_dir _ph0 *.dos* *.in *.json *.fc *.freq* *.save " + + "*.out *.dyn* *wfc* *.xml *save lambda *.modes dyn*" ) + os.system(cmd) + + +class SuperCond(object): + """Module to calculate Tc.""" + + def __init__( + self, + atoms=None, + kp=None, + qp=None, + qe_cmd="pw.x", + relax_calc="'vc-relax'", + pressure=None, + ): + """Initialize the class.""" + self.atoms = atoms + self.kp = kp + self.qp = qp + self.relax_calc = relax_calc + self.qe_cmd = qe_cmd + self.pressure = pressure + + def to_dict(self): + """Get dictionary.""" + info = {} + info["atoms"] = self.atoms.to_dict() + info["kp"] = self.kp.to_dict() + info["qp"] = self.qp.to_dict() + info["qe_cmd"] = self.qe_cmd + info["relax_calc"] = self.relax_calc + info["pressure"] = self.pressure + return info + + @classmethod + def from_dict(self, info={}): + """Load from a dictionary.""" + return SuperCond( + atoms=Atoms.from_dict(info["atoms"]), + kp=Kpoints3D.from_dict(info["kp"]), + qp=Kpoints3D.from_dict(info["qp"]), + qe_cmd=info["qe_cmd"], + pressure=info["pressure"], + relax_calc=info["relax_calc"], + ) - qejob_scf.runjob() - ph = { - "inputph": { - "prefix": "'QE'", - "fildyn": "'QE.dyn'", - "outdir": "'./'", - "ldisp": ".true.", - "trans": ".true.", - "fildvscf": "'dvscf'", - "electron_phonon": "'interpolated'", - "nq1": 2, - "nq2": 2, - "nq3": 3, - "tr2_ph": "1.0d-14", + def runjob(self): + """Calculate Tc using QE.""" + # Still under development, + atoms = self.atoms + kp = self.kp + qp = self.qp + relax = { + "control": { + # "calculation": "'scf'", + "calculation": self.relax_calc, # "'vc-relax'", + "restart_mode": "'from_scratch'", + "prefix": "'RELAX'", + "outdir": "'./'", + "tstress": ".true.", + "tprnfor": ".true.", + "disk_io": "'low'", + "wf_collect": ".true.", + "pseudo_dir": None, + "verbosity": "'high'", + "nstep": 100, + }, + "system": { + "ibrav": 0, + "nat": None, + "ntyp": None, + "ecutwfc": 45, + "ecutrho": 250, + "q2sigma": 1, + "ecfixed": 44.5, + "qcutz": 800, + "occupations": "'smearing'", + "degauss": 0.01, + "lda_plus_u": ".false.", + }, + "electrons": { + "diagonalization": "'david'", + "mixing_mode": "'local-TF'", + "mixing_beta": 0.3, + "conv_thr": "1d-9", + }, + "ions": {"ion_dynamics": "'bfgs'"}, + "cell": {"cell_dynamics": "'bfgs'", "cell_dofree": "'all'"}, } - } - qejob_ph = QEjob( - atoms=atoms, - input_params=ph, - output_file="ph.out", - qe_cmd="/users/knc6/Software/QE/q-e/bin/ph.x", - jobname="ph", - kpoints=None, - input_file="aph.in", - ) + if self.pressure is not None: + relax["cell"]["press"] = self.pressure + qejob_relax = QEjob( + atoms=atoms, + input_params=relax, + output_file="relax.out", + qe_cmd=self.qe_cmd, + jobname="relax", + kpoints=kp, + input_file="arelax.in", + ) + + info = qejob_relax.runjob() + xml_path = info["xml_path"] + xml_dat = DataFileSchema(xml_path) + final_strt = xml_dat.final_structure - qejob_ph.runjob() + print("final_strt", final_strt) - qr = { - "input": { - "zasr": "'simple'", - "fildyn": "'QE.dyn'", - "flfrc": "'QE333.fc'", - "la2F": ".true.", + # scf_init = + scf_init = { + "control": { + "calculation": "'scf'", + "restart_mode": "'from_scratch'", + "prefix": "'QE'", + "outdir": "'./'", + "tstress": ".true.", + "tprnfor": ".true.", + "disk_io": "'low'", + "pseudo_dir": None, + "verbosity": "'high'", + "nstep": 100, + "etot_conv_thr": "1.0d-5", + "forc_conv_thr": "1.0d-4", + }, + "system": { + "ibrav": 0, + "degauss": 0.01, + "nat": None, + "ntyp": None, + "ecutwfc": 45, + "ecutrho": 250, + "occupations": "'smearing'", + "smearing": "'mp'", + "la2F ": ".true.", + }, + "electrons": { + "diagonalization": "'david'", + "mixing_mode": "'plain'", + "mixing_beta": 0.7, + "conv_thr": "1d-9", + }, } - } - qejob_qr = QEjob( - atoms=atoms, - input_params=qr, - output_file="q2r.out", - qe_cmd="/users/knc6/Software/QE/q-e/bin/q2r.x", - jobname="qr", - kpoints=None, - input_file="aqr.in", - ) - qejob_qr.runjob() - - matdyn = { - "input": { - "asr": "'simple'", - "flfrc": "'QE333.fc'", - "flfrq": "'QE333.freq'", - "la2F": ".true.", - "dos": ".true.", - "fldos": "'phonon.dos'", - "nk1": 10, - "nk2": 10, - "nk3": 10, - "ndos": 50, + qejob_scf_init = QEjob( + atoms=final_strt, + input_params=scf_init, + output_file="scf_init.out", + qe_cmd=self.qe_cmd, + jobname="scf_init", + kpoints=kp, + input_file="ascf_init.in", + ) + + info_scf = qejob_scf_init.runjob() + print(info_scf) + # kpts = kp._kpoints[0] + qpts = qp._kpoints[0] + nq1 = qpts[0] # get_factors(kpts[0])[0] + nq2 = qpts[1] # get_factors(kpts[1])[0] + nq3 = qpts[2] # get_factors(kpts[2])[0] + ph = { + "inputph": { + "prefix": "'QE'", + "fildyn": "'QE.dyn'", + "outdir": "'./'", + "ldisp": ".true.", + "trans": ".true.", + "fildvscf": "'dvscf'", + "electron_phonon": "'interpolated'", + "el_ph_sigma": 0.005, + "nq1": nq1, + "nq2": nq2, + "nq3": nq3, + "tr2_ph": "1.0d-12", + } } - } - - qejob_matdyn = QEjob( - atoms=atoms, - input_params=matdyn, - output_file="matdyn.out", - qe_cmd="/users/knc6/Software/QE/q-e/bin/matdyn.x", - jobname="matdyn", - kpoints=None, - input_file="amatdyn.in", - ) + qejob_ph = QEjob( + atoms=final_strt, + input_params=ph, + output_file="ph.out", + qe_cmd=self.qe_cmd.replace("pw.x", "ph.x"), + jobname="ph", + kpoints=None, + input_file="aph.in", + ) - qejob_matdyn.runjob() + qejob_ph.runjob() + # import sys + # sys.exit() + qr = { + "input": { + "zasr": "'simple'", + "fildyn": "'QE.dyn'", + "flfrc": "'QE333.fc'", + "la2F": ".true.", + } + } + qejob_qr = QEjob( + atoms=final_strt, + input_params=qr, + output_file="q2r.out", + # qe_cmd="/home/knc6/Software/qe/q-e/bin/q2r.x", + qe_cmd=self.qe_cmd.replace("pw.x", "q2r.x"), + jobname="qr", + kpoints=None, + input_file="aqr.in", + ) + + qejob_qr.runjob() + kpts = kp._kpoints[0] + matdyn = { + "input": { + "asr": "'simple'", + "flfrc": "'QE333.fc'", + "flfrq": "'QE333.freq'", + "la2F": ".true.", + "dos": ".true.", + "fldos": "'phonon.dos'", + "nk1": kpts[0], + "nk2": kpts[1], + "nk3": kpts[2], + "ndos": 50, + } + } -""" -if __name__ == "__main__": - from jarvis.db.jsonutils import loadjson, dumpjson - from jarvis.core.atoms import Atoms - from jarvis.db.figshare import get_jid_data - from jarvis.core.kpoints import Kpoints3D + qejob_matdyn = QEjob( + atoms=final_strt, + input_params=matdyn, + output_file="matdyn.out", + # qe_cmd="/home/knc6/Software/qe/q-e/bin/matdyn.x", + qe_cmd=self.qe_cmd.replace("pw.x", "matdyn.x"), + jobname="matdyn", + kpoints=None, + input_file="amatdyn.in", + ) - dat = get_jid_data(jid="JVASP-19821", dataset="dft_3d") - atoms = Atoms.from_dict(dat["atoms"]) - kp = Kpoints3D().automatic_length_mesh( - lattice_mat=atoms.lattice_mat, length=int(dat["kpoint_length_unit"]) - ) - print("kpoint_length_unit", dat["kpoint_length_unit"], kp) - print(atoms) - supercond_workflow(atoms=atoms, kp=kp) -""" + qejob_matdyn.runjob() + parse_lambda() diff --git a/jarvis/tasks/qe/super_tetra.py b/jarvis/tasks/qe/super_tetra.py new file mode 100644 index 00000000..c4028764 --- /dev/null +++ b/jarvis/tasks/qe/super_tetra.py @@ -0,0 +1,247 @@ +"""Module to run Tc calculation.""" +from jarvis.io.qe.outputs import DataFileSchema +from jarvis.core.atoms import Atoms +from jarvis.core.kpoints import Kpoints3D +from jarvis.tasks.qe.qe import QEjob + +# import numpy as np +import os + +# from jarvis.core.utils import get_factors + + +def very_clean(): + """Clean files.""" + cmd = ( + "rm -r elph_dir _ph0 *.dos* *.in *.json *.fc *.freq* *.save " + + "*.out *.dyn* *wfc* *.xml *save lambda *.modes dyn*" + ) + os.system(cmd) + + +class SuperCond(object): + """Module to calculate Tc.""" + + def __init__(self, atoms=None, kp=None, qp=None, qe_cmd="pw.x"): + """Initialize the class.""" + self.atoms = atoms + self.kp = kp + self.qp = qp + self.qe_cmd = qe_cmd + + def to_dict(self): + """Get dictionary.""" + info = {} + info["atoms"] = self.atoms.to_dict() + info["kp"] = self.kp.to_dict() + info["qp"] = self.qp.to_dict() + info["qe_cmd"] = self.qe_cmd + return info + + @classmethod + def from_dict(self, info={}): + """Load from a dictionary.""" + return SuperCond( + atoms=Atoms.from_dict(info["atoms"]), + kp=Kpoints3D.from_dict(info["kp"]), + qp=Kpoints3D.from_dict(info["qp"]), + qe_cmd=info["qe_cmd"], + ) + + def runjob(self): + """Calculate Tc using QE.""" + # Still under development, + atoms = self.atoms + kp = self.kp + qp = self.qp + relax = { + "control": { + # "calculation": "'scf'", + "calculation": "'vc-relax'", + "restart_mode": "'from_scratch'", + "prefix": "'RELAX'", + "outdir": "'./'", + "tstress": ".true.", + "tprnfor": ".true.", + "disk_io": "'low'", + "wf_collect": ".true.", + "pseudo_dir": None, + "verbosity": "'high'", + "nstep": 100, + }, + "system": { + "ibrav": 0, + "nat": None, + "ntyp": None, + "ecutwfc": 45, + "ecutrho": 250, + "q2sigma": 1, + "ecfixed": 44.5, + "qcutz": 800, + "occupations": "'smearing'", + "degauss": 0.01, + "lda_plus_u": ".false.", + }, + "electrons": { + "diagonalization": "'david'", + "mixing_mode": "'local-TF'", + "mixing_beta": 0.3, + "conv_thr": "1d-10", + }, + "ions": {"ion_dynamics": "'bfgs'"}, + "cell": {"cell_dynamics": "'bfgs'", "cell_dofree": "'all'"}, + } + qejob_relax = QEjob( + atoms=atoms, + input_params=relax, + output_file="relax.out", + qe_cmd=self.qe_cmd, + jobname="relax", + kpoints=kp, + input_file="arelax.in", + ) + + info = qejob_relax.runjob() + xml_path = info["xml_path"] + xml_dat = DataFileSchema(xml_path) + final_strt = xml_dat.final_structure + + print("final_strt", final_strt) + + # scf_init = + scf_init = { + "control": { + "calculation": "'scf'", + "restart_mode": "'from_scratch'", + "prefix": "'QE'", + "outdir": "'./'", + "tstress": ".true.", + "tprnfor": ".true.", + "disk_io": "'low'", + "pseudo_dir": None, + "verbosity": "'high'", + "nstep": 100, + "etot_conv_thr": "1.0d-5", + "forc_conv_thr": "1.0d-4", + }, + "system": { + "ibrav": 0, + # "degauss": 0.01, + "nat": None, + "ntyp": None, + "ecutwfc": 45, + "ecutrho": 250, + "occupations": "'tetrahedra_opt'", + # "smearing": "'mp'", + # "la2F ": ".true.", + }, + "electrons": { + "diagonalization": "'david'", + "mixing_mode": "'plain'", + "mixing_beta": 0.7, + "conv_thr": "1d-10", + }, + } + + qejob_scf_init = QEjob( + atoms=final_strt, + input_params=scf_init, + output_file="scf_init.out", + qe_cmd=self.qe_cmd, + jobname="scf_init", + kpoints=kp, + input_file="ascf_init.in", + ) + + info_scf = qejob_scf_init.runjob() + print(info_scf) + kpts = kp._kpoints[0] + qpts = qp._kpoints[0] + nq1 = qpts[0] # get_factors(kpts[0])[0] + nq2 = qpts[1] # get_factors(kpts[1])[0] + nq3 = qpts[2] # get_factors(kpts[2])[0] + nk1 = kpts[0] + nk2 = kpts[1] + nk3 = kpts[2] + ph = { + "inputph": { + "prefix": "'QE'", + "fildyn": "'QE.dyn'", + "outdir": "'./'", + "ldisp": ".true.", + "lshift_q": ".true.", + "fildvscf": "'dvscf'", + "fildrho": "'dvrho'", + # "electron_phonon": "'lambda_tetra'", + # "electron_phonon": "'interpolated'", + # "el_ph_sigma": 0.005, + "nq1": nq1, + "nq2": nq2, + "nq3": nq3, + "nk1": nk1, + "nk2": nk2, + "nk3": nk3, + # "tr2_ph": "1.0d-12", + }, + } + qejob_ph = QEjob( + atoms=final_strt, + input_params=ph, + output_file="ph.out", + qe_cmd=self.qe_cmd.replace("pw.x", "ph.x"), + jobname="ph", + kpoints=None, + input_file="aph.in", + ) + + qejob_ph.runjob() + + nq1 = qpts[0] # get_factors(kpts[0])[0] + nq2 = qpts[1] # get_factors(kpts[1])[0] + nq3 = qpts[2] # get_factors(kpts[2])[0] + nk1 = kpts[0] + nk2 = kpts[1] + nk3 = kpts[2] + ph_tetra = { + "inputph": { + "prefix": "'QE'", + "fildyn": "'QE.dyn'", + "outdir": "'./'", + "ldisp": ".true.", + "lshift_q": ".true.", + "fildvscf": "'dvscf'", + "fildrho": "'dvrho'", + "electron_phonon": "'lambda_tetra'", + # "electron_phonon": "'interpolated'", + # "el_ph_sigma": 0.005, + "nq1": nq1, + "nq2": nq2, + "nq3": nq3, + "nk1": nk1, + "nk2": nk2, + "nk3": nk3, + # "tr2_ph": "1.0d-12", + }, + "inputa2f": { + "nfreq": 500, + }, + } + qejob_ph_tetra = QEjob( + atoms=final_strt, + input_params=ph_tetra, + output_file="ph_tetra.out", + qe_cmd=self.qe_cmd.replace("pw.x", "ph.x"), + jobname="ph_tetra", + kpoints=None, + input_file="aph_tetra.in", + ) + + qejob_ph_tetra.runjob() + cmd = ( + self.qe_cmd.replace("pw.x", "alpha2f.x") + + "<" + + "aph_tetra.in" + + ">" + + "aph_tetra.out" + ) + os.system(cmd) diff --git a/jarvis/tasks/vasp/vasp.py b/jarvis/tasks/vasp/vasp.py index 50244be5..65a71040 100644 --- a/jarvis/tasks/vasp/vasp.py +++ b/jarvis/tasks/vasp/vasp.py @@ -1893,6 +1893,54 @@ def scan(self): name="scan", incar=inc, pot_type="POT_GGA_PAW_PBE" ) + def r2scan(self): + """Select GGA-PBE functional.""" + data = dict( + PREC="Accurate", + ISMEAR=0, + IBRION=2, + METAGGA="R2SCAN", + LASPH=".TRUE.", + EDIFF="1E-7", + NSW=1, + NELM=400, + ISIF=2, + LCHARG=".FALSE.", + LWAVE=".FALSE.", + ) + inc = Incar(data) + return GenericIncars( + name="r2scan", incar=inc, pot_type="POT_GGA_PAW_PBE" + ) + + def hse06(self): + """Select HSE06 functional.""" + data = dict( + EDIFF="1E-6", + NEDOS=5000, + ALGO="All", + ISPIN=2, + LORBIT=11, + ISMEAR=0, + NPAR=16, + LHFCALC=".TRUE.", + HFSCREEN=0.2, + TIME=0.4, + LREAL=".FALSE.", + NSIM=4, + LPLANE=".TRUE.", + NELM=450, + LOPTICS=".FALSE.", + LMAXMIX=6, + ISTART=1, + LCHARG=".FALSE.", + LWAVE=".FALSE.", + ) + inc = Incar(data) + return GenericIncars( + name="hse06", incar=inc, pot_type="POT_GGA_PAW_PBE" + ) + def lda(self): """Select LDA functional.""" data = dict( diff --git a/jarvis/tests/testfiles/analysis/elastic/test_tensor.py b/jarvis/tests/testfiles/analysis/elastic/test_tensor.py index ede44003..819db76a 100644 --- a/jarvis/tests/testfiles/analysis/elastic/test_tensor.py +++ b/jarvis/tests/testfiles/analysis/elastic/test_tensor.py @@ -1,7 +1,11 @@ +from jarvis.db.figshare import get_jid_data +import numpy as np from jarvis.analysis.elastic.tensor import ElasticTensor +from jarvis.core.atoms import Atoms import os, tarfile from jarvis.io.lammps.outputs import parse_folder from jarvis.io.vasp.outputs import Vasprun, Outcar +from jarvis.core.atoms import Atoms example_fold_tgz = os.path.join( os.path.dirname(__file__), @@ -46,11 +50,31 @@ "OUTCAR", ) +poscar = os.path.join( + os.path.dirname(__file__), + "..", + "..", + "..", + "..", + "examples", + "vasp", + "SiOptb88", + "SiOptb88", + "MAIN-ELASTIC-bulk@mp_149", + "POSCAR", +) + +atoms = Atoms.from_poscar(poscar) + def test_vasp_et(): out = Outcar(outcar) et = ElasticTensor(out.elastic_props()["cij"]) print(et.to_dict()) + theta = et.debye_temperature(atoms=atoms) + print( + et.is_brittle, et.is_ductile,et.cauchy_pressure, et.melting_temperature_metals + ) example_fold_tgz = os.path.join( @@ -103,4 +127,10 @@ def test_lammps_et(): print(data["elastic_tensor"]["raw_et_tensor"]) -# test_lammps_et() +def test_deb(): + x = get_jid_data(jid="JVASP-19821", dataset="dft_3d") + et = ElasticTensor(et_tensor=np.array(x["elastic_tensor"])) + atoms = Atoms.from_dict(x["atoms"]) + dd = et.debye_temperature(atoms=atoms) + assert round(dd,2)==round(1047.547632064132,2) + # test_lammps_et() diff --git a/setup.py b/setup.py index ba4c7537..0911b930 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ setup( name="jarvis-tools", - version="2022.01.10", + version="2022.05.05", long_description=long_d, install_requires=[ "numpy>=1.19.5",