From ead8c97047fc8b9c130c4d2c6ca9074b483df474 Mon Sep 17 00:00:00 2001 From: Thomas Young Cluster RITS Do NOT reset password <mmm0586@login04.thomas.ucl.ac.uk> Date: Mon, 21 Oct 2019 22:03:42 +0100 Subject: [PATCH 1/5] Revise incar.py with two new classes *Param* and *Params*, still compatible with previous usage, and make INCAR writing simple and extendable with VASP INCAR Parameters DataBase (vasp_para_db.py). --- vaspy/incar.py | 567 +++++++++++++++++++++++++++++++----------- vaspy/vasp_para_db.py | 173 +++++++++++++ 2 files changed, 597 insertions(+), 143 deletions(-) create mode 100644 vaspy/vasp_para_db.py diff --git a/vaspy/incar.py b/vaspy/incar.py index 18b65ae..64a3fa4 100644 --- a/vaspy/incar.py +++ b/vaspy/incar.py @@ -5,191 +5,210 @@ ======================================================================== Written by PytLab <shaozhengjiang@gmail.com>, October 2015 Updated by PytLab <shaozhengjiang@gmail.com>, July 2016 +Revised by jyxu <jxu15@qub.ac.uk>, October 2019 ======================================================================== """ +import os +import sys + import logging +import warnings from vaspy import VasPy +from vaspy.vasp_para_db import * -class InCar(VasPy): - def __init__(self, filename='INCAR'): +class Param(VasPy): + def __init__(self, pname, pvalue='', pcomm=''): """ - Create a INCAR file class. + Create a INCAR parameter class. Example: - - >>> a = InCar() + >>> para = Param('SYSTEM') Class attributes descriptions ======================================================= Attribute Description ============ ======================================= - filename string, name of INCAR file + pname string, parameter name + pvalue string/int/flaot, parameter value + pcomm string, parameter comment ============ ======================================= + """ - super(self.__class__, self).__init__(filename) - self.filename = filename - self.load() + __slots__ = ('para', 'pname', 'pvalue', 'pcomm') - # Set logger. - self.__logger = logging.getLogger("vaspy.InCar") + self._pname, self._pvalue, self._pcomm = None, None, None - def load(self): - "Load all data in INCAR." - tot_pnames, tot_datas = [], [] - with open(self.filename, 'r') as f: - for line in f: - matched = self.rdata(line) - if matched: - pnames, datas = matched - tot_pnames.extend(pnames) - tot_datas.extend(datas) - # set attrs - for pname, data in zip(tot_pnames, tot_datas): - setattr(self, pname, data) - - # Set parameter names and data lists. -# sorted_pnames, sorted_datas = self.__sort_two_lists(tot_pnames, tot_datas) -# self.pnames = sorted_pnames -# self.datas = sorted_datas - self.pnames = tot_pnames - self.datas = tot_datas + self.pname = pname + self.pvalue, self.pcomm = str(pvalue), str(pcomm) - return + self.__logger = logging.getLogger("vaspy.Param") - def __sort_two_lists(self, list1, list2): - """ - Private helper function to sort two lists. - """ - assert len(list1) == len(list2) - # Sort the pairs according the entries of list1. - sorted_pairs = sorted(zip(list1, list2), key=lambda pair: pair[0]) - sorted_list1, sorted_list2 = [list(x) for x in zip(*sorted_pairs)] + @property + def pname(self): + """Parameter Name""" + return self._pname - return sorted_list1, sorted_list2 + @pname.setter + def pname(self, name): + """""" + name = name.upper() + if name not in INCAR_PARAMETERS.keys(): + raise ValueError("Unknown Parameter <%s> in VASP INCAR Database." %name) + self._pname = name - @staticmethod - def rdata(line): - "Get INCAR data(s) in a line." - line = line.strip() - if not line or line.startswith(('!', '#')): - return None + return + + @property + def pvalue(self): + """Parameter Value""" + return self._pvalue + + @pvalue.setter + def pvalue(self, value): + """""" + optional_values = [str(v) for v in INCAR_PARAMETERS[self.pname][1]] + + # check optional values, under development + ''' + if optional_values == [] or value in optional_values: + pass else: - if '#' in line: - line = line.split('#')[0].strip() - if '!' in line: - line = line.split('!')[0].strip() - elif '!' in line: - line = line.split('!')[0].strip() - # get parameter name and data - if ';' in line: - params = [param.strip() for param in line.split(';')] - else: - params = [line] - pnames, datas = [], [] - for param in params: - pname, data = [i.strip() for i in param.split('=')] - pnames.append(pname) - datas.append(data) + raise ValueError("Unknown Value <%s> for Parameter <%s>." \ + %(value, self.pname)) + ''' + + if value != '': + default_value = value + else: + default_value = INCAR_PARAMETERS[self.pname][0] - return pnames, datas + self._pvalue = str(default_value) - def set(self, pname, data): - """ - Set a named parameter of InCar object. + return - Example: - -------- - >>> incar_obj.set("ISIF", 2) - """ - if not hasattr(self, pname): - raise ValueError('%s is not in INCAR, ' + - 'Use add() instead.' % pname) - setattr(self, pname, str(data)) + @property + def pcomm(self): + """Parameter Comment""" + return self._pcomm - return + @pcomm.setter + def pcomm(self, comm): + """""" + if comm == '': + comm = " ".join((COMMSIGN, INCAR_PARAMETERS[self.pname][2])) + else: + if not comm.startswith(COMMSIGN): + comm = " ".join((COMMSIGN, comm)) - def add(self, pname, data): - """ - Add a new parameter name to InCar object. + self._pcomm = comm - Example: - -------- - >>> incar_obj.add("ISIF", 2) + return + + @property + def para(self): + """""" + return (self.pname, self.pvalue, self.pcomm) + + def __add__(self, another): + """ + Overload the add operator, a *Param* adds a *Param*/*Params* equal *Params*. """ - data = str(data) - if hasattr(self, pname): - msg = "{} is already in INCAR, set to {}".format(pname, data) - self.__logger.warning(msg) + if isinstance(another, Param): + return Params((self, another)) + elif isinstance(another, Params): + return Params((self,) + another.paras) else: - self.pnames.append(pname) - setattr(self, pname, data) + raise ValueError("Add must also be a *Param*/*Params* object.") - return + def __repr__(self): + return str(self.para) - def pop(self, pname): + +class Params(VasPy): + def __init__(self, paras=()): """ - Delete a parameter from InCar object. + Create a INCAR parameters class. + """ + # set logger + self.__logger = logging.getLogger("vaspy.Params") - Returns: - -------- - parameter name, parameter value. + if paras == (): + self.paras = () + elif isinstance(paras, list) or isinstance(paras, tuple): + self.paras = self.remove_duplicates(paras) + else: + self("%s must be a *list* or *tuple* object." %paras) + + def remove_duplicates(self, paras): + """Remove duplicates in paras, return a tuple""" + paras_list = [] + for para in paras: + if isinstance(para, Param): + pnames = [p.pname for p in paras_list] + if para.pname in pnames: + warnings.warn("Duplicate parameter " + \ + "%s, value %s(old) %s(new), the new one is not read."\ + %(para.pname, paras_list[pnames.index(para.pname)], \ + para.pvalue), RuntimeWarning) + else: + paras_list.append(para) + else: + raise ValueError("%s must be a *Param* object." %para) - Example: - -------- - >>> incar_obj.del("ISIF") - """ - if not hasattr(self, pname): - msg = "InCar has no parameter '{}'".format(pname) - self.__logger.warning(msg) - return + return tuple(paras_list) + + @property + def pnames(self): + """Return all parameters' names.""" + self._pnames = [p.pname for p in self.paras] - # Delete from pnames and datas. - idx = self.pnames.index(pname) - self.pnames.pop(idx) - data = self.datas.pop(idx) + return tuple(self._pnames) - # Delete attribute. - del self.__dict__[pname] + @property + def pvalues(self): + """""" + self._pvalues = [p.pvalue for p in self.paras] - return pname, data + return tuple(self._pvalues) - def compare(self, another): - """ - Function to compare two InCar objects. - - Parameters: - ----------- - another: Another InCar object. + def get_para(self, name): + """""" + return self.paras[self.pnames.index(name)] - Returns: - -------- - A tuple of two dictionaries containing difference informations. + def get_pvalue(self, name): + """""" + return self.pvalues[self.pnames.index(name)] + + def __compare(self, another): """ - tot_pnames = set(self.pnames + another.pnames) + Private method to compare two Params object. + """ + self_pnames, another_pnames = self.pnames, another.pnames + tot_pnames = set(list(self_pnames) + list(another_pnames)) self_dict, another_dict = {}, {} for pname in tot_pnames: # If both have, check the difference. - if (pname in self.pnames and pname in another.pnames): - self_data = getattr(self, pname) - another_data = getattr(another, pname) - if self_data != another_data: - self_dict.setdefault(pname, self_data) - another_dict.setdefault(pname, another_data) + if (pname in self_pnames and pname in another_pnames): + self_pvalue = self.get_pvalue(pname) + another_pvalue = self.get_pvalue(pname) + if self_pvalue != another_pvalue: + self_dict.setdefault(pname, self_pvalue) + another_dict.setdefault(pname, another_pvalue) else: # Only in this object. - if pname in self.pnames: - self_data = getattr(self, pname) - self_dict.setdefault(pname, self_data) + if pname in self_pnames: + self_pvalue = self.get_pvalue(pname) + self_dict.setdefault(pname, self_pvalue) another_dict.setdefault(pname, "") # Only in the other object. else: - another_data = getattr(another, pname) - another_dict.setdefault(pname, another_data) + another_pvalue = self.get_pvalue(pname) + another_dict.setdefault(pname, another_pvalue) self_dict.setdefault(pname, "") return self_dict, another_dict @@ -198,7 +217,8 @@ def __eq__(self, another): """ Overload euqal operator function. """ - self_dict, another_dict = self.compare(another) + self_dict, another_dict = self.__compare(another) + # print(self_dict, another_dict) if (not self_dict) and (not another_dict): return True @@ -214,20 +234,281 @@ def __ne__(self, another): else: return True - def tofile(self, filename=None): - "Create INCAR file." + def __add__(self, another): + """ + Overload add operator, append a *Param*/*Params* to a *Params* + """ + if isinstance(another, Param): + paras = self.paras + (another,) + elif isinstance(another, Params): + paras = self.paras + another.paras + + paras = self.remove_duplicates(paras) + + return Params(paras) + + def add(self, pname, pvalue=''): + """ + Add a new parameter to *Params* object. + Now only param object are supported. + Different from __add__, which does not change the *Param* object. + + Example: + -------- + >>> paras.add('ISIF', 2) + """ + para = Param(pname, pvalue) + paras = (self + para).paras + self.paras = paras + + return self + + def __sub__(self, another): + """ + Overload sub operator, remove a *Param*/*Params* to a *Params* + """ + if isinstance(another, Param): + paras = (para for para in self.paras if para.pname != another.pname) + elif isinstance(another, Params): + paras = (para for para in self.paras if para.pname not in another.pnames) + + self.paras = tuple(paras) + + return self + + def set(self, name, value): + """ + Set a named parameter of InCar object. + + Example: + -------- + >>> incar_obj.set("ISIF", 2) + """ + if name not in self.pnames: + raise ValueError('%s is not in INCAR, ' + 'Use add() instead.' % name) + + self.get_para(name).pvalue = str(value) + + return + + def pop(self, pname): + """ + Delete a parameter from InCar object. + + Returns: + -------- + parameter name, parameter value. + + Example: + -------- + >>> incar_obj.pop("ISIF") + """ + if pname not in self.pnames: + raise ValueError('%s is not in INCAR, ' + 'Use add() instead.' % name) + + # Delete from pnames and datas. + value = self.get_pvalue(pname) + paras = (self - self.get_para(pname)).paras + self.paras = paras + + return pname, value + + def __len__(self): + """ + Overload len operator, return the number of parameters. + """ + return len(self.paras) + + def __repr__(self): + """ + """ + return str(self.paras) + + +class InCar(Params): + def __init__(self, src=None): + """ + Create a INCAR file class. + + Example: + + >>> a = InCar() + + Class attributes descriptions + ======================================================= + Attribute Description + ============ ======================================= + src string/Params, incar parameter source + ============ ======================================= + """ + # super(self.__class__, self).__init__(src) + if src is None: + self.paras = () + else: + if isinstance(src, str): + if os.path.isfile(src): + self.filename = src + self.paras = self.load() + elif isinstance(src, Params): + self.paras = src.paras + + self.paras = self.remove_duplicates(self.paras) + self.parasets = None + + # set logger + self.__logger = logging.getLogger("vaspy.InCar") + + def load(self): + "Load all data in INCAR." + tot_pnames, tot_pvalues, tot_pcomms = [], [], [] + with open(self.filename, 'r') as reader: + for line in reader: + matched = self.rdata(line) + if matched: + pnames, pvalues, pcomms = matched + tot_pnames.extend(pnames) + tot_pvalues.extend(pvalues) + tot_pcomms.extend(pcomms) + + paras_list = [] + for pname, pvalue, pcomm in zip(tot_pnames, tot_pvalues, tot_pcomms): + para = Param(pname, pvalue, pcomm) + paras_list.append(para) + + return tuple(paras_list) + + @staticmethod + def rdata(line): + "Get INCAR data(s) in a line." + line = line.strip() + if not line or line.startswith(('!', '#')): + return None + else: + pnames, pvalues, pcomms = [], [], [] + value, comm = '', '' + if '#' in line: + splitted_line = line.split('#') + value = splitted_line[0].strip() + comm = splitted_line[1].strip() + if '!' in value: + splitted_value = value.split('!') + value = splitted_value[0].strip() + comm = ' '.join(comm, splitted_value[1].strip()) + elif '!' in line: + splitted_line = line.split('!') + value = splitted_line[0].strip() + comm = splitted_line[1].strip() + if '#' in value: + splitted_value = value.split('#') + value = splitted_value[0].strip() + comm = ' '.join(comm, splitted_value[1].strip()) + else: + value = line + pcomms.append(comm) + # get parameter name and data + if ';' in value: + params = [param.strip() for param in value.split(';')] + else: + params = [value] + for param in params: + pname, pvalue = [i.strip() for i in param.split('=')] + pnames.append(pname) + pvalues.append(pvalue) + + return pnames, pvalues, pcomms + + def quickgen(self, tasks, **kargs): + """Quick generation of INCAR with built-in parameters.""" + # check task + tasks = tasks.strip().split('-') + task_basic = ['SC'] + if 'SC' not in tasks: + task_basic.extend(tasks) + tasks = task_basic + + parasets = [] + for task in tasks: + if task in BUILTIN_PARASETS.keys(): + parasets.extend(BUILTIN_PARASETS[task][0]) + else: + msg = "Unsupported INCAR parameter set %s." %task + self.__logger.error(msg) + sys.exit(1) + + self.parasets = parasets + + # load parasets + self.incar_categories = INCAR_PARACATEGORIES + pnames = [] + for pset in self.parasets: + pnames.extend(list(self.incar_categories[pset])) + + paras_list = [] + for pname in pnames: + paras_list.append(Param(pname)) + + self.paras = tuple(paras_list) + + # special settings for some task + paras_list = [] + for task in tasks: + for para in BUILTIN_PARASETS[task][1]: + self.get_para(para[0]).pvalue = para[1] + + # add more parameters along with built-in parasets + for key, value in kargs.items(): + self.set(key, str(value)) + + return + + def tostr(self): + """""" content = '# Created by VASPy\n' - for pname in self.pnames: - if not hasattr(self, pname): - raise ValueError('Unknown parameter: %s' % pname) - data = str(getattr(self, pname)) - content += '%s = %s\n' % (pname, data) + if self.parasets: + tot_pnames = [] + for pset in self.parasets: + content += '# %s\n' %pset + pnames = INCAR_PARACATEGORIES[pset] + tot_pnames.extend(pnames) + for pname in pnames: + para = self.get_para(pname) + content += PARAFORMAT.format(para.pname, para.pvalue, para.pcomm) + content += '\n' + + other_pnames = [pname for pname in self.pnames \ + if pname not in tot_pnames] + if len(other_pnames) != 0: + content += '# Additional\n' + for pname in other_pnames: + para = self.get_para(pname) + content += PARAFORMAT.format(para.pname, para.pvalue, para.pcomm) + content += '\n' + else: + for para in self.paras: + content += PARAFORMAT.format(para.pname, para.pvalue, para.pcomm) - # Write to file. + return content + + def tofile(self, filename='INCAR', verbos=True): + "Create INCAR file." if filename is None: - filename = self.filename - with open(filename, 'w') as f: - f.write(content) + self.__logger.error("Filename to write INCAR is needed.") + else: + if os.path.exists(filename): + self.__logger.warning("%s exists will be overrided." %filename) + + content = self.tostr() + with open(filename, 'w') as writer: + writer.write(content) + + self.__logger.info("Succesfully write incar obejct to %s." %filename) + + if verbos: + print(content) return + + def __repr__(self): + """""" + return self.tostr() diff --git a/vaspy/vasp_para_db.py b/vaspy/vasp_para_db.py new file mode 100644 index 0000000..0afb121 --- /dev/null +++ b/vaspy/vasp_para_db.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Golabel Variables Descriptions (Most Frequently Used INCAR Parameters) +=============================================================================== + Attribute Description + ====================== =================================================== + COMMSIGN comment sign in INCAR file + PARAFORMAT format of parameter in INCAR + INCAR_PARAMETERS a dictionary of INCAR parameters + INCAR_PARACATEGORIES different groups of INCAR parameters + BUILTIN_PARASETS built-in parameter groups for quick-generation + ====================== =================================================== +""" + +COMMSIGN = '#' + +PARAFORMAT = " {:<12s} = {:<24s} {:<s}\n" + +INCAR_PARAMETERS = { + # paraname defaultvalue paracomm + # GENERAL + "SYSTEM" : ["example" , (), + "system name"], + "NWRITE" : ["2" , (0, 1, 2, 3, 4), + "verbosity flag, 0|1|*2|3|4"], + "ISTART" : ["0" , (0, 1), + "0 New | 1 Restart"], + "ICHARG" : ["2" , (0, 1, 2, 4), + "0 orbital | 1 CHGCAR | *2 superposition | 4 POT"], + # parallel + "NPAR" : ["6" , (), + ""], + # MAGNETIC + "ISPIN" : ["2" , (1, 2), + "*1 no | 2 yes"], + "MAGMOM" : [" " , (), + "array, spin per atom"], + # WAVEFUNC + "INIWAV" : ["1" , (0, 1), + "0 jellium | *1 random"], + "LWAVE" : [".FALSE." , (".TRUE.", ".FALSE."), + "if write WAVECAR"], + # CHARGE + "LCHARG" : [".FALSE." , (".TRUE.", ".FALSE."), + "if write CHGCAR"], + # ELECTRONIC + "ENCUT" : ["450" , (), + "energy cutoff"], + "PREC" : ["Accurate" , + ("Low", "Medium", "High", "Normal", "Accurate", "Single"), + "precision"], + "EDIFF" : ["1.0E-5" , (), + "stopping criterion for electronic updates"], + "NELM" : ["300" , (), + "maximium number of ionic updates"], + "NELMIN" : ["6" , (), + "minimium number of ionic updates"], + # IONIC + "EDIFFG" : ["-0.05" , (), + "stopping criterion for ionic updates"], + "NSW" : ["1000" , (), + "number of steps for ionic updates"], + "IBRION" : ["2" , (0,1,2,3,5), + "0 MD | 1 quasi-Newton | 2 CG | 3 damped-MD | 5 FC"], + "ISIF" : ["2" , (0, 1, 2, 3, 4, 5, 6), + "0 MD | *2 | 3 lat opt"], + "POTIM" : ["0.2" , (), + "ionic step size / MD time step"], + # Molecular Dynamics + "TEBEG" : ["300" , (), + "begin temperature"], + "TEEND" : ["300" , (), + "end temperature"], + "SMASS" : ["3" , (-3, -2, -1, 0, 3), + "controls velocities during AIMD"], + "NBLOCK" : ["10" , (), + "update XDATCAR every NBLOCK fs"], + # Smearing + "ISMEAR" : ["0" , (-5, 0, 1), + "-5 DOS | 0 large cell | 1 metal"], + "SIGMA" : ["0.05" , (), + "smearing parameter"], + # ALGO + "ALGO" : ["Fast" , ("ALL", "Normal", "Fast", "Very Fast"), + "algorithms for electronic self-consistent"], + "IALGO" : ["48" , (), + "8 CG | 48 RMM-DIIS"], + "LREAL" : ["Auto" , ("Auto", ".TRUE.", ".FALSE."), + "if calculation done in real spcae"], + "ISYM" : ["2" , (0, 1, 2, 3), + "0 off | 1 on | 2 charge | 3 no charge"], + # BAND + "LORBIT" : ["11" , (), + "PAW radii for projected DOS"], + "NEDOS" : ["2001" , (), + "DOSCAR points"], + # vdW + "IVDW" : ["11" , (), + "DFT-D3 without BJ damping"], + "VDW_s6" : ["1.0" , (), + "s6-scaling parameter (kept fix at 1.0)"], + "VDW_s8" : ["0.7875" , (), + "s8 for PBE"], + "VDW_a1" : ["0.4289" , (), + "a1 damping parameter for PBE"], + "VDW_a2" : ["4.4407" , (), + "a2 damping parameter for PBE"], + # DFT+U(J) + "LDAU" : [".TRUE." , (".TRUE.", ".FALSE."), + "Enable DFTU calculation"], + "LDAUTYPE" : ["2" , (1, 2, 4), + "1 Liechtenstein | *2 Dudarev | 4"], "LDAUL" : ["" , (), + "-1 off | 1 p | 2 d | 3 f"], + "LDAUU" : ["" , (), + "coulomb interaction"], + "LDAUJ" : ["" , (), + "exchange interaction"], + "LDAUPRINT" : ["2" , (0, 1, 2), + "*0 silent | 1 occupancy | 2 idem"], + "LMAXMIX" : ["4" , (2, 4, 6), + "twice the max l-quantum number"], + # Hybrid Functional + "LHFCALC" : [".TRUE." , (), + "Enable HF calculation"], + "AEXX" : ["0.25" , (), + "Hartree-Fock percentage"], + "PREFOCK" : ["Accurate" , (), + ""], + "LMAXFOCK" : ["4" , (4, 6), + "4 s/p | 6 f"], + "HFSCREEN" : ["0.2" , (), + "HSE06"], + "TIME" : ["0.4" , (), + ""], + + } + +INCAR_PARACATEGORIES = { + # catname paranames + "GENERAL" : ["SYSTEM", "NWRITE", "ISTART"], + "PARALLEL" : ["NPAR"], + "WAVEFUNC" : ["INIWAV", "LWAVE"], + "CHARGE" : ["LCHARG"], + "MAGNETIC" : ["ISPIN"], + "ELECTRONIC": ["ENCUT", "PREC", "EDIFF", "NELM", "NELMIN"], + "IONIC" : ["EDIFFG", "NSW", "IBRION", "ISIF", "POTIM"], + "MD" : ["TEBEG", "TEEND", "SMASS", "NBLOCK"], + "SMEARING" : ["ISMEAR", "SIGMA"], + "VDW" : ["IVDW"], + "VDWBJ" : ["IVDW", "VDW_s6", "VDW_s8", "VDW_a1", "VDW_a2"], + "ALGO" : ["ALGO", "LREAL", "ISYM"], + "UJ" : ["LDAU", "LDAUTYPE", "LDAUU", "LDAUJ", "LDAUPRINT", "LMAXMIX"], + "HF" : ["LHFCALC", "AEXX", "PREFOCK", "LMAXFOCK", "HFSCREEN", "TIME"], + } + +BASIC_PARAS = ["GENERAL", "PARALLEL", "ELECTRONIC", "MAGNETIC", \ + "SMEARING", "ALGO", "IONIC"] +BUILTIN_PARASETS = { + # task paras specail settings + 'SC' : [BASIC_PARAS , + []], + 'MD' : [["MD"] , + [('IBRION', 0), ('ISIF', 0), ('POTIM', 1.0), ('NSW', 15000), + ('ALGO', 'Very Fast'), ('NELM', '60')]], + 'BAND' : [["BAND"] , []], + 'VDW' : [["VDW"] , []], + 'VDWBJ' : [["VDWBJ"] , []], + 'UJ' : [["UJ"] , []], + 'HF' : [["HF"] , + [('ISYM', 3), ('ALGO', 'ALL')]], + } + From 1fe280a51fe73f99605d0e6a5c17895262b5ca17 Mon Sep 17 00:00:00 2001 From: jyxu <ahcigar@foxmail.com> Date: Tue, 22 Oct 2019 20:50:54 +0100 Subject: [PATCH 2/5] Make *InCar* obeject default value as INCAR, compatable with previous usage --- vaspy/incar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vaspy/incar.py b/vaspy/incar.py index 64a3fa4..b1a7244 100644 --- a/vaspy/incar.py +++ b/vaspy/incar.py @@ -326,7 +326,7 @@ def __repr__(self): class InCar(Params): - def __init__(self, src=None): + def __init__(self, src='INCAR'): """ Create a INCAR file class. From df98ab70b5a73c49f63b50bc6fff765b69b61e21 Mon Sep 17 00:00:00 2001 From: jyxu <ahcigar@foxmail.com> Date: Wed, 23 Oct 2019 10:29:50 +0100 Subject: [PATCH 3/5] add electronic mixing algo para in vasp_para_db.py --- vaspy/vasp_para_db.py | 52 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/vaspy/vasp_para_db.py b/vaspy/vasp_para_db.py index 0afb121..aedc31c 100644 --- a/vaspy/vasp_para_db.py +++ b/vaspy/vasp_para_db.py @@ -73,9 +73,20 @@ "TEEND" : ["300" , (), "end temperature"], "SMASS" : ["3" , (-3, -2, -1, 0, 3), - "controls velocities during AIMD"], + "controls velocities in MD, -3 | -2 | -1 | >=0 Nosé"], "NBLOCK" : ["10" , (), "update XDATCAR every NBLOCK fs"], + # Advanced Molecualr Dynamics + "MDALGO" : ["21" , (0, 1, 2, 3, 11, 21, 13), + "0 standard MD | 21 meta Nose-Hoover"], + "LBLUEOUT" : [".FALSE." , (".TRUE.", ".FALSE."), + "print out free-energy gradient"], + # US + "HILLS_BIN" : ["15000" , (), + "bias potential update interval"], + # slow-grownth + "INCREM" : ["0" , (), + "increment in slow-grownth algo"], # Smearing "ISMEAR" : ["0" , (-5, 0, 1), "-5 DOS | 0 large cell | 1 metal"], @@ -90,6 +101,28 @@ "if calculation done in real spcae"], "ISYM" : ["2" , (0, 1, 2, 3), "0 off | 1 on | 2 charge | 3 no charge"], + "NSIM" : ["4" , (), + "blocked band update"], + # ALGO-Mixing + "IMIX" : ["4" , (), + "0 no mix | 1 Kerker | 2 Tchebycheff | 4 Broyden2"], + "AMIX" : ["0.4" , (), + "linear mixing parameter"], + "AMIN" + "BMIX" : ["1.0" , (), + "cutoff wave vector for Kerker mixing scheme"], + "AMIX_MAG" : ["1.6" , (), + "linear mixing parameter for magnetization"], + "BMIX_MAG" : ["1.0" , (), + ""], + "WC" : ["1000" , (), + "weight factor in each step in Broyden"], + "INIMIX" : ["1" , (), + "initial mixing in Broyden"], + "MIXPRE" : ["1" , (), + "preconditioning in Broyden"], + "MAXMIX" : ["-45" , (), + "maximum number steps stored in Broyden mixer"], # BAND "LORBIT" : ["11" , (), "PAW radii for projected DOS"], @@ -110,7 +143,8 @@ "LDAU" : [".TRUE." , (".TRUE.", ".FALSE."), "Enable DFTU calculation"], "LDAUTYPE" : ["2" , (1, 2, 4), - "1 Liechtenstein | *2 Dudarev | 4"], "LDAUL" : ["" , (), + "1 Liechtenstein | *2 Dudarev | 4"], + "LDAUL" : ["" , (), "-1 off | 1 p | 2 d | 3 f"], "LDAUU" : ["" , (), "coulomb interaction"], @@ -133,7 +167,13 @@ "HSE06"], "TIME" : ["0.4" , (), ""], - + # POTCAR related + "POMASS" : ["" , (), + "mass each atomic species in a.u."], + "ZVAL" : ["" , (), + "valence for each atomic species"], + "RWIGS" : ["" , (), + "Wigner-Seitz radius"], } INCAR_PARACATEGORIES = { @@ -161,8 +201,10 @@ 'SC' : [BASIC_PARAS , []], 'MD' : [["MD"] , - [('IBRION', 0), ('ISIF', 0), ('POTIM', 1.0), ('NSW', 15000), - ('ALGO', 'Very Fast'), ('NELM', '60')]], + [('IBRION', 0), ('ISIF', 0), ('POTIM', 1.0), ('NSW', 15000), + ('PREC', 'Normal'), ('EDIFFG', -0.01), + ('ALGO', 'Very Fast'), ('ISYM', 0), + ('NELM', '120')]], 'BAND' : [["BAND"] , []], 'VDW' : [["VDW"] , []], 'VDWBJ' : [["VDWBJ"] , []], From 2a9358b7a113e83fc67a0dd38161e27f3c65cb2b Mon Sep 17 00:00:00 2001 From: jyxu <ahcigar@foxmail.com> Date: Wed, 23 Oct 2019 11:35:08 +0100 Subject: [PATCH 4/5] fix a bug which happens when no src is used when creating *InCar* object --- vaspy/incar.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/vaspy/incar.py b/vaspy/incar.py index b1a7244..4858611 100644 --- a/vaspy/incar.py +++ b/vaspy/incar.py @@ -342,6 +342,10 @@ def __init__(self, src='INCAR'): ============ ======================================= """ # super(self.__class__, self).__init__(src) + if src == 'INCAR': + if not os.path.exists('INCAR'): + src = None + if src is None: self.paras = () else: @@ -352,7 +356,8 @@ def __init__(self, src='INCAR'): elif isinstance(src, Params): self.paras = src.paras - self.paras = self.remove_duplicates(self.paras) + if self.paras != (): + self.paras = self.remove_duplicates(self.paras) self.parasets = None # set logger From f74184818645df99a510933e1a1cee4c0fde003d Mon Sep 17 00:00:00 2001 From: hsulab <ahcigar@foxmail.com> Date: Wed, 29 Jul 2020 22:31:27 +0100 Subject: [PATCH 5/5] update few parameters used in INCAR --- vaspy/incar.py | 4 +++- vaspy/vasp_para_db.py | 23 ++++++++++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/vaspy/incar.py b/vaspy/incar.py index 4858611..7d8ae6f 100644 --- a/vaspy/incar.py +++ b/vaspy/incar.py @@ -426,10 +426,12 @@ def quickgen(self, tasks, **kargs): """Quick generation of INCAR with built-in parameters.""" # check task tasks = tasks.strip().split('-') + + # check if SC in tasks task_basic = ['SC'] if 'SC' not in tasks: task_basic.extend(tasks) - tasks = task_basic + tasks = task_basic parasets = [] for task in tasks: diff --git a/vaspy/vasp_para_db.py b/vaspy/vasp_para_db.py index aedc31c..30053d9 100644 --- a/vaspy/vasp_para_db.py +++ b/vaspy/vasp_para_db.py @@ -30,7 +30,9 @@ "0 orbital | 1 CHGCAR | *2 superposition | 4 POT"], # parallel "NPAR" : ["6" , (), - ""], + "NCORE=ncores/NPAR"], + "NCORE" : ["8" , (), + "cores/orbital, Better use NPAR"], # MAGNETIC "ISPIN" : ["2" , (1, 2), "*1 no | 2 yes"], @@ -39,11 +41,12 @@ # WAVEFUNC "INIWAV" : ["1" , (0, 1), "0 jellium | *1 random"], - "LWAVE" : [".FALSE." , (".TRUE.", ".FALSE."), - "if write WAVECAR"], # CHARGE + # Writing "LCHARG" : [".FALSE." , (".TRUE.", ".FALSE."), "if write CHGCAR"], + "LWAVE" : [".FALSE." , (".TRUE.", ".FALSE."), + "if write WAVECAR"], # ELECTRONIC "ENCUT" : ["450" , (), "energy cutoff"], @@ -56,6 +59,12 @@ "maximium number of ionic updates"], "NELMIN" : ["6" , (), "minimium number of ionic updates"], + # dipole correction + "IDIPOL" : ["3" , (), + "surface 3"], + # hole/electron + "NELECT" : ["0" , (), + "number of electrons"], # IONIC "EDIFFG" : ["-0.05" , (), "stopping criterion for ionic updates"], @@ -179,9 +188,9 @@ INCAR_PARACATEGORIES = { # catname paranames "GENERAL" : ["SYSTEM", "NWRITE", "ISTART"], + "WRITING" : ["LCHARG", "LWAVE"], "PARALLEL" : ["NPAR"], - "WAVEFUNC" : ["INIWAV", "LWAVE"], - "CHARGE" : ["LCHARG"], + "WAVEFUNC" : ["INIWAV"], "MAGNETIC" : ["ISPIN"], "ELECTRONIC": ["ENCUT", "PREC", "EDIFF", "NELM", "NELMIN"], "IONIC" : ["EDIFFG", "NSW", "IBRION", "ISIF", "POTIM"], @@ -190,11 +199,11 @@ "VDW" : ["IVDW"], "VDWBJ" : ["IVDW", "VDW_s6", "VDW_s8", "VDW_a1", "VDW_a2"], "ALGO" : ["ALGO", "LREAL", "ISYM"], - "UJ" : ["LDAU", "LDAUTYPE", "LDAUU", "LDAUJ", "LDAUPRINT", "LMAXMIX"], + "UJ" : ["LDAU", "LDAUTYPE", "LDAUL", "LDAUU", "LDAUJ", "LDAUPRINT", "LMAXMIX"], "HF" : ["LHFCALC", "AEXX", "PREFOCK", "LMAXFOCK", "HFSCREEN", "TIME"], } -BASIC_PARAS = ["GENERAL", "PARALLEL", "ELECTRONIC", "MAGNETIC", \ +BASIC_PARAS = ["GENERAL", "WRITING", "PARALLEL", "ELECTRONIC", "MAGNETIC", \ "SMEARING", "ALGO", "IONIC"] BUILTIN_PARASETS = { # task paras specail settings