/vaspy/incar.py

https://github.com/PytLab/VASPy · Python · 233 lines · 126 code · 30 blank · 77 comment · 36 complexity · cb83de96419806408667a3fe67c357be MD5 · raw file

  1. # -*- coding:utf-8 -*-
  2. """
  3. ========================================================================
  4. Provide INCAR file class which do operations on these files.
  5. ========================================================================
  6. Written by PytLab <shaozhengjiang@gmail.com>, October 2015
  7. Updated by PytLab <shaozhengjiang@gmail.com>, July 2016
  8. ========================================================================
  9. """
  10. import logging
  11. from vaspy import VasPy
  12. class InCar(VasPy):
  13. def __init__(self, filename='INCAR'):
  14. """
  15. Create a INCAR file class.
  16. Example:
  17. >>> a = InCar()
  18. Class attributes descriptions
  19. =======================================================
  20. Attribute Description
  21. ============ =======================================
  22. filename string, name of INCAR file
  23. ============ =======================================
  24. """
  25. super(self.__class__, self).__init__(filename)
  26. self.filename = filename
  27. self.load()
  28. # Set logger.
  29. self.__logger = logging.getLogger("vaspy.InCar")
  30. def load(self):
  31. "Load all data in INCAR."
  32. tot_pnames, tot_datas = [], []
  33. with open(self.filename, 'r') as f:
  34. for line in f:
  35. matched = self.rdata(line)
  36. if matched:
  37. pnames, datas = matched
  38. tot_pnames.extend(pnames)
  39. tot_datas.extend(datas)
  40. # set attrs
  41. for pname, data in zip(tot_pnames, tot_datas):
  42. setattr(self, pname, data)
  43. # Set parameter names and data lists.
  44. # sorted_pnames, sorted_datas = self.__sort_two_lists(tot_pnames, tot_datas)
  45. # self.pnames = sorted_pnames
  46. # self.datas = sorted_datas
  47. self.pnames = tot_pnames
  48. self.datas = tot_datas
  49. return
  50. def __sort_two_lists(self, list1, list2):
  51. """
  52. Private helper function to sort two lists.
  53. """
  54. assert len(list1) == len(list2)
  55. # Sort the pairs according the entries of list1.
  56. sorted_pairs = sorted(zip(list1, list2), key=lambda pair: pair[0])
  57. sorted_list1, sorted_list2 = [list(x) for x in zip(*sorted_pairs)]
  58. return sorted_list1, sorted_list2
  59. @staticmethod
  60. def rdata(line):
  61. "Get INCAR data(s) in a line."
  62. line = line.strip()
  63. if not line or line.startswith(('!', '#')):
  64. return None
  65. else:
  66. if '#' in line:
  67. line = line.split('#')[0].strip()
  68. if '!' in line:
  69. line = line.split('!')[0].strip()
  70. elif '!' in line:
  71. line = line.split('!')[0].strip()
  72. # get parameter name and data
  73. if ';' in line:
  74. params = [param.strip() for param in line.split(';')]
  75. else:
  76. params = [line]
  77. pnames, datas = [], []
  78. for param in params:
  79. pname, data = [i.strip() for i in param.split('=')]
  80. pnames.append(pname)
  81. datas.append(data)
  82. return pnames, datas
  83. def set(self, pname, data):
  84. """
  85. Set a named parameter of InCar object.
  86. Example:
  87. --------
  88. >>> incar_obj.set("ISIF", 2)
  89. """
  90. if not hasattr(self, pname):
  91. raise ValueError('%s is not in INCAR, ' +
  92. 'Use add() instead.' % pname)
  93. setattr(self, pname, str(data))
  94. return
  95. def add(self, pname, data):
  96. """
  97. Add a new parameter name to InCar object.
  98. Example:
  99. --------
  100. >>> incar_obj.add("ISIF", 2)
  101. """
  102. data = str(data)
  103. if hasattr(self, pname):
  104. msg = "{} is already in INCAR, set to {}".format(pname, data)
  105. self.__logger.warning(msg)
  106. else:
  107. self.pnames.append(pname)
  108. setattr(self, pname, data)
  109. return
  110. def pop(self, pname):
  111. """
  112. Delete a parameter from InCar object.
  113. Returns:
  114. --------
  115. parameter name, parameter value.
  116. Example:
  117. --------
  118. >>> incar_obj.del("ISIF")
  119. """
  120. if not hasattr(self, pname):
  121. msg = "InCar has no parameter '{}'".format(pname)
  122. self.__logger.warning(msg)
  123. return
  124. # Delete from pnames and datas.
  125. idx = self.pnames.index(pname)
  126. self.pnames.pop(idx)
  127. data = self.datas.pop(idx)
  128. # Delete attribute.
  129. del self.__dict__[pname]
  130. return pname, data
  131. def compare(self, another):
  132. """
  133. Function to compare two InCar objects.
  134. Parameters:
  135. -----------
  136. another: Another InCar object.
  137. Returns:
  138. --------
  139. A tuple of two dictionaries containing difference informations.
  140. """
  141. tot_pnames = set(self.pnames + another.pnames)
  142. self_dict, another_dict = {}, {}
  143. for pname in tot_pnames:
  144. # If both have, check the difference.
  145. if (pname in self.pnames and pname in another.pnames):
  146. self_data = getattr(self, pname)
  147. another_data = getattr(another, pname)
  148. if self_data != another_data:
  149. self_dict.setdefault(pname, self_data)
  150. another_dict.setdefault(pname, another_data)
  151. else:
  152. # Only in this object.
  153. if pname in self.pnames:
  154. self_data = getattr(self, pname)
  155. self_dict.setdefault(pname, self_data)
  156. another_dict.setdefault(pname, "")
  157. # Only in the other object.
  158. else:
  159. another_data = getattr(another, pname)
  160. another_dict.setdefault(pname, another_data)
  161. self_dict.setdefault(pname, "")
  162. return self_dict, another_dict
  163. def __eq__(self, another):
  164. """
  165. Overload euqal operator function.
  166. """
  167. self_dict, another_dict = self.compare(another)
  168. if (not self_dict) and (not another_dict):
  169. return True
  170. else:
  171. return False
  172. def __ne__(self, another):
  173. """
  174. Overload not equal operator function.
  175. """
  176. if self == another:
  177. return False
  178. else:
  179. return True
  180. def tofile(self, filename=None):
  181. "Create INCAR file."
  182. content = '# Created by VASPy\n'
  183. for pname in self.pnames:
  184. if not hasattr(self, pname):
  185. raise ValueError('Unknown parameter: %s' % pname)
  186. data = str(getattr(self, pname))
  187. content += '%s = %s\n' % (pname, data)
  188. # Write to file.
  189. if filename is None:
  190. filename = self.filename
  191. with open(filename, 'w') as f:
  192. f.write(content)
  193. return