vasputils 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. data/.document +5 -0
  2. data/Gemfile +18 -0
  3. data/LICENSE.txt +20 -0
  4. data/README.rdoc +19 -0
  5. data/Rakefile +54 -0
  6. data/VERSION +1 -0
  7. data/bin/addVolumeToten.rb +19 -0
  8. data/bin/latticeconstants +14 -0
  9. data/bin/lsvaspdir +60 -0
  10. data/bin/lsvaspseries +95 -0
  11. data/bin/repeatvasp +47 -0
  12. data/bin/symposcar +154 -0
  13. data/lib/vasputils/calcinspector.rb +24 -0
  14. data/lib/vasputils/calcrepeater.rb +27 -0
  15. data/lib/vasputils/calcseries.rb +98 -0
  16. data/lib/vasputils/incar.rb +55 -0
  17. data/lib/vasputils/kpoints.rb +41 -0
  18. data/lib/vasputils/outcar.rb +59 -0
  19. data/lib/vasputils/poscar.rb +168 -0
  20. data/lib/vasputils/potcar.rb +18 -0
  21. data/lib/vasputils/vaspdir.rb +278 -0
  22. data/lib/vasputils.rb +0 -0
  23. data/test/calcseries/dup_finished/try00/CONTCAR +17 -0
  24. data/test/calcseries/dup_finished/try00/INCAR +28 -0
  25. data/test/calcseries/dup_finished/try00/KPOINTS +6 -0
  26. data/test/calcseries/dup_finished/try00/OUTCAR +28 -0
  27. data/test/calcseries/dup_finished/try00/POSCAR +12 -0
  28. data/test/calcseries/dup_finished/try00/POTCAR +2 -0
  29. data/test/calcseries/dup_finished/try00/lock +0 -0
  30. data/test/calcseries/dup_finished/try01/CONTCAR +17 -0
  31. data/test/calcseries/dup_finished/try01/INCAR +28 -0
  32. data/test/calcseries/dup_finished/try01/KPOINTS +6 -0
  33. data/test/calcseries/dup_finished/try01/OUTCAR +28 -0
  34. data/test/calcseries/dup_finished/try01/POSCAR +12 -0
  35. data/test/calcseries/dup_finished/try01/POTCAR +2 -0
  36. data/test/calcseries/dup_finished/try01/lock +0 -0
  37. data/test/calcseries/normal_finished/try00/CONTCAR +17 -0
  38. data/test/calcseries/normal_finished/try00/INCAR +28 -0
  39. data/test/calcseries/normal_finished/try00/KPOINTS +6 -0
  40. data/test/calcseries/normal_finished/try00/OUTCAR +40 -0
  41. data/test/calcseries/normal_finished/try00/POSCAR +12 -0
  42. data/test/calcseries/normal_finished/try00/POTCAR +2 -0
  43. data/test/calcseries/normal_finished/try00/lock +0 -0
  44. data/test/calcseries/normal_finished/try01/CONTCAR +17 -0
  45. data/test/calcseries/normal_finished/try01/INCAR +28 -0
  46. data/test/calcseries/normal_finished/try01/KPOINTS +6 -0
  47. data/test/calcseries/normal_finished/try01/OUTCAR +33 -0
  48. data/test/calcseries/normal_finished/try01/POSCAR +12 -0
  49. data/test/calcseries/normal_finished/try01/POTCAR +2 -0
  50. data/test/calcseries/normal_finished/try01/lock +0 -0
  51. data/test/calcseries/not_finished/try00/CONTCAR +17 -0
  52. data/test/calcseries/not_finished/try00/INCAR +28 -0
  53. data/test/calcseries/not_finished/try00/KPOINTS +6 -0
  54. data/test/calcseries/not_finished/try00/OUTCAR +38 -0
  55. data/test/calcseries/not_finished/try00/POSCAR +12 -0
  56. data/test/calcseries/not_finished/try00/POTCAR +2 -0
  57. data/test/calcseries/not_finished/try00/lock +0 -0
  58. data/test/helper.rb +17 -0
  59. data/test/incar/INCAR.00 +35 -0
  60. data/test/incar/INCAR.01 +28 -0
  61. data/test/kpoints/g123-456 +6 -0
  62. data/test/kpoints/m123-456 +6 -0
  63. data/test/outcar/01-03-INT.OUTCAR +619 -0
  64. data/test/outcar/01-13-FIN.OUTCAR +1436 -0
  65. data/test/outcar/02-05-FIN.OUTCAR +2025 -0
  66. data/test/outcar/03-05-FIN.OUTCAR +2602 -0
  67. data/test/outcar/10-01-FIN.OUTCAR +437 -0
  68. data/test/poscar/NOT_POSCAR +0 -0
  69. data/test/poscar/POSCAR.00 +10 -0
  70. data/test/poscar/POSCAR.01 +12 -0
  71. data/test/poscarparser/POSCAR.00 +10 -0
  72. data/test/poscarparser/POSCAR.01 +12 -0
  73. data/test/potcar/POTCAR +5279 -0
  74. data/test/potcar/POTCAR.allElement +165 -0
  75. data/test/potcar/POTCAR.dummy +3 -0
  76. data/test/repeatVasp/Iter2-Nsw2.00/INCAR +35 -0
  77. data/test/repeatVasp/Iter2-Nsw2.00/KPOINTS +6 -0
  78. data/test/repeatVasp/Iter2-Nsw2.00/POSCAR +12 -0
  79. data/test/repeatVasp/Iter2-Nsw2.00/POTCAR +3151 -0
  80. data/test/repeatVasp/test.sh +3 -0
  81. data/test/test_calcinspector.rb +53 -0
  82. data/test/test_calcrepeater.rb +69 -0
  83. data/test/test_calcseries.rb +77 -0
  84. data/test/test_incar.rb +126 -0
  85. data/test/test_kpoints.rb +110 -0
  86. data/test/test_outcar.rb +162 -0
  87. data/test/test_poscar.rb +209 -0
  88. data/test/test_potcar.rb +65 -0
  89. data/test/test_vaspdir.rb +253 -0
  90. data/test/vaspdir/IBRION-1-NSW000-OUTCAR-Iter1/CONTCAR +17 -0
  91. data/test/vaspdir/IBRION-1-NSW000-OUTCAR-Iter1/INCAR +27 -0
  92. data/test/vaspdir/IBRION-1-NSW000-OUTCAR-Iter1/KPOINTS +6 -0
  93. data/test/vaspdir/IBRION-1-NSW000-OUTCAR-Iter1/OUTCAR +1436 -0
  94. data/test/vaspdir/IBRION-1-NSW000-OUTCAR-Iter1/POSCAR +12 -0
  95. data/test/vaspdir/IBRION-1-NSW000-OUTCAR-Iter1/POTCAR +3151 -0
  96. data/test/vaspdir/IBRION-1-NSW000-OUTCAR-Iter1/lock +0 -0
  97. data/test/vaspdir/ISIF2-NSW000-OUTCAR-Iter1/CONTCAR +17 -0
  98. data/test/vaspdir/ISIF2-NSW000-OUTCAR-Iter1/INCAR +28 -0
  99. data/test/vaspdir/ISIF2-NSW000-OUTCAR-Iter1/KPOINTS +6 -0
  100. data/test/vaspdir/ISIF2-NSW000-OUTCAR-Iter1/OUTCAR +1436 -0
  101. data/test/vaspdir/ISIF2-NSW000-OUTCAR-Iter1/POSCAR +12 -0
  102. data/test/vaspdir/ISIF2-NSW000-OUTCAR-Iter1/POTCAR +3151 -0
  103. data/test/vaspdir/ISIF2-NSW000-OUTCAR-Iter1/lock +0 -0
  104. data/test/vaspdir/ISIF2-NSW001-OUTCAR-Iter1/CONTCAR +17 -0
  105. data/test/vaspdir/ISIF2-NSW001-OUTCAR-Iter1/INCAR +28 -0
  106. data/test/vaspdir/ISIF2-NSW001-OUTCAR-Iter1/KPOINTS +6 -0
  107. data/test/vaspdir/ISIF2-NSW001-OUTCAR-Iter1/OUTCAR +1436 -0
  108. data/test/vaspdir/ISIF2-NSW001-OUTCAR-Iter1/POSCAR +12 -0
  109. data/test/vaspdir/ISIF2-NSW001-OUTCAR-Iter1/POTCAR +3151 -0
  110. data/test/vaspdir/ISIF2-NSW001-OUTCAR-Iter1/lock +0 -0
  111. data/test/vaspdir/ISIF2-NSW100-OUTCAR-Iter1/CONTCAR +17 -0
  112. data/test/vaspdir/ISIF2-NSW100-OUTCAR-Iter1/INCAR +28 -0
  113. data/test/vaspdir/ISIF2-NSW100-OUTCAR-Iter1/KPOINTS +6 -0
  114. data/test/vaspdir/ISIF2-NSW100-OUTCAR-Iter1/OUTCAR +1436 -0
  115. data/test/vaspdir/ISIF2-NSW100-OUTCAR-Iter1/POSCAR +12 -0
  116. data/test/vaspdir/ISIF2-NSW100-OUTCAR-Iter1/POTCAR +3151 -0
  117. data/test/vaspdir/ISIF2-NSW100-OUTCAR-Iter1/lock +0 -0
  118. data/test/vaspdir/ISIF2-NSW100-OUTCAR-Iter3/CONTCAR +17 -0
  119. data/test/vaspdir/ISIF2-NSW100-OUTCAR-Iter3/INCAR +28 -0
  120. data/test/vaspdir/ISIF2-NSW100-OUTCAR-Iter3/KPOINTS +6 -0
  121. data/test/vaspdir/ISIF2-NSW100-OUTCAR-Iter3/OUTCAR +2602 -0
  122. data/test/vaspdir/ISIF2-NSW100-OUTCAR-Iter3/POSCAR +12 -0
  123. data/test/vaspdir/ISIF2-NSW100-OUTCAR-Iter3/POTCAR +3151 -0
  124. data/test/vaspdir/ISIF2-NSW100-OUTCAR-Iter3/lock +0 -0
  125. data/test/vaspdir/ISIF3-NSW000-OUTCAR-Iter1/CONTCAR +17 -0
  126. data/test/vaspdir/ISIF3-NSW000-OUTCAR-Iter1/INCAR +28 -0
  127. data/test/vaspdir/ISIF3-NSW000-OUTCAR-Iter1/KPOINTS +6 -0
  128. data/test/vaspdir/ISIF3-NSW000-OUTCAR-Iter1/OUTCAR +1436 -0
  129. data/test/vaspdir/ISIF3-NSW000-OUTCAR-Iter1/POSCAR +12 -0
  130. data/test/vaspdir/ISIF3-NSW000-OUTCAR-Iter1/POTCAR +3151 -0
  131. data/test/vaspdir/ISIF3-NSW000-OUTCAR-Iter1/lock +0 -0
  132. data/test/vaspdir/ISIF3-NSW001-OUTCAR-Iter1/CONTCAR +17 -0
  133. data/test/vaspdir/ISIF3-NSW001-OUTCAR-Iter1/INCAR +28 -0
  134. data/test/vaspdir/ISIF3-NSW001-OUTCAR-Iter1/KPOINTS +6 -0
  135. data/test/vaspdir/ISIF3-NSW001-OUTCAR-Iter1/OUTCAR +1436 -0
  136. data/test/vaspdir/ISIF3-NSW001-OUTCAR-Iter1/POSCAR +12 -0
  137. data/test/vaspdir/ISIF3-NSW001-OUTCAR-Iter1/POTCAR +3151 -0
  138. data/test/vaspdir/ISIF3-NSW001-OUTCAR-Iter1/lock +0 -0
  139. data/test/vaspdir/ISIF3-NSW002-OUTCAR-Iter2/CONTCAR +17 -0
  140. data/test/vaspdir/ISIF3-NSW002-OUTCAR-Iter2/INCAR +28 -0
  141. data/test/vaspdir/ISIF3-NSW002-OUTCAR-Iter2/KPOINTS +6 -0
  142. data/test/vaspdir/ISIF3-NSW002-OUTCAR-Iter2/OUTCAR +2025 -0
  143. data/test/vaspdir/ISIF3-NSW002-OUTCAR-Iter2/POSCAR +12 -0
  144. data/test/vaspdir/ISIF3-NSW002-OUTCAR-Iter2/POTCAR +3151 -0
  145. data/test/vaspdir/ISIF3-NSW002-OUTCAR-Iter2/lock +0 -0
  146. data/test/vaspdir/ISIF3-NSW100-OUTCAR-Iter1-INT/CONTCAR +0 -0
  147. data/test/vaspdir/ISIF3-NSW100-OUTCAR-Iter1-INT/INCAR +28 -0
  148. data/test/vaspdir/ISIF3-NSW100-OUTCAR-Iter1-INT/KPOINTS +6 -0
  149. data/test/vaspdir/ISIF3-NSW100-OUTCAR-Iter1-INT/OUTCAR +619 -0
  150. data/test/vaspdir/ISIF3-NSW100-OUTCAR-Iter1-INT/POSCAR +12 -0
  151. data/test/vaspdir/ISIF3-NSW100-OUTCAR-Iter1-INT/POTCAR +3151 -0
  152. data/test/vaspdir/ISIF3-NSW100-OUTCAR-Iter1-INT/lock +0 -0
  153. data/test/vaspdir/ISIF3-NSW100-OUTCAR-Iter3/CONTCAR +17 -0
  154. data/test/vaspdir/ISIF3-NSW100-OUTCAR-Iter3/INCAR +28 -0
  155. data/test/vaspdir/ISIF3-NSW100-OUTCAR-Iter3/KPOINTS +6 -0
  156. data/test/vaspdir/ISIF3-NSW100-OUTCAR-Iter3/OUTCAR +2602 -0
  157. data/test/vaspdir/ISIF3-NSW100-OUTCAR-Iter3/POSCAR +12 -0
  158. data/test/vaspdir/ISIF3-NSW100-OUTCAR-Iter3/POTCAR +3151 -0
  159. data/test/vaspdir/ISIF3-NSW100-OUTCAR-Iter3/lock +0 -0
  160. data/test/vaspdir/PI/INCAR +28 -0
  161. data/test/vaspdir/PI/KPOINTS +5 -0
  162. data/test/vaspdir/PI/PI12345 +0 -0
  163. data/test/vaspdir/PI/POSCAR +57 -0
  164. data/test/vaspdir/PI/POTCAR +698 -0
  165. data/test/vaspdir/lack-INCAR/KPOINTS +5 -0
  166. data/test/vaspdir/lack-INCAR/POSCAR +57 -0
  167. data/test/vaspdir/lack-INCAR/POTCAR +698 -0
  168. data/test/vaspdir/lack-KPOINTS/INCAR +28 -0
  169. data/test/vaspdir/lack-KPOINTS/POSCAR +57 -0
  170. data/test/vaspdir/lack-KPOINTS/POTCAR +698 -0
  171. data/test/vaspdir/lack-POSCAR/INCAR +28 -0
  172. data/test/vaspdir/lack-POSCAR/KPOINTS +5 -0
  173. data/test/vaspdir/lack-POSCAR/POTCAR +698 -0
  174. data/test/vaspdir/lack-POTCAR/INCAR +28 -0
  175. data/test/vaspdir/lack-POTCAR/KPOINTS +5 -0
  176. data/test/vaspdir/lack-POTCAR/POSCAR +57 -0
  177. data/test/vaspdir/lock/INCAR +28 -0
  178. data/test/vaspdir/lock/KPOINTS +5 -0
  179. data/test/vaspdir/lock/POSCAR +57 -0
  180. data/test/vaspdir/lock/POTCAR +698 -0
  181. data/test/vaspdir/lock/lock +0 -0
  182. data/test/vaspdir/lock-PI/INCAR +28 -0
  183. data/test/vaspdir/lock-PI/KPOINTS +5 -0
  184. data/test/vaspdir/lock-PI/PI12345 +0 -0
  185. data/test/vaspdir/lock-PI/POSCAR +57 -0
  186. data/test/vaspdir/lock-PI/POTCAR +698 -0
  187. data/test/vaspdir/lock-PI/lock +0 -0
  188. data/test/vaspdir/next-try00/CONTCAR +17 -0
  189. data/test/vaspdir/next-try00/INCAR +28 -0
  190. data/test/vaspdir/next-try00/KPOINTS +6 -0
  191. data/test/vaspdir/next-try00/OUTCAR +2025 -0
  192. data/test/vaspdir/next-try00/POSCAR +12 -0
  193. data/test/vaspdir/next-try00/POTCAR +3151 -0
  194. data/test/vaspdir/next-try00/lock +0 -0
  195. data/test/vaspdir/not-yet-ISIF2/INCAR +28 -0
  196. data/test/vaspdir/not-yet-ISIF2/KPOINTS +5 -0
  197. data/test/vaspdir/not-yet-ISIF2/PI17489 +2 -0
  198. data/test/vaspdir/not-yet-ISIF2/PI17736 +2 -0
  199. data/test/vaspdir/not-yet-ISIF2/PI1858 +2 -0
  200. data/test/vaspdir/not-yet-ISIF2/PI1866 +2 -0
  201. data/test/vaspdir/not-yet-ISIF2/PI2059 +2 -0
  202. data/test/vaspdir/not-yet-ISIF2/POSCAR +57 -0
  203. data/test/vaspdir/not-yet-ISIF2/POTCAR +698 -0
  204. data/test/vaspdir/not-yet-ISIF3/INCAR +28 -0
  205. data/test/vaspdir/not-yet-ISIF3/KPOINTS +5 -0
  206. data/test/vaspdir/not-yet-ISIF3/POSCAR +57 -0
  207. data/test/vaspdir/not-yet-ISIF3/POTCAR +698 -0
  208. data/vasputils.gemspec +272 -0
  209. metadata +409 -0
@@ -0,0 +1,55 @@
1
+ #! /usr/bin/env ruby
2
+ # coding: utf-8
3
+
4
+ # see http://cms.mpi.univie.ac.at/vasp/vasp/INCAR_File.html
5
+ #
6
+ # INCAR のフォーマット
7
+ # - 基本 1行 1項目。
8
+ # - = 区切りで左辺の項目名に対して右辺の値になる。
9
+ # - 半角# のあと、コメント
10
+ #
11
+ # TODO, Future feature
12
+ # INCAR のフォーマット
13
+ # - 右辺のあとの文字列は、セミコロンでなければ無視される。
14
+ # - ; 区切りで1行に複数の項目を設定できる。
15
+ # - \ で次の行に設定を続けることができる。
16
+
17
+ # Class to utilize INCAR file of VASP.
18
+ # まず、自分で使う範囲だけ作る。
19
+ # あとで余力があれば精密化する。
20
+ module Incar
21
+ #
22
+ #def initialize()
23
+ #end
24
+
25
+ # 与えられた IO を読み込み、INCAR として解析したハッシュを返す。
26
+ def self.parse(io)
27
+ results = {}
28
+ io.each_line do |line|
29
+ line.sub!(/\#.*/, "") # コメント文字以降を削除
30
+ next unless /=/ =~ line
31
+ if /(.*)=(.*)/ =~ line
32
+ key = $1.strip
33
+ val = $2.strip
34
+ val.sub!(/\s.*$/, "")
35
+ next if key.empty?
36
+ results[key] = val
37
+ end
38
+ end
39
+ return results
40
+ end
41
+
42
+ # 与えられた名前のファイルを INCAR として解析したハッシュを返す。
43
+ def self.load_file(file)
44
+ io = File.open(file, "r")
45
+ return self.parse(io)
46
+ end
47
+
48
+ ## 与えられたデータ対(ハッシュ)を io に書き出す。
49
+ ## io が nil の場合は INCAR 形式文字列を返す。
50
+ ## (改行文字を埋め込んでおり、配列化していない)
51
+ #def dump(pairs, io = nil)
52
+ #end
53
+
54
+ end
55
+
@@ -0,0 +1,41 @@
1
+ #! /usr/bin/env ruby
2
+ # coding: utf-8
3
+
4
+ # Module dearing with KPOINTS.
5
+ module Kpoints
6
+ def self.parse(io)
7
+ results = {}
8
+ results[:comment] = io.readline.chomp
9
+
10
+ raise "Not automatic generating KPOINTS! 2nd line must be 0." unless io.readline == "0\n"
11
+
12
+ line = io.readline
13
+ case line
14
+ when /^m/i; then; results[:type] = :monkhorst
15
+ when /^g/i; then; results[:type] = :gamma_center
16
+ else
17
+ raise "Kpoints module can deal with only monkhorst and gamma-center."
18
+ end
19
+
20
+ #pp io.readline.strip.split(/\s+/).map{|i| i.to_i}
21
+ results[:mesh] = io.readline.strip.split(/\s+/).map{|i| i.to_i}
22
+ #pp io.readline.strip.split(/\s+/).map{|i| i.to_f}
23
+ results[:shift] = io.readline.strip.split(/\s+/).map{|i| i.to_f}
24
+
25
+ return results
26
+ end
27
+
28
+ #
29
+ def self.load_file(file)
30
+ self.parse(File.open(file, "r"))
31
+ end
32
+
33
+ def self.dump(data, io)
34
+ io.puts "Automatic mesh"
35
+ io.puts "0"
36
+ io.puts data[:type].to_s.capitalize
37
+ io.puts data[:mesh].join(" ")
38
+ io.puts data[:shift].join(" ")
39
+ end
40
+ end
41
+
@@ -0,0 +1,59 @@
1
+ # OUTCAR をパースする。
2
+ # 精確には行わず、必要な情報だけをピックアップする感じ。
3
+ #
4
+ # あまり頑張らないことにした理由は以下。
5
+ # OUTCAR がどう出力されるのかがよくわからない。
6
+ # 本来は vasp のソースを見て決めるべきだろう。
7
+ # やるとすればかなり大掛かりなプロジェクトになるが、そのわりには旨味が少ない。
8
+ # grep でなんとかなるし。
9
+ #
10
+ # 基本的に終了した計算から情報を取り出すには vasprun.xml を読む。
11
+ # OUTCAR は終了する前も含めてなんか簡単に見るために使う、という位置付けで。
12
+
13
+ module Outcar
14
+ #toten は全 electronic and ionic steps のを flat に並べただけのもの。
15
+ #必要なら構造化するが、現状その予定はない。
16
+ #attr_reader :name
17
+ #attr_reader :ionic_steps, :electronic_steps, :totens, :volumes, :elapsed_time
18
+
19
+ def self.load_file(file)
20
+ results = {}
21
+ results[:name] = file
22
+ results[:irreducible_kpoints] = nil
23
+ results[:electronic_steps ] = 0
24
+ results[:ionic_steps ] = 0
25
+ results[:totens ] = []
26
+ results[:volumes ] = []
27
+ results[:elapsed_time ] = nil
28
+ results[:normal_ended ] = false
29
+
30
+ lines = File.readlines(file)
31
+ lines.each do |line|
32
+ if /Found\s+(\d+)\s+irreducible k-points/i =~ line
33
+ results[:irreducible_kpoints] = $1.to_i
34
+ end
35
+
36
+ if /^-* Iteration\s+(\d+)/ =~ line
37
+ results[:ionic_steps ] = $1.to_i
38
+ results[:electronic_steps] += 1
39
+ end
40
+
41
+ #if /free\s+energy\s+TOTEN\s+=\s(.*)\s+eV/ =~ line
42
+ if /TOTEN\s+=\s(.*)\s+eV/ =~ line
43
+ results[:totens] << $1.to_f
44
+ end
45
+
46
+ if /volume of cell :\s+(\d+\.\d+)$/ =~ line
47
+ results[:volumes] << $1.to_f
48
+ end
49
+
50
+ if (/Elapsed time \(sec\):\s+(\d+\.\d+)/ =~ line)
51
+ results[:elapsed_time] = $1.to_f
52
+ end
53
+ end
54
+
55
+ results[:normal_ended] = true if (/Voluntary context switches:/ =~ lines[-1])
56
+
57
+ results
58
+ end
59
+ end
@@ -0,0 +1,168 @@
1
+ #! /usr/bin/ruby
2
+
3
+ require "rubygems"
4
+ gem "crystalcell"
5
+ require "crystalcell/cell.rb"
6
+
7
+ # Class to manage POSCAR format of VASP.
8
+ #
9
+ # parse と dump のどちらかだけでなく、両方を統括して扱うクラス。
10
+ #
11
+ # MEMO
12
+ # POSCAR 自身は元素の情報を持っていない。
13
+ # POSCAR が native に持っている情報だけを取り扱う。
14
+ # Poscar では個々の原子が何の element であるかという情報を取り扱わない。
15
+ # 1番目の種類の原子種が何かだけを扱う。
16
+ # こうしておくことで POTCAR がない環境でも POSCAR を扱うことができる。
17
+ #
18
+ # VASP 5 系を使うようになれば事情が変わるだろう。
19
+ class Poscar
20
+
21
+ class ElementMismatchError < Exception; end
22
+ class ParseError < Exception; end
23
+
24
+ # io を読み込んで Cell クラスインスタンスを返す。
25
+ # 構文解析できなければ例外 Poscar::ParseError を投げる。
26
+ def self.parse(io)
27
+ # analyze POSCAR.
28
+
29
+ begin
30
+ #line 1: comment (string)
31
+ comment = io.readline.chomp
32
+
33
+ #line 2: universal scaling factor (float)
34
+ scale = io.readline.to_f
35
+ raise "Poscar.load_file cannot use negative scaling factor.\n" if scale < 0
36
+
37
+ #line 3-5: axes (3x3 Array of float)
38
+ axes = []
39
+ 3.times do |i| #each axis of a, b, c.
40
+ vec = io.readline.strip.split(/\s+/) #in x,y,z directions
41
+ axes << vec.collect! { |i| i.to_f * scale } #multiply scaling factor
42
+ end
43
+
44
+ #line 6: numbers of elements. e.g.,[1, 1, 2]
45
+ nums_elements = io.readline.strip.split( /\s+/ ).map{|i| i.to_i}
46
+
47
+ #line 7-(8): 'Selective dynamics' or not (bool)
48
+ line = io.readline
49
+ if line =~ /^\s*s/i
50
+ selective_dynamics = true
51
+ line = io.readline # when this situation, reading one more line is nessesarry
52
+ end
53
+
54
+ if (line =~ /^\s*d/i ) # allow only 'Direct' now
55
+ direct = true
56
+ else
57
+ raise "Not 'direct' indication."
58
+ end
59
+
60
+ #line 9(8): position
61
+ #e.g., positions_of_elements
62
+ #e.g., movable_flags_of_elements
63
+
64
+ atoms = []
65
+ nums_elements.size.times do |elem_index|
66
+ nums_elements[elem_index].times do |index|
67
+ items = io.readline.strip.split( /\s+/ )
68
+ pos = items[0..2].map {|coord| coord.to_f}
69
+ #pp pos
70
+
71
+ mov_flags = []
72
+ if items.size >= 6 then
73
+ items[3..5].each do |i|
74
+ ( i =~ /^t/i ) ? mov_flags << true : mov_flags << false
75
+ end
76
+ atoms << Atom.new(elem_index, pos, mov_flags)
77
+ else
78
+ atoms << Atom.new(elem_index, pos)
79
+ end
80
+ end
81
+ end
82
+ rescue EOFError
83
+ raise ParseError, "end of file reached"
84
+ end
85
+
86
+ cell = Cell.new(axes, atoms )
87
+ cell.comment = comment
88
+ cell
89
+ end
90
+
91
+ # file で与えられた名前のファイルを読み込んで Cell クラスインスタンスを返す。
92
+ # 構文解析できなければ例外 Poscar::ParseError を投げる。
93
+ def self.load_file(file)
94
+ io = File.open(file, "r")
95
+ self.parse(io)
96
+ end
97
+
98
+ # POSCAR 形式で書き出す。
99
+ # cell は Cell クラスインスタンスと同等のメソッドを持つもの。
100
+ # elems は書き出す元素の順番。
101
+ # elems が cell の持つ元素リストとマッチしなければ
102
+ # 例外 Poscar::ElementMismatchError を投げる。
103
+ # io は書き出すファイルハンドル。
104
+ def self.dump(cell, elems, io)
105
+ unless (Mapping::map?(cell.elements.uniq, elems){ |i, j| i == j })
106
+ raise ElementMismatchError,
107
+ "elems [#{elems.join(",")}] mismatches to cell.elements [#{cell.elements.join(",")}."
108
+ end
109
+
110
+ io.puts cell.comment
111
+ io.puts "1.0" #scale
112
+ 3.times do |i|
113
+ io.printf( " % 18.15f % 18.15f % 18.15f\n", cell.axes[i][0], cell.axes[i][1], cell.axes[i][2]
114
+ )
115
+ end
116
+
117
+ # collect information
118
+ elem_list = Hash.new
119
+ elems.each do |elem|
120
+ elem_list[ elem ] = cell.atoms.select{ |atom| atom.element == elem }
121
+ end
122
+ io.puts(elems.map { |elem| elem_list[elem].size }.join(" "))
123
+
124
+ # Selective dynamics
125
+ # どれか1つでも getMovableFlag が真であれば Selective dynamics をオンにする
126
+ selective_dynamics = false
127
+ cell.atoms.each do |atom|
128
+ if atom.movable_flags
129
+ selective_dynamics = true
130
+ io.puts "Selective dynamics"
131
+ break
132
+ end
133
+ end
134
+
135
+ elems.each do |elem|
136
+ elem_list[ elem ].each do |atom|
137
+ if atom.movable_flags
138
+ selective_dynamics = true
139
+ break
140
+ end
141
+ end
142
+ break if selective_dynamics
143
+ end
144
+
145
+ io.puts "Direct"
146
+
147
+ # positions of atoms
148
+ elems.each do |elem|
149
+ elem_list[ elem ].each do |atom|
150
+ tmp = sprintf(
151
+ " % 18.15f % 18.15f % 18.15f",
152
+ * atom.position )
153
+ if selective_dynamics
154
+ if atom.movable_flags == nil
155
+ tmp += " T T T"
156
+ else
157
+ atom.movable_flags.each do |mov|
158
+ ( mov == true ) ? tmp += " T" : tmp += " F"
159
+ end
160
+ end
161
+ end
162
+ io.puts tmp
163
+ end
164
+ end
165
+ end
166
+
167
+ end
168
+
@@ -0,0 +1,18 @@
1
+ #
2
+ # Class for dealing with POTCAR.
3
+ #
4
+ module Potcar
5
+ def self.load_file(file)
6
+ results = {}
7
+ results[:name] = file
8
+
9
+ elements = Array.new
10
+ File.open( file, "r" ).each do |line|
11
+ if line =~ /VRHFIN\s*=\s*([A-Za-z]*)/
12
+ elements << $1
13
+ end
14
+ end
15
+ results[:elements] = elements
16
+ results
17
+ end
18
+ end
@@ -0,0 +1,278 @@
1
+ #! /usr/bin/env ruby
2
+ # coding: utf-8
3
+
4
+ require "vasputils/incar.rb"
5
+ require "vasputils/outcar.rb"
6
+ require "vasputils/poscar.rb"
7
+ require "vasputils/kpoints.rb"
8
+ require "fileutils"
9
+ require "pp"
10
+ require "date"
11
+
12
+
13
+ # vasp 実行ディレクトリ(入力・出力ファイルを含む)を扱うクラス
14
+ #
15
+ # MEMO
16
+ # interrupted? みたいなメソッドは作れない。
17
+ # 実行が開始したあと、その計算の状態が中断されているのか、
18
+ # 単に実行中でファイルが書き込まれている途中なのか、
19
+ # プログラムを実行しているプロセス自身以外は、外部からは判別がつかない。
20
+ #
21
+ # ルール
22
+ # try00 形式の postfix がついていることを前提とする。
23
+ # 00 の部分には CONTCAR を POSCAR にする手続きで連続して行う計算の番号を示す。
24
+ #
25
+ class VaspDir
26
+
27
+ class InitializeError < Exception; end
28
+ class ConvergedError < Exception; end
29
+ class NotEndedError < Exception; end
30
+ class LockedError < Exception; end
31
+ class PostfixMismatchError < Exception; end
32
+
33
+
34
+ LOCK_FILE = "lock"
35
+ POSTFIX = /try(\d+)$/
36
+
37
+ YET = 0# - 未計算。
38
+ STARTED = 1# - 開始した。
39
+ INTERRUPTED = 2# - 中断された。
40
+ CONTINUED = 3# - 終了し、次の計算を生成した。
41
+ COMPLETED = 4# - 終了し、収束した。
42
+
43
+ attr_reader :mode
44
+ #attr_reader :dir
45
+
46
+ #INCAR 解析とかして、モードを調べる。
47
+ #- 格子定数の構造最適化モード(ISIF = 3)
48
+ #- 格子定数を固定した構造最適化モード(ISIF = 2)
49
+ ##- k 点探索モードは無理だろう。
50
+ def initialize(dir_name)
51
+ @dir = dir_name
52
+
53
+ %w(INCAR KPOINTS POSCAR POTCAR).each do |file|
54
+ infile = "#{@dir}/#{file}"
55
+ raise InitializeError, infile unless FileTest.exist? infile
56
+ end
57
+
58
+ @incar = Incar.load_file("#{@dir}/INCAR")
59
+ case @incar["IBRION"]
60
+ when "-1"
61
+ @mode = :single_point
62
+ #when "1"
63
+ # @mode = :molecular_dynamics
64
+ when "2"
65
+ if (@incar["ISIF"] == "2")
66
+ @mode = :geom_opt_atoms
67
+ elsif (@incar["ISIF"] == "3")
68
+ @mode = :geom_opt_lattice
69
+ else
70
+ @mode = :geom_opt
71
+ end
72
+ else
73
+ @mode = nil
74
+ end
75
+ end
76
+
77
+ # ディレクトリ名を返す。
78
+ def name
79
+ @dir
80
+ end
81
+
82
+ # 計算が過去に始まっていれば true を返す。
83
+ # 終わっているかは判定しない。
84
+ # 具体的には lock ファイルが存在すれば true を返す。
85
+ #
86
+ # MEMO
87
+ # (mpi 経由で?)vasp を実行すると PI12345 とかいうファイルができるが、
88
+ # これはたぶん起動してから若干のタイムラグが生じる。
89
+ # このタイムラグ中に別のプロセスが同時に計算したらマズい。
90
+ def started?
91
+ return File.exist? lock_file
92
+ end
93
+
94
+ # 正常に終了していれば true を返す。
95
+ # 実行する前や実行中、OUTCAR が完遂していなければ false。
96
+ #
97
+ # MEMO
98
+ # PI12345 ファイルは実行中のみ存在し、終了後 vasp (mpi?) に自動的に削除される。
99
+ def normal_ended?
100
+ begin
101
+ return Outcar.load_file("#{@dir}/OUTCAR")[:normal_ended]
102
+ rescue Errno::ENOENT
103
+ return false
104
+ end
105
+ end
106
+
107
+ # normal_ended? が false なら false。
108
+ # normal_ended? が true のうち、
109
+ # 結果を使って次に計算すべきなら true を、そうでなければ false を返す。
110
+ #
111
+ # 計算すべき、の条件はモードによって異なる。
112
+ # NSW = 0 もしくは NSW = 1 のとき、必ず false。
113
+ # - :single_point モードならば、常に false。
114
+ # - :geom_opt_lattice モードならば、ionic step が 2 以上なら true。
115
+ # - :geom_opt_atoms モードならば、ionic step が NSW と同じなら true。
116
+ #
117
+ def to_be_continued?
118
+ begin
119
+ outcar = Outcar.load_file("#{@dir}/OUTCAR")
120
+ rescue Errno::ENOENT
121
+ return false
122
+ end
123
+ ionic_steps = outcar[:ionic_steps]
124
+ return false unless outcar[:normal_ended]
125
+ return false if @incar["NSW"].to_i <= 1
126
+ if @mode == :geom_opt_lattice
127
+ return ionic_steps != 1
128
+ elsif @mode == :geom_opt_atoms
129
+ return ionic_steps == @incar["NSW"].to_i
130
+ else
131
+ return false
132
+ end
133
+ end
134
+
135
+ # vasp を投げる。
136
+ # 計算実行時に lock を生成する。
137
+ # もし既に lock が存在していれば、例外 VaspDirLockedError を
138
+ # 投げる。
139
+ # lock は作られっぱなしで、プログラムからは削除されない。
140
+ # 通常、一度計算したらもう二度と計算しないし。
141
+ #
142
+ # MEMO
143
+ # mpirun で投げる場合は
144
+ # machinefile を生成しないとどのホストで計算するか、安定しない。
145
+ # そのうち mpiexec from torque に対応するが、
146
+ # まずは mpirun で動くように作る。
147
+ def calculate
148
+ raise LockedError if started?
149
+
150
+ File.open(lock_file, "w") do |lock_io|
151
+ lock_io.puts "HOST: #{ENV["HOST"]}"
152
+ lock_io.puts "START: #{Time.now.to_s}"
153
+ lock_io.flush
154
+
155
+ num_cores = 4 if /^Se\d\d/ =~ ENV["HOST"]
156
+ num_cores = 4 if /^Ge\d\d/ =~ ENV["HOST"]
157
+ num_cores = 4 if /^Ga\d\d/ =~ ENV["HOST"]
158
+ num_cores = 4 if /^At$/ =~ ENV["HOST"]
159
+ num_cores = 2 if /^yggdrasil$/ =~ ENV["HOST"]
160
+
161
+ # machines を生成
162
+ File.open("#{@dir}/machines", "w") do |io|
163
+ io.puts "localhost:#{num_cores}"
164
+ end
165
+
166
+ command = "cd #{@dir};" +
167
+ "/usr/local/calc/mpich-1.2.7-ifc7/bin/mpirun " +
168
+ "-np #{num_cores} " +
169
+ "-machinefile machines " +
170
+ "/usr/local/calc/vasp/vasp4631mpi" +
171
+ "> stdout"
172
+
173
+ if $TEST
174
+ generated_files = [
175
+ "CHG",
176
+ "CHGCAR",
177
+ "CONTCAR",
178
+ "DOSCAR",
179
+ "EIGENVAL",
180
+ "IBZKPT",
181
+ "OSZICAR",
182
+ "OUTCAR",
183
+ "PCDAT",
184
+ "WAVECAR",
185
+ "XDATCAR",
186
+ "machines",
187
+ "vasprun.xml",
188
+ "lock",
189
+ ]
190
+ generated_files.map!{|i| "#{@dir}/#{i}"}
191
+ command = "touch #{generated_files.join(" ")}"
192
+ end
193
+
194
+ status = system command
195
+ if status
196
+ lock_io.puts "STATUS: normal ended."
197
+ else
198
+ lock_io.puts "STATUS: irregular ended, status #{$?}."
199
+ end
200
+ end
201
+ end
202
+
203
+ # 次の計算ディレクトリを作成し、
204
+ # その VaspDir クラスで self を置き換える。
205
+ # 計算が正常終了していなければ、例外 VaspDirNotEndedError を生じる。
206
+ # 次の計算ディレクトリが既に存在していれば例外 Errno::EEXIST が投げられる。
207
+ def next
208
+ raise NotEndedError unless normal_ended?
209
+ raise ConvergedError unless to_be_continued?
210
+ #postfix = /try(\d+)$/
211
+ POSTFIX =~ @dir
212
+ try_num = $1.to_i
213
+ next_dir = @dir.sub(POSTFIX, sprintf("try%02d", try_num + 1))
214
+ Dir.mkdir next_dir
215
+ FileUtils.cp( "#{@dir}/INCAR" , "#{next_dir}/INCAR")
216
+ FileUtils.cp( "#{@dir}/KPOINTS", "#{next_dir}/KPOINTS")
217
+ FileUtils.cp( "#{@dir}/POTCAR" , "#{next_dir}/POTCAR")
218
+ FileUtils.cp( "#{@dir}/CONTCAR", "#{next_dir}/POSCAR")
219
+ initialize(next_dir)
220
+ end
221
+
222
+ # Postprocess.
223
+ def teardown
224
+ # Do nothing.
225
+ end
226
+
227
+ # Return number of electronic steps.
228
+ def internal_steps
229
+ return outcar[:electronic_steps] if outcar
230
+ return 0
231
+ end
232
+
233
+ # Return number of ionic steps.
234
+ def external_steps
235
+ return outcar[:ionic_steps] if outcar
236
+ return 0
237
+ end
238
+
239
+ # Return elapsed time.
240
+ def elapsed_time
241
+ return outcar[:elapsed_time] if outcar
242
+ return 0.0
243
+ end
244
+
245
+ # 配下の OUTCAR を Outcar インスタンスにして返す。
246
+ # 存在しなければ例外 Errno::ENOENT を返す。
247
+ def outcar
248
+ Outcar.load_file("#{@dir}/OUTCAR")
249
+ end
250
+
251
+ # 配下の CONTCAR を Cell2 インスタンスにして返す。
252
+ # 存在しなければ例外 Errno::ENOENT を返す。
253
+ def contcar
254
+ Poscar.load_file("#{@dir}/CONTCAR")
255
+ end
256
+
257
+ # 配下の KPOINTS を読み込んだ結果をハッシュにして返す。
258
+ #
259
+ # 存在しなければ例外 Errno::ENOENT を返す筈だが、
260
+ # vasp dir の判定を incar でやっているので置こる筈がない。
261
+ def incar
262
+ Incar.load_file("#{@dir}/INCAR")
263
+ end
264
+
265
+ # 配下の KPOINTS を読み込んだ結果をハッシュにして返す。
266
+ def kpoints
267
+ Kpoints.load_file("#{@dir}/KPOINTS")
268
+ end
269
+
270
+ private
271
+
272
+ # Return lock file name.
273
+ def lock_file
274
+ return "#{@dir}/#{LOCK_FILE}"
275
+ end
276
+
277
+ end
278
+
data/lib/vasputils.rb ADDED
File without changes
@@ -0,0 +1,17 @@
1
+ Untitled (VASP)
2
+ 1.00000000000000
3
+ 3.6218218384059248 -0.0000000000000001 0.0000000000000000
4
+ -1.8109109192029544 3.1365897200407926 0.0000000000000000
5
+ 0.0000000000000000 0.0000000000000000 3.8586803850215405
6
+ 3 1
7
+ Selective dynamics
8
+ Direct
9
+ 0.0000000000000000 0.0000000000000000 0.5000000000000000 T T T
10
+ 0.3333333333333357 0.6666666666666642 0.0000000000000000 T T T
11
+ 0.6666666666666642 0.3333333333333357 0.0000000000000000 T T T
12
+ 0.0000000000000000 0.0000000000000000 0.0000000000000000 F F F
13
+
14
+ 0.00000000E+00 0.00000000E+00 0.00000000E+00
15
+ 0.00000000E+00 0.00000000E+00 0.00000000E+00
16
+ 0.00000000E+00 0.00000000E+00 0.00000000E+00
17
+ 0.00000000E+00 0.00000000E+00 0.00000000E+00
@@ -0,0 +1,28 @@
1
+ # SCF input for VASP
2
+
3
+ SYSTEM = Untitled (VASP)
4
+ PREC = High
5
+ IBRION = 2 #-1:atoms not moved, 1:quasi-Newton, 2:conjugate-gradient
6
+ NSW = 3 #maximum number of ionic steps
7
+ ISIF = 2
8
+ ENCUT = 400
9
+ NELM = 60 #maximum number of electronic steps
10
+ NELMIN = 2 #minimum number of electronic steps
11
+ EDIFF = 1.0e-05
12
+ EDIFFG = -0.02
13
+ VOSKOWN = 1
14
+ NBLOCK = 1
15
+ ISPIN = 1 #1:non spin polarized, 2:spin polarized
16
+ INIWAV = 1
17
+ ISTART = 1
18
+ ICHARG = 1
19
+ LWAVE = .TRUE.
20
+ LCHARG = .TRUE.
21
+ ISMEAR = 0
22
+ SIGMA = 0.1
23
+ IALGO = 38 #38:KosugiAlgorithm, 48:RMM-DIIS
24
+ #LREAL = .FALSE.
25
+ LREAL = Auto #fast & not accurate
26
+ NGX = 36
27
+ NGY = 36
28
+ NGZ = 42
@@ -0,0 +1,6 @@
1
+ Automatic mesh
2
+ 0
3
+ Monkhorst Pack
4
+ 5 5 5
5
+ 0. 0. 0.
6
+