diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4ab6d5b --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +__pycache__/ +*.pyc +.vs/ +.ipynb_checkpoints/ +.idea/ + +*.db +*.traj +*.txt +*.json diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index fb0392b..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/workspace.xml -*.db \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..bb0de12 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,13 @@ +repos: +- repo: https://github.com/ambv/black + rev: stable + hooks: + - id: black + language_version: python3.9 +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: flake8 + - id: trailing-whitespace + - id: check-added-large-files + - id: end-of-file-fixer diff --git a/00_make_molecule.py b/00_make_molecule.py index 2a07e99..5cc3617 100644 --- a/00_make_molecule.py +++ b/00_make_molecule.py @@ -1,13 +1,13 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import numpy as np +import numpy as np from ase.build import molecule -from ase.visualize import view +from ase.visualize import view import ase.io as io -atoms = molecule('H2O') -atoms.set_cell(8*np.identity(3)) +atoms = molecule("H2O") +atoms.set_cell(8 * np.identity(3)) atoms.center() view(atoms) -io.write('start.traj', atoms) +io.write("start.traj", atoms) diff --git a/01_submit_job.py b/01_submit_job.py index 55eec8a..5bd9493 100644 --- a/01_submit_job.py +++ b/01_submit_job.py @@ -1,43 +1,43 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -#SBATCH -p high -#SBATCH --job-name=opt_try -#SBATCH --output=job.out -#SBATCH --error=job.err -#SBATCH --time=8:00:00 -#SBATCH --nodes=1 -#SBATCH --ntasks-per-node=16 -#SiBATCH --exclusive +# SBATCH -p high +# SBATCH --job-name=opt_try +# SBATCH --output=job.out +# SBATCH --error=job.err +# SBATCH --time=8:00:00 +# SBATCH --nodes=1 +# SBATCH --ntasks-per-node=16 +# SiBATCH --exclusive """ Created on Thu Mar 26 17:10:56 2020 @author: ark245 """ -import os, sys -sys.path.insert(0,'/home/ark245/lib/onboarding_DFT/') +import os, sys + +sys.path.insert(0, "/home/ark245/lib/onboarding_DFT/") from ase import io from kul_tools import KulTools as KT -kt = KT(gamma_only=False,structure_type='zeo') -kt.set_calculation_type('opt') -atoms = io.read('start.traj') -atoms.pbc=True +kt = KT(gamma_only=False, structure_type="zeo") +kt.set_calculation_type("opt") +atoms = io.read("start.traj") +atoms.pbc = True kt.set_structure(atoms) -kt.set_overall_vasp_params({'gga':'RP'}) +kt.set_overall_vasp_params({"gga": "RP"}) kt.run() -#print(kt.calc_default.int_params['ismear']) -#print(kt.calc_default.special_params['lreal']) -#print(kt.calculation_type) - +# print(kt.calc_default.int_params['ismear']) +# print(kt.calc_default.special_params['lreal']) +# print(kt.calculation_type) -# Calculation type -# opt --> needs atoms -# opt_fine --> needs constraints -# vib --> needs constraints -# dimer --> needs path annd atoms -# neb --> needs traj +# Calculation type +# opt --> needs atoms +# opt_fine --> needs constraints +# vib --> needs constraints +# dimer --> needs path annd atoms +# neb --> needs traj diff --git a/05_dimer_demo.py b/05_dimer_demo.py index 5dba33d..3d19074 100644 --- a/05_dimer_demo.py +++ b/05_dimer_demo.py @@ -1,26 +1,27 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -#SBATCH -p high -#SBATCH --job-name=opt_try -#SBATCH --output=job.out -#SBATCH --error=job.err -#SBATCH --time=8:00:00 -#SBATCH --nodes=1 -#SBATCH --ntasks-per-node=64 -c 2 -#SiBATCH --exclusive +# SBATCH -p high +# SBATCH --job-name=opt_try +# SBATCH --output=job.out +# SBATCH --error=job.err +# SBATCH --time=8:00:00 +# SBATCH --nodes=1 +# SBATCH --ntasks-per-node=64 -c 2 +# SiBATCH --exclusive """ Created on Thu Mar 26 17:10:56 2020 @author: ark245 """ import os, sys -sys.path.insert(0,'/home/ark245/lib/onboarding_DFT/') + +sys.path.insert(0, "/home/ark245/lib/onboarding_DFT/") from ase import io from kul_tools import KulTools as KT -kt = KT(gamma_only=False,structure_type='zeo',calculation_type='dimer') -atoms = io.read('dimer_start.traj') +kt = KT(gamma_only=False, structure_type="zeo", calculation_type="dimer") +atoms = io.read("dimer_start.traj") kt.set_structure(atoms) -kt.set_overall_vasp_params({'gga':'RP'}) +kt.set_overall_vasp_params({"gga": "RP"}) kt.run() diff --git a/CHA.traj b/CHA.traj deleted file mode 100644 index f545b61..0000000 Binary files a/CHA.traj and /dev/null differ diff --git a/KulTools/KT_object.py b/KulTools/KT_object.py new file mode 100644 index 0000000..a796015 --- /dev/null +++ b/KulTools/KT_object.py @@ -0,0 +1,142 @@ +"""class structure(custom_params,ase_atoms) + assert param has been Changed + ISMEAR SIGMA etc + structure.get_calc_object (VASP,QE) + structure.set_defaults + +class calculation_type(custom_params): + self.params = {} + self.params["IBRION"] = self.custom + contains default params for each calc + if calculator_name - 'VASP': + kt_params = "" + else assert +assert param has been Changed +IBRION,NSW,EDIFFG,POTIM + + +from kt.calculation_type import calc_params... + +.sh script package -> environments""" + +from kt_structure import KT_structure +from ase.calculators.vasp import Vasp +from load_environ import identify_hpc_cluster, identify_vasp_environ + + +class KT_Object(KT_structure): + def __init__( + self, + gamma_only, + structure, + structure_type, + calculator_name, + calculation_type, + calc_params={}, + ): + + super().__init__(structure, structure_type, calculator_name, calculation_type) + + self.gamma = gamma_only + self.user_params = calc_params + self.kt_params = {} + + self._set_environment_variables() + + if self.calc_name.lower() == "vasp": + self._load_structure_type_params_vasp() + self._load_calc_type_params_vasp() + + self._load_update_kt_params() + + self._init_ase_calc() + + def _set_environment_variables(self): + if self.calc_name.lower() == "vasp": + self.hpc = identify_hpc_cluster() + print("ENVIRONMENT VARIABLES ARE AT:") + print(identify_vasp_environ(self.hpc, self.gamma)) + + else: + pass + + def _load_structure_type_params_vasp(self): + + if self.structure_type.lower() == "metal": + self.default_calc_params.update({"sigma": 0.2, "ismear": 1}) + + elif self.structure_type.lower() == "gas-phase": + self.default_calc_params.update({"lreal": False}) + + else: + pass + + def _load_calc_type_params_vasp(self): + + if self.calculation_type.lower() == "spe": + self.default_calc_params.update({"nsw": 0}) + + elif self.calculation_type.lower() == "opt_fine": + self.default_calc_params.update( + {"ibrion": 1, "potim": 0.05, "nsw": 50, "ediffg": -0.03} + ) + + elif self.calculation_type.lower() == "vib": + self.default_calc_params.update({"ibrion": 5, "potim": 0.02, "nsw": 1}) + + elif self.calculation_type.lower() == "solv": + self.default_calc_params.update( + { + "potim": 0.0, + "nsw": 5, + "lwave": True, + "lsol": False, + "prec": "Accurate", + } + ) + + elif self.calculation_type.lower() == "solv-spe": + self.default_calc_params.update( + { + "potim": 0.0, + "nsw": 3, + "lwave": True, + "lsol": True, + "prec": "Accurate", + } + ) + + elif self.calculation_type.lower() == "solv-spe-rho": + self.default_calc_params.update( + { + "potim": 0.0, + "nsw": 5, + "lrho": True, + "lwave": True, + "lsol": True, + "prec": "Accurate", + "lrhob": True, + "lrhoion": True, + } + ) + + elif self.calculation_type.lower() == "md": + self.default_calc_params.update( + {"ibrion": 0, "nsw": 1000000, "tebeg": 298, "isif": 2, "smass": 0} + ) + + else: + pass + + def _load_update_kt_params(self): + self.default_calc_params.update(self.user_params) + self.kt_params = self.default_calc_params + + def _init_ase_calc(self): + if self.calc_name.lower() == "vasp": + self.ase_calculator = Vasp() + else: + pass + + for key in self.kt_params: + self.ase_calculator.set(key=self.kt_params[key]) diff --git a/KulTools/README.md b/KulTools/README.md new file mode 100644 index 0000000..a934118 --- /dev/null +++ b/KulTools/README.md @@ -0,0 +1 @@ +Script related to creating the kT object diff --git a/KulTools/__init__.py b/KulTools/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/KulTools/calc_object.py b/KulTools/calc_object.py new file mode 100644 index 0000000..969008c --- /dev/null +++ b/KulTools/calc_object.py @@ -0,0 +1,43 @@ +from ase.calculators.vasp import Vasp + + +class default_calc: + def __init__(self): + pass + + def load_default_vasp(self): + self.vasp_params = { + "kpts": (1, 1, 1), + "potim": 0.5, + "encut": 500, + "ispin": 2, + "nsw": 50, + "prec": "Normal", + "istart": 1, + "isif": 2, + "ismear": 0, + "sigma": 0.05, + "nelmin": 4, + "nelmdl": -4, + "nwrite": 1, + "icharg": 2, + "lasph": True, + "ediff": 1e-6, + "ediffg": -0.05, + "ibrion": 2, + "lcharg": False, + "lwave": False, + "laechg": False, + "voskown": 1, + "algo": "Fast", + "lplane": True, + "lreal": "Auto", + "isym": 0, + "xc": "PBE", + "lorbit": 11, + "nupdown": -1, + "npar": 4, + "nsim": 4, + "ivdw": 12, + } + return self.vasp_params diff --git a/KulTools/kt_structure.py b/KulTools/kt_structure.py new file mode 100644 index 0000000..cd9a255 --- /dev/null +++ b/KulTools/kt_structure.py @@ -0,0 +1,61 @@ +from calc_object import default_calc +from ase import Atoms + + +class KT_structure(default_calc): + def __init__(self, structure, structure_type, calculator_name, calculation_type): + super().__init__() + self.structure = structure + self.structure_type = structure_type + self.calc_name = calculator_name + self.calculation_type = calculation_type + + self._check_calculator_name() + self._load_default_calc_params() + self._check_structure_type() + self._check_calc_type() + + def _check_calculator_name(self): + + assert self.calc_name.lower() in ["vasp", "emt"], ( + "Unknown/Not implemented calculator name = %s" % self.calc_name + ) + + def _load_default_calc_params(self): + + if self.calc_name.lower() == "vasp": + self.default_calc_params = self.load_default_vasp() + + else: + pass + + def _check_structure_type(self): + + if self.calculation_type.lower() == "neb": + assert isinstance(self.structure, list) and isinstance( + self.structure[0], Atoms + ), "Not an ASE atoms object" + + else: + assert isinstance(self.structure, Atoms), "Not an ASE atoms object" + + assert self.structure_type.lower() in ["zeo", "mof", "metal", "gas-phase"], ( + "Unknown structure_type = %s" + % self.structure_type # Add insulating slab , conducting slab and gas-phase no need for metal + ) + + def _check_calc_type(self): + + assert self.calculation_type.lower() in [ + "spe", + "opt", + "opt_fine", + "vib", + "neb", + "md", + "solv", + "solv-spe", + "solv-spe-rho", + ], ( + "Unknown calculation_type = %s" % self.calculation_type + ) diff --git a/KulTools/load_environ.py b/KulTools/load_environ.py new file mode 100644 index 0000000..014354a --- /dev/null +++ b/KulTools/load_environ.py @@ -0,0 +1,85 @@ +import sys, os + + +def identify_hpc_cluster(): + path_home = os.environ["HOME"] + if path_home.startswith("/global/homes"): + host_name = "cori" + elif path_home.startswith("/home/"): + if os.environ["SLURM_SUBMIT_HOST"] == "hpc1": + host_name = "hpc1" + elif os.environ["SLURM_SUBMIT_HOST"] == "hpc2": + host_name = "hpc2" + elif path_home.startswith("/Users/"): + host_name = "local" + elif path_home.startswith("/home1/"): + host_name = "stampede" + else: + print("Check cluster settings") + sys.exit() + return host_name + + +def identify_vasp_environ(hpc, gamma_only): + if hpc.lower() == "hpc1": + os.environ[ + "VASP_PP_PATH" + ] = "/home/ark245/programs/vasp5.4.4/pseudopotentials/pseudo54" + if gamma_only: + vasp_exe = "vasp_gam" + else: + vasp_exe = "vasp_std" + os.environ["VASP_COMMAND"] = ( + "module load vasp/5.4.4pl2-vtst; NTASKS=`echo $SLURM_TASKS_PER_NODE|tr '(' ' '|awk '{print $1}'`; NNODES=`scontrol show hostnames $SLURM_JOB_NODELIST|wc -l`; NCPU=`echo \" $NTASKS * $NNODES \" | bc`; echo \"num_cpu=\" $NCPU; srun -n $NCPU %s | tee -a op.vasp" + % vasp_exe + ) + + elif hpc.lower() == "hpc2": + os.environ[ + "VASP_PP_PATH" + ] = "/home/sours/programs/vasp_PP" # '/home/ark245/programs/pseudopotentials/pseudo54' + if gamma_only: + vasp_exe = "vasp_gam" + else: + vasp_exe = "vasp_std" + os.environ["VASP_COMMAND"] = ( + "NTASKS=`echo $SLURM_TASKS_PER_NODE|tr '(' ' '|awk '{print $1}'`; NNODES=`scontrol show hostnames $SLURM_JOB_NODELIST|wc -l`; NCPU=`echo \" $NTASKS * $NNODES \" | bc`; echo \"num_cpu=\" $NCPU; $(which mpirun) --map-by core --display-map --report-bindings --mca btl_openib_allow_ib true --mca btl_openib_if_include mlx5_0:1 --mca btl_openib_warn_nonexistent_if 0 --mca btl_openib_warn_no_device_params_found 0 --mca pml ob1 --mca btl openib,self,vader --mca mpi_cuda_support 0 -np $NCPU %s | tee -a op.vasp" + % vasp_exe + ) + print(os.environ["VASP_COMMAND"]) + + elif hpc.lower() == "cori": + os.environ["VASP_PP_PATH"] = "/global/homes/a/ark245/pseudopotentials/PBE54" + if gamma_only: + vasp_exe = "vasp_gam" + else: + vasp_exe = "vasp_std" + os.environ["VASP_COMMAND"] = ( + "NTASKS=`echo $SLURM_TASKS_PER_NODE|tr '(' ' '|awk '{print $1}'`; NNODES=`scontrol show hostnames $SLURM_JOB_NODELIST|wc -l`; NCPU=`echo \" $NTASKS * $NNODES \" | bc`; echo \"num_cpu=\" $NCPU; srun -n $NCPU %s | tee -a op.vasp" + % vasp_exe + ) + + elif hpc.lower() == "stampede": + os.environ["VASP_PP_PATH"] = "/home1/05364/ark245/pseudopotentials/PBE54" + if gamma_only: + vasp_exe = "vasp_gam_vtst" + else: + vasp_exe = "vasp_std_vtst" + os.environ["VASP_COMMAND"] = ( + "module load vasp/5.4.4; export OMP_NUM_THREADS=1;rm op.vasp; mpirun -np $SLURM_NTASKS %s | tee op.vasp" + % vasp_exe + ) + + elif hpc.lower() == "local": + os.environ["VASP_PP_PATH"] = "local_vasp_pp" + if gamma_only: + vasp_exe = "vasp_gam" + else: + vasp_exe = "vasp_std" + os.environ["VASP_COMMAND"] = "local_%s" % vasp_exe + else: + print("Check cluster settings") + sys.exit() + vasp_pp_path = os.environ["VASP_PP_PATH"] + vasp_command = os.environ["VASP_COMMAND"] + return vasp_pp_path, vasp_command diff --git a/KulTools/run_Kultools.py b/KulTools/run_Kultools.py new file mode 100644 index 0000000..c85a6aa --- /dev/null +++ b/KulTools/run_Kultools.py @@ -0,0 +1,32 @@ +from copy import copy +from KT_object import KT_Object + +class run_KulTools(KT_Object): + + def __init__(self,gamma_only,structure,structure_type,calculator_name,calculation_type,calc_params={}): + + super().__init__(gamma_only,structure,structure_type,calculator_name,calculation_type,calc_params) + + def run_calculation(self): + + if self.calculation_type.lower() == 'opt': + self._run_opt() + elif self.calculation_type.lower() == 'vib': + self._run_vib() + elif + else + + def _run_opt(self): + ase_atoms = copy.deepcopy(self.structure) + + dir_name = 'opt' + + #Set working directory generations + self.ase_calculator.set('directory':os.getwd()) + + ase_atoms.set_calculator(self.ase_calculator) + energy = ase_atoms.get_potential_energy() #Running vasp + + + new_atoms = self.run_dft(ase_atoms,dir_name) + return new_atoms diff --git a/README.md b/README.md index ed8ff13..0f509a2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # VASP Test Instructions -1. add `module load vasp/5.4.4` to your `.bashrc` file and reload it or reconnect +1. add `module load vasp/5.4.4` to your `.bashrc` file and reload it or reconnect 2. run file `00_make_molecule.py` by running `python3 00_make_molecule.py` -3. verify that the file `start.traj` was created -4. run the second file with slurm by typing `sbatch 01_submit_job.py` (you might need a __init__.py file for kultools.py to be recognized as a module). +3. verify that the file `start.traj` was created +4. run the second file with slurm by typing `sbatch 01_submit_job.py` (you might need a __init__.py file for kultools.py to be recognized as a module). 5. Check the `job.out` and `job.err` files for errors diff --git a/__init__.py b/__init__.py index 8b13789..e69de29 100644 --- a/__init__.py +++ b/__init__.py @@ -1 +0,0 @@ - diff --git a/analysis/README.md b/analysis/README.md new file mode 100644 index 0000000..54832c2 --- /dev/null +++ b/analysis/README.md @@ -0,0 +1 @@ +Folder for creating analysis module to plot results, etc diff --git a/hpc2_header.py b/hpc2_header.py index 5ce4aab..bc734de 100644 --- a/hpc2_header.py +++ b/hpc2_header.py @@ -1,14 +1,14 @@ #!/usr/bin/env python ##SBATCH --exclude=agate-0,agate-1 -#SBATCH --nodes=1 --partition=high -#SBATCH --ntasks-per-node=64 -#SBATCH --ntasks-per-core=1 -#SBATCH --threads-per-core=1 -#SBATCH --output=job.out -#SBATCH --error=job.err -#SBATCH --time=28:00:00 -#SBATCH --verbose +# SBATCH --nodes=1 --partition=high +# SBATCH --ntasks-per-node=64 +# SBATCH --ntasks-per-core=1 +# SBATCH --threads-per-core=1 +# SBATCH --output=job.out +# SBATCH --error=job.err +# SBATCH --time=28:00:00 +# SBATCH --verbose import shutil from ase.parallel import * @@ -18,7 +18,7 @@ import os import time import shutil -from ase.optimize import BFGS,FIRE, QuasiNewton +from ase.optimize import BFGS, FIRE, QuasiNewton from glob import glob from ase.calculators.emt import EMT from ase.constraints import FixAtoms @@ -26,11 +26,15 @@ from ase.calculators.vasp import Vasp from ase.optimize.gpmin import gpmin -os.environ['VASP_PP_PATH']='/home/sours/programs/vasp_PP' -os.environ["MPIRUN_OPTIONS"] = "--verbose --map-by core --display-map --report-bindings " -os.environ["MPIRUN_OPTIONS"] += "--mca btl_openib_allow_ib true --mca btl_openib_if_include mlx5_0:1 " +os.environ["VASP_PP_PATH"] = "/home/sours/programs/vasp_PP" +os.environ[ + "MPIRUN_OPTIONS" +] = "--verbose --map-by core --display-map --report-bindings " +os.environ[ + "MPIRUN_OPTIONS" +] += "--mca btl_openib_allow_ib true --mca btl_openib_if_include mlx5_0:1 " os.environ["MPIRUN_OPTIONS"] += "--mca btl_openib_warn_nonexistent_if 0 " os.environ["MPIRUN_OPTIONS"] += "--mca btl_openib_warn_no_device_params_found 0 " os.environ["MPIRUN_OPTIONS"] += "--mca pml ob1 --mca btl openib,self,vader " os.environ["MPIRUN_OPTIONS"] += "--mca mpi_cuda_support 0 " -os.environ['VASP_COMMAND'] = "mpirun $MPIRUN_OPTIONS -np $SLURM_NTASKS vasp_gam" +os.environ["VASP_COMMAND"] = "mpirun $MPIRUN_OPTIONS -np $SLURM_NTASKS vasp_gam" diff --git a/kt.pdf b/kt.pdf new file mode 100644 index 0000000..7a24b4f Binary files /dev/null and b/kt.pdf differ diff --git a/kt.pptx b/kt.pptx new file mode 100644 index 0000000..8455f3b Binary files /dev/null and b/kt.pptx differ diff --git a/kul_tools.py b/kul_tools.py index b45db1a..be2a8dd 100644 --- a/kul_tools.py +++ b/kul_tools.py @@ -1,13 +1,14 @@ -# Kulkarn group @ UC Davis +# Kulkarni group @ UC Davis """Definition of the Zeotype class. -This module defines the central object in analyzing Zeotypes +This module defines the central object in analyzing Zeotypes """ import sys, os -import numpy as np +import numpy as np from ase import Atoms from ase.neighborlist import NeighborList + try: from ase.neighborlist import natural_cutoffs except: @@ -15,98 +16,123 @@ from ase.visualize import view from ase.calculators.vasp import Vasp + class KulTools: - """KulTools class that provides all the necessary tools for running simulations. Currently targetted towards using vasp. """ - def __init__(self,gamma_only=False,structure_type=None,calculation_type='spe',structure=None): + """KulTools class that provides all the necessary tools for running simulations. Currently targetted towards using vasp.""" + + def __init__( + self, + gamma_only=False, + structure_type=None, + calculation_type="spe", + structure=None, + ): self.working_dir = os.getcwd() - + self.hpc = self.identify_hpc_cluster() - print('KT: HPC= %s' %self.hpc) + print("KT: HPC= %s" % self.hpc) self.gamma_only = gamma_only - print('KT: VASP_GAMMA= %s' %self.gamma_only) - + print("KT: VASP_GAMMA= %s" % self.gamma_only) + self.structure_type = structure_type self.calculation_type = calculation_type self.main_dir = os.getcwd() - self.structure = structure + self.structure = structure self.identify_vasp_eviron() - print('KT: VASP_PP_PATH= %s' %self.vasp_pp_path) - print('KT: VASP_COMMAND= %s' %self.vasp_command) + print("KT: VASP_PP_PATH= %s" % self.vasp_pp_path) + print("KT: VASP_COMMAND= %s" % self.vasp_command) self.assign_default_calculator() def identify_hpc_cluster(self): - path_home = os.environ['HOME'] - if path_home.startswith('/global/homes'): - host_name = 'cori' - elif path_home.startswith('/home/'): - if os.environ['SLURM_SUBMIT_HOST']=='hpc1': - host_name = 'hpc1' - elif os.environ['SLURM_SUBMIT_HOST']=='hpc2': - host_name = 'hpc2' - elif path_home.startswith('/Users/'): - host_name = 'local' - elif path_home.startswith('/home1/'): - host_name = 'stampede' + path_home = os.environ["HOME"] + if path_home.startswith("/global/homes"): + host_name = "cori" + elif path_home.startswith("/home/"): + if os.environ["SLURM_SUBMIT_HOST"] == "hpc1": + host_name = "hpc1" + elif os.environ["SLURM_SUBMIT_HOST"] == "hpc2": + host_name = "hpc2" + elif path_home.startswith("/Users/"): + host_name = "local" + elif path_home.startswith("/home1/"): + host_name = "stampede" else: - print('Check cluster settings') + print("Check cluster settings") sys.exit() return host_name - + def identify_vasp_eviron(self): - if self.hpc == 'hpc1': - os.environ['VASP_PP_PATH']='/home/ark245/programs/vasp5.4.4/pseudopotentials/pseudo54' - if self.gamma_only: - vasp_exe = 'vasp_gam' + if self.hpc == "hpc1": + os.environ[ + "VASP_PP_PATH" + ] = "/home/ark245/programs/vasp5.4.4/pseudopotentials/pseudo54" + if self.gamma_only: + vasp_exe = "vasp_gam" else: - vasp_exe = 'vasp_std' - os.environ['VASP_COMMAND']='module load vasp/5.4.4pl2-vtst; NTASKS=`echo $SLURM_TASKS_PER_NODE|tr \'(\' \' \'|awk \'{print $1}\'`; NNODES=`scontrol show hostnames $SLURM_JOB_NODELIST|wc -l`; NCPU=`echo " $NTASKS * $NNODES " | bc`; echo "num_cpu=" $NCPU; srun -n $NCPU %s | tee -a op.vasp' % vasp_exe + vasp_exe = "vasp_std" + os.environ["VASP_COMMAND"] = ( + "module load vasp/5.4.4pl2-vtst; NTASKS=`echo $SLURM_TASKS_PER_NODE|tr '(' ' '|awk '{print $1}'`; NNODES=`scontrol show hostnames $SLURM_JOB_NODELIST|wc -l`; NCPU=`echo \" $NTASKS * $NNODES \" | bc`; echo \"num_cpu=\" $NCPU; srun -n $NCPU %s | tee -a op.vasp" + % vasp_exe + ) - elif self.hpc == 'hpc2': - os.environ['VASP_PP_PATH']= '/home/sours/programs/vasp_PP' # '/home/ark245/programs/pseudopotentials/pseudo54' + elif self.hpc == "hpc2": + os.environ[ + "VASP_PP_PATH" + ] = "/home/sours/programs/vasp_PP" # '/home/ark245/programs/pseudopotentials/pseudo54' if self.gamma_only: - vasp_exe = 'vasp_gam' + vasp_exe = "vasp_gam" else: - vasp_exe = 'vasp_std' - os.environ['VASP_COMMAND']='NTASKS=`echo $SLURM_TASKS_PER_NODE|tr \'(\' \' \'|awk \'{print $1}\'`; NNODES=`scontrol show hostnames $SLURM_JOB_NODELIST|wc -l`; NCPU=`echo " $NTASKS * $NNODES " | bc`; echo "num_cpu=" $NCPU; $(which mpirun) --map-by core --display-map --report-bindings --mca btl_openib_allow_ib true --mca btl_openib_if_include mlx5_0:1 --mca btl_openib_warn_nonexistent_if 0 --mca btl_openib_warn_no_device_params_found 0 --mca pml ob1 --mca btl openib,self,vader --mca mpi_cuda_support 0 -np $NCPU %s | tee -a op.vasp' % vasp_exe - print(os.environ['VASP_COMMAND']) - - elif self.hpc == 'cori': - os.environ['VASP_PP_PATH']='/global/homes/a/ark245/pseudopotentials/PBE54' - if self.gamma_only: - vasp_exe = 'vasp_gam' + vasp_exe = "vasp_std" + os.environ["VASP_COMMAND"] = ( + "NTASKS=`echo $SLURM_TASKS_PER_NODE|tr '(' ' '|awk '{print $1}'`; NNODES=`scontrol show hostnames $SLURM_JOB_NODELIST|wc -l`; NCPU=`echo \" $NTASKS * $NNODES \" | bc`; echo \"num_cpu=\" $NCPU; $(which mpirun) --map-by core --display-map --report-bindings --mca btl_openib_allow_ib true --mca btl_openib_if_include mlx5_0:1 --mca btl_openib_warn_nonexistent_if 0 --mca btl_openib_warn_no_device_params_found 0 --mca pml ob1 --mca btl openib,self,vader --mca mpi_cuda_support 0 -np $NCPU %s | tee -a op.vasp" + % vasp_exe + ) + print(os.environ["VASP_COMMAND"]) + + elif self.hpc == "cori": + os.environ["VASP_PP_PATH"] = "/global/homes/a/ark245/pseudopotentials/PBE54" + if self.gamma_only: + vasp_exe = "vasp_gam" else: - vasp_exe = 'vasp_std' - os.environ['VASP_COMMAND']='NTASKS=`echo $SLURM_TASKS_PER_NODE|tr \'(\' \' \'|awk \'{print $1}\'`; NNODES=`scontrol show hostnames $SLURM_JOB_NODELIST|wc -l`; NCPU=`echo " $NTASKS * $NNODES " | bc`; echo "num_cpu=" $NCPU; srun -n $NCPU %s | tee -a op.vasp' % vasp_exe - elif self.hpc == 'stampede': - os.environ['VASP_PP_PATH']='/home1/05364/ark245/pseudopotentials/PBE54' - if self.gamma_only: - vasp_exe = 'vasp_gam_vtst' + vasp_exe = "vasp_std" + os.environ["VASP_COMMAND"] = ( + "NTASKS=`echo $SLURM_TASKS_PER_NODE|tr '(' ' '|awk '{print $1}'`; NNODES=`scontrol show hostnames $SLURM_JOB_NODELIST|wc -l`; NCPU=`echo \" $NTASKS * $NNODES \" | bc`; echo \"num_cpu=\" $NCPU; srun -n $NCPU %s | tee -a op.vasp" + % vasp_exe + ) + elif self.hpc == "stampede": + os.environ["VASP_PP_PATH"] = "/home1/05364/ark245/pseudopotentials/PBE54" + if self.gamma_only: + vasp_exe = "vasp_gam_vtst" else: - vasp_exe = 'vasp_std_vtst' - os.environ['VASP_COMMAND']='module load vasp/5.4.4; export OMP_NUM_THREADS=1;rm op.vasp; mpirun -np $SLURM_NTASKS %s | tee op.vasp' % vasp_exe - elif self.hpc == 'local': - os.environ['VASP_PP_PATH']='local_vasp_pp' - if self.gamma_only: - vasp_exe = 'vasp_gam' + vasp_exe = "vasp_std_vtst" + os.environ["VASP_COMMAND"] = ( + "module load vasp/5.4.4; export OMP_NUM_THREADS=1;rm op.vasp; mpirun -np $SLURM_NTASKS %s | tee op.vasp" + % vasp_exe + ) + elif self.hpc == "local": + os.environ["VASP_PP_PATH"] = "local_vasp_pp" + if self.gamma_only: + vasp_exe = "vasp_gam" else: - vasp_exe = 'vasp_std' - os.environ['VASP_COMMAND']='local_%s' % vasp_exe - else: - print('Check cluster settings') + vasp_exe = "vasp_std" + os.environ["VASP_COMMAND"] = "local_%s" % vasp_exe + else: + print("Check cluster settings") sys.exit() - self.vasp_pp_path = os.environ['VASP_PP_PATH'] - self.vasp_command = os.environ['VASP_COMMAND'] + self.vasp_pp_path = os.environ["VASP_PP_PATH"] + self.vasp_command = os.environ["VASP_COMMAND"] def assign_default_calculator(self): """Sets a default calculator regadless of the structure type""" - self.calc_default = Vasp(kpts=(1,1,1), + self.calc_default = Vasp( + kpts=(1, 1, 1), potim=0.5, encut=500, ispin=2, nsw=50, - prec='Normal', + prec="Normal", istart=1, isif=2, ismear=0, @@ -116,260 +142,267 @@ def assign_default_calculator(self): nwrite=1, icharg=2, lasph=True, - ediff=1E-6, - ediffg=-0.05, + ediff=1e-6, + ediffg=-0.05, ibrion=2, lcharg=False, lwave=False, laechg=False, voskown=1, - algo='Fast', + algo="Fast", lplane=True, - lreal='Auto', + lreal="Auto", isym=0, - xc='PBE', + xc="PBE", lorbit=11, nupdown=-1, npar=4, nsim=4, - ivdw=12) + ivdw=12, + ) self.modify_calc_according_to_structure_type() - - def set_overall_vasp_params(self,overall_vasp_params): + + def set_overall_vasp_params(self, overall_vasp_params): self.overall_vasp_params = overall_vasp_params - + def modify_calc_according_to_structure_type(self): - assert self.structure_type in ['zeo','mof','metal','gas-phase'], "Unknown structure_type = %s" % self.structure_type - if self.structure_type == 'zeo' or self.structure_type == 'mof': + assert self.structure_type in ["zeo", "mof", "metal", "gas-phase"], ( + "Unknown structure_type = %s" % self.structure_type + ) + if self.structure_type == "zeo" or self.structure_type == "mof": pass - elif self.structure_type == 'metal': - self.calc_default.set(sigma=0.2,ismear=1) - elif self.structure_type == 'gas-phase': - self.calc_default.set(kpts=(1,1,1),lreal=False) - - def set_calculation_type(self,calculation_type): - assert self.calculation_type in ['spe','opt','opt_fine'], "Unknown calculation_type = %s" % self.calculation_type + elif self.structure_type == "metal": + self.calc_default.set(sigma=0.2, ismear=1) + elif self.structure_type == "gas-phase": + self.calc_default.set(kpts=(1, 1, 1), lreal=False) + + def set_calculation_type(self, calculation_type): + assert self.calculation_type in ["spe", "opt", "opt_fine"], ( + "Unknown calculation_type = %s" % self.calculation_type + ) self.calculation_type = calculation_type - - def set_structure(self,atoms_or_traj): + + def set_structure(self, atoms_or_traj): if isinstance(atoms_or_traj, Atoms): atoms = atoms_or_traj - self.structure = atoms - self.allowed_calculation_types = ['opt','opt_fine','vib'] + self.structure = atoms + self.allowed_calculation_types = ["opt", "opt_fine", "vib"] self.structure_istraj = False - if isinstance(atoms_or_traj, list) and isinstance(atoms_or_traj[0], Atoms): - #print('Dealing with an traj object') + if isinstance(atoms_or_traj, list) and isinstance(atoms_or_traj[0], Atoms): + # print('Dealing with an traj object') traj = atoms_or_traj self.structure = traj - self.allowed_calculation_types = ['neb'] + self.allowed_calculation_types = ["neb"] self.structure_istraj = True - + def get_structure(self): return self.structure - - def _change_to_dir(self,dir_name): + + def _change_to_dir(self, dir_name): if not os.path.exists(dir_name): os.makedirs(dir_name) os.chdir(dir_name) - def run_dft(self,atoms,dir_name): + def run_dft(self, atoms, dir_name): atoms.set_calculator(self.calc) atoms.calc.set(**self.overall_vasp_params) - if self.calculation_type == 'opt' or self.calculation_type == 'vib': - encut_for_dir = atoms.calc.float_params['encut'] - kpts_for_dir = ''.join([str(val) for val in atoms.calc.input_params['kpts']]) - func_for_dir = atoms.calc.input_params['xc'] - directory = dir_name + '_' + str(func_for_dir) + '_' + str(encut_for_dir) + '_' + str(kpts_for_dir) + if self.calculation_type == "opt" or self.calculation_type == "vib": + encut_for_dir = atoms.calc.float_params["encut"] + kpts_for_dir = "".join( + [str(val) for val in atoms.calc.input_params["kpts"]] + ) + func_for_dir = atoms.calc.input_params["xc"] + directory = ( + dir_name + + "_" + + str(func_for_dir) + + "_" + + str(encut_for_dir) + + "_" + + str(kpts_for_dir) + ) self._change_to_dir(directory) - energy = atoms.get_potential_energy() # Run vasp here - os.chdir(self.working_dir) + energy = atoms.get_potential_energy() # Run vasp here + os.chdir(self.working_dir) # Check for convergence after optimization - #f = atoms.get_forces() - #forces=np.sqrt(np.square(f[:,0]) +np.square(f[:,1]) + np.square(f[:,2])) - #max_forces = max(forces) - #magmoms = atoms.get_magnetic_moments() - #mag_oszi = atoms.get_magnetic_moment() - return (atoms) - + # f = atoms.get_forces() + # forces=np.sqrt(np.square(f[:,0]) +np.square(f[:,1]) + np.square(f[:,2])) + # max_forces = max(forces) + # magmoms = atoms.get_magnetic_moments() + # mag_oszi = atoms.get_magnetic_moment() + return atoms + def run(self): - if self.calculation_type == 'opt': - self.structure_after = self.run_opt()#atoms,dir_name) - elif self.calculation_type == 'opt_fine': + if self.calculation_type == "opt": + self.structure_after = self.run_opt() # atoms,dir_name) + elif self.calculation_type == "opt_fine": self.structure_after = self.run_opt_fine() - elif self.calculation_type == 'vib': + elif self.calculation_type == "vib": self.structure_after = self.run_vib() - elif self.calculation_type == 'solv': + elif self.calculation_type == "solv": self.structure_after = self.run_solv() - elif self.calculation_type == 'md': + elif self.calculation_type == "md": self.structure_after = self.run_md() def run_spe(self): """Runs a simple single point energy""" atoms = self.structure - dir_name = 'spe' + dir_name = "spe" self.calc = self.calc_default self.calc.set(nsw=0) - new_atoms = self.run_dft(atoms,dir_name) + new_atoms = self.run_dft(atoms, dir_name) return new_atoms - + def run_opt(self): """Runs a simple optimization""" atoms = self.structure self.calc = self.calc_default - dir_name = 'opt' - new_atoms = self.run_dft(atoms,dir_name) + dir_name = "opt" + new_atoms = self.run_dft(atoms, dir_name) return new_atoms - + def run_opt_fine(self): """Runs a finer optimization""" atoms = self.structure - dir_name = 'opt_fine' + dir_name = "opt_fine" self.calc = self.calc_default - self.calc.set(ibrion=1, potim = 0.05, nsw = 50, ediffg=-0.03) - new_atoms = self.run_dft(atoms,dir_name) + self.calc.set(ibrion=1, potim=0.05, nsw=50, ediffg=-0.03) + new_atoms = self.run_dft(atoms, dir_name) return new_atoms - + def run_vib(self): """Runs a simple vib calculation""" atoms = self.structure - dir_name = 'vib' + dir_name = "vib" self.calc = self.calc_default - self.calc.set(ibrion=5,potim=0.02,nsw=1) - new_atoms = self.run_dft(atoms,dir_name) + self.calc.set(ibrion=5, potim=0.02, nsw=1) + new_atoms = self.run_dft(atoms, dir_name) return new_atoms - - def run_solv(self,lrho=False): + + def run_solv(self, lrho=False): """Runs a simple solvation calculation""" atoms = self.structure - dir_name = 'spe' + dir_name = "spe" if not os.path.exists(dir_name): os.makedirs(dir_name) self.calc = self.calc_default - self.calc.set(potim=0.0,nsw=5,lwave=True,lsol=False,prec='Accurate') - new_atoms = self.run_dft(atoms,dir_name) - + self.calc.set(potim=0.0, nsw=5, lwave=True, lsol=False, prec="Accurate") + new_atoms = self.run_dft(atoms, dir_name) + atoms = new_atoms - dir_name = 'solv-spe' + dir_name = "solv-spe" if not os.path.exists(dir_name): os.makedirs(dir_name) self.calc = self.calc_default - shutil.copyfile('spe/WAVECAR','solv-spe/WAVECAR') - self.calc.set(potim=0.0,nsw=3,lwave=True,lsol=True,prec='Accurate') - new_atoms = self.run_dft(atoms,dir_name) - - if lrho: + shutil.copyfile("spe/WAVECAR", "solv-spe/WAVECAR") + self.calc.set(potim=0.0, nsw=3, lwave=True, lsol=True, prec="Accurate") + new_atoms = self.run_dft(atoms, dir_name) + + if lrho: atoms = new_atoms - dir_name = 'solv-spe-rho' + dir_name = "solv-spe-rho" if not os.path.exists(dir_name): os.makedirs(dir_name) self.calc = self.calc_default - shutil.copyfile('spe-spe/WAVECAR','solv-spe-rho/WAVECAR') - self.calc.set(potim=0.0,nsw=0,lwave=True,lsol=True,prec='Accurate',lrhob=True,lrhoion=True) - new_atoms = self.run_dft(atoms,dir_name) - + shutil.copyfile("spe-spe/WAVECAR", "solv-spe-rho/WAVECAR") + self.calc.set( + potim=0.0, + nsw=0, + lwave=True, + lsol=True, + prec="Accurate", + lrhob=True, + lrhoion=True, + ) + new_atoms = self.run_dft(atoms, dir_name) + return new_atoms - + def run_md(self): """Runs a finer optimization""" atoms = self.structure - dir_name = 'md' + dir_name = "md" self.calc = self.calc_default - self.calc.set(nsw=100000,ibrion=0,tebeg=298, isif=2, smass=0) - new_atoms = self.run_dft(atoms,dir_name) + self.calc.set(nsw=100000, ibrion=0, tebeg=298, isif=2, smass=0) + new_atoms = self.run_dft(atoms, dir_name) return new_atoms - - - -# if not 'solv-opt' in mode and not 'solv-spe' in mode: -# print('ERROR: Check mode') -# sys.exit() -# cwd = os.getcwd() -# if 'opt' in mode: -# dir_name = 'opt' -# my_nsw = 100 -# elif 'spe' in mode: -# dir_name = 'spe' -# my_nsw = 0 -# atoms = opt(atoms,dir_name=dir_name,lwave=True,lsol=False,nsw=my_nsw) -# -# directory = mode #solv-spe or solv-opt -# if not os.path.exists(directory): -# os.makedirs(directory) -# os.chdir(directory) -# shutil.copyfile('../spe/WAVECAR','WAVECAR') -# atoms = opt(atoms,dir_name='solv-spe',nsw=0,lwave=False,lsol=True) + + # if not 'solv-opt' in mode and not 'solv-spe' in mode: + # print('ERROR: Check mode') + # sys.exit() + # cwd = os.getcwd() + # if 'opt' in mode: + # dir_name = 'opt' + # my_nsw = 100 + # elif 'spe' in mode: + # dir_name = 'spe' + # my_nsw = 0 + # atoms = opt(atoms,dir_name=dir_name,lwave=True,lsol=False,nsw=my_nsw) + # + # directory = mode #solv-spe or solv-opt + # if not os.path.exists(directory): + # os.makedirs(directory) + # os.chdir(directory) + # shutil.copyfile('../spe/WAVECAR','WAVECAR') + # atoms = opt(atoms,dir_name='solv-spe',nsw=0,lwave=False,lsol=True) def run_specific_calcualtion_type(): - if self.calculation_type == 'opt': + if self.calculation_type == "opt": atoms = run_opt() - elif self.calculation_type == 'opt_fine': + elif self.calculation_type == "opt_fine": atoms = run_opt_fine() - elif self.calculation_type == 'vib': + elif self.calculation_type == "vib": atoms = run_vib() - elif self.calculation_type == 'solv': + elif self.calculation_type == "solv": atoms = run_vib() - - if 'solv' in mode: - if not 'solv-opt' in mode and not 'solv-spe' in mode: - print('ERROR: Check mode') + + if "solv" in mode: + if not "solv-opt" in mode and not "solv-spe" in mode: + print("ERROR: Check mode") sys.exit() cwd = os.getcwd() - if 'opt' in mode: - dir_name = 'opt' + if "opt" in mode: + dir_name = "opt" my_nsw = 100 - elif 'spe' in mode: - dir_name = 'spe' + elif "spe" in mode: + dir_name = "spe" my_nsw = 0 - atoms = opt(atoms,dir_name=dir_name,lwave=True,lsol=False,nsw=my_nsw) - - directory = mode #solv-spe or solv-opt + atoms = opt(atoms, dir_name=dir_name, lwave=True, lsol=False, nsw=my_nsw) + + directory = mode # solv-spe or solv-opt if not os.path.exists(directory): os.makedirs(directory) os.chdir(directory) - shutil.copyfile('../spe/WAVECAR','WAVECAR') - atoms = opt(atoms,dir_name='solv-spe',nsw=0,lwave=False,lsol=True) - + shutil.copyfile("../spe/WAVECAR", "WAVECAR") + atoms = opt(atoms, dir_name="solv-spe", nsw=0, lwave=False, lsol=True) + os.chdir(cwd) - - - - # vibrations - if 'vib' in mode and 'ts' not in mode and 'isolated' not in mode: + + # vibrations + if "vib" in mode and "ts" not in mode and "isolated" not in mode: atoms = apply_constraints(atoms) atoms = vib_workflow(atoms, **kwargs) - elif 'vib' in mode and 'ts' in mode: - atoms = apply_constraints(atoms) - atoms = vib_workflow(atoms,type_vib='ts',**kwargs) - elif 'vib' in mode and 'isolated' in mode: - atoms = vib_workflow(atoms,type_vib='isolated', **kwargs) - - # dimer - if mode == 'dimer': - if not os.path.exists('NEWMODECAR'): - atoms = io.read('dimer_start.traj') - atoms = apply_constraints(atoms) - dimer(atoms) - else: - atoms = io.read('CENTCAR',format='vasp') - shutil.copyfile('NEWMODECAR', 'MODECAR') - shutil.copyfile('OUTCAR', 'OUTCAR.bak') - shutil.copyfile('vasprun.xml', 'vasprun.xml.bak') - + elif "vib" in mode and "ts" in mode: + atoms = apply_constraints(atoms) + atoms = vib_workflow(atoms, type_vib="ts", **kwargs) + elif "vib" in mode and "isolated" in mode: + atoms = vib_workflow(atoms, type_vib="isolated", **kwargs) + + # dimer + if mode == "dimer": + if not os.path.exists("NEWMODECAR"): + atoms = io.read("dimer_start.traj") atoms = apply_constraints(atoms) dimer(atoms) - - return atoms - - - - - - - - - + else: + atoms = io.read("CENTCAR", format="vasp") + shutil.copyfile("NEWMODECAR", "MODECAR") + shutil.copyfile("OUTCAR", "OUTCAR.bak") + shutil.copyfile("vasprun.xml", "vasprun.xml.bak") + atoms = apply_constraints(atoms) + dimer(atoms) - + return atoms