vasputils 0.0.1 → 0.0.2

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 (42) hide show
  1. data/Gemfile +1 -1
  2. data/VERSION +1 -1
  3. data/bin/qsubvasp +30 -0
  4. data/lib/vasputils/vaspdir.rb +176 -218
  5. data/test/test_vaspdir.rb +59 -189
  6. data/test/vaspdir/finished/CONTCAR +17 -0
  7. data/test/vaspdir/finished/INCAR +27 -0
  8. data/test/vaspdir/finished/KPOINTS +6 -0
  9. data/test/vaspdir/finished/OUTCAR +1436 -0
  10. data/test/vaspdir/finished/POSCAR +12 -0
  11. data/test/vaspdir/finished/POTCAR +16 -0
  12. data/test/vaspdir/finished/lock +0 -0
  13. data/test/vaspdir/lack-INCAR/KPOINTS +5 -4
  14. data/test/vaspdir/lack-INCAR/POSCAR +11 -56
  15. data/test/vaspdir/lack-INCAR/POTCAR +13 -695
  16. data/test/vaspdir/lack-KPOINTS/INCAR +2 -3
  17. data/test/vaspdir/lack-KPOINTS/POSCAR +11 -56
  18. data/test/vaspdir/lack-KPOINTS/POTCAR +13 -695
  19. data/test/vaspdir/lack-POSCAR/INCAR +2 -3
  20. data/test/vaspdir/lack-POSCAR/KPOINTS +5 -4
  21. data/test/vaspdir/lack-POSCAR/POTCAR +13 -695
  22. data/test/vaspdir/lack-POTCAR/INCAR +2 -3
  23. data/test/vaspdir/lack-POTCAR/KPOINTS +5 -4
  24. data/test/vaspdir/lack-POTCAR/POSCAR +11 -56
  25. data/test/vaspdir/locked/INCAR +28 -0
  26. data/test/vaspdir/locked/KPOINTS +6 -0
  27. data/test/vaspdir/locked/POSCAR +12 -0
  28. data/test/vaspdir/locked/POTCAR +16 -0
  29. data/test/vaspdir/locked/lock +0 -0
  30. data/test/vaspdir/not-yet/INCAR +28 -0
  31. data/test/vaspdir/not-yet/KPOINTS +6 -0
  32. data/test/vaspdir/not-yet/POSCAR +12 -0
  33. data/test/vaspdir/not-yet/POTCAR +16 -0
  34. data/test/vaspdir/started/CONTCAR +17 -0
  35. data/test/vaspdir/started/INCAR +27 -0
  36. data/test/vaspdir/started/KPOINTS +6 -0
  37. data/test/vaspdir/started/OUTCAR +1028 -0
  38. data/test/vaspdir/started/POSCAR +12 -0
  39. data/test/vaspdir/started/POTCAR +16 -0
  40. data/test/vaspdir/started/lock +0 -0
  41. data/vasputils.gemspec +27 -3
  42. metadata +48 -23
data/Gemfile CHANGED
@@ -14,6 +14,6 @@ group :development do
14
14
  gem "mageo", ">= 0.0.0"
15
15
  gem "malge", ">= 0.0.1"
16
16
  gem "maset", ">= 0.0.0"
17
- gem "comana", ">= 0.0.0"
17
+ gem "comana", ">= 0.0.4"
18
18
  gem "builtinextension", ">= 0.0.3"
19
19
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.0.2
data/bin/qsubvasp ADDED
@@ -0,0 +1,30 @@
1
+ #! /usr/bin/env ruby
2
+ # coding: utf-8
3
+
4
+ require "optparse"
5
+
6
+ ## option analysis
7
+ OPTS = {}
8
+ op = OptionParser.new
9
+ op.on("-e", "--economy" , "Prior efficiency."){OPTS[:e] = true}
10
+ op.on("-s", "--speed" , "Prior speed.") {OPTS[:s] = true}
11
+
12
+ op.on("-g", "--geom-opt" , "Geometry optimization.") {OPTS[:g] = true}
13
+ op.on("-n", "--nebm" , "Nudged Elastic Band method."){OPTS[:n] = true}
14
+ op.on("-c", "--cond-find", "Condition Finding.") {OPTS[:c] = true}
15
+
16
+ op.parse!(ARGV)
17
+
18
+ cluster = ARGV[0]
19
+ #cluster = ARGV
20
+ #qsub で複数のクラスターを候補に入れることができるか?e.g., Ga, Ge
21
+ #それによって、ここがかきかわる。
22
+
23
+ puts "Options -e and -s cannot be duplicated." if OPTS[:e] && OPTS[:s]
24
+ if [OPTS[:g], OPTS[:n], OPTS[:c]].select_all(true).size ==
25
+ puts "Options -g, -n, and -c cannot be duplicated."
26
+ exit
27
+ end
28
+
29
+
30
+
@@ -26,115 +26,35 @@ require "vasputils/kpoints.rb"
26
26
  # try00 形式の postfix がついていることを前提とする。
27
27
  # 00 の部分には CONTCAR を POSCAR にする手続きで連続して行う計算の番号を示す。
28
28
  #
29
- class VaspDir
30
-
29
+ class VaspDir < Comana
31
30
  class InitializeError < Exception; end
32
- class ConvergedError < Exception; end
33
- class NotEndedError < Exception; end
34
- class LockedError < Exception; end
35
- class PostfixMismatchError < Exception; end
36
-
37
-
38
- LOCK_FILE = "lock"
39
- POSTFIX = /try(\d+)$/
40
-
41
- YET = 0# - 未計算。
42
- STARTED = 1# - 開始した。
43
- INTERRUPTED = 2# - 中断された。
44
- CONTINUED = 3# - 終了し、次の計算を生成した。
45
- COMPLETED = 4# - 終了し、収束した。
46
-
47
- attr_reader :mode
48
- #attr_reader :dir
49
-
50
- #INCAR 解析とかして、モードを調べる。
51
- #- 格子定数の構造最適化モード(ISIF = 3)
52
- #- 格子定数を固定した構造最適化モード(ISIF = 2)
53
- ##- k 点探索モードは無理だろう。
54
- def initialize(dir_name)
55
- @dir = dir_name
56
-
57
- %w(INCAR KPOINTS POSCAR POTCAR).each do |file|
58
- infile = "#{@dir}/#{file}"
59
- raise InitializeError, infile unless FileTest.exist? infile
60
- end
61
31
 
62
- @incar = Incar.load_file("#{@dir}/INCAR")
63
- case @incar["IBRION"]
64
- when "-1"
65
- @mode = :single_point
66
- #when "1"
67
- # @mode = :molecular_dynamics
68
- when "2"
69
- if (@incar["ISIF"] == "2")
70
- @mode = :geom_opt_atoms
71
- elsif (@incar["ISIF"] == "3")
72
- @mode = :geom_opt_lattice
73
- else
74
- @mode = :geom_opt
75
- end
76
- else
77
- @mode = nil
78
- end
32
+ # 配下の OUTCAR を Outcar インスタンスにして返す。
33
+ # 存在しなければ例外 Errno::ENOENT を返す。
34
+ def outcar
35
+ Outcar.load_file("#{@dir}/OUTCAR")
79
36
  end
80
37
 
81
- # ディレクトリ名を返す。
82
- def name
83
- @dir
38
+ # 配下の CONTCAR を Cell2 インスタンスにして返す。
39
+ # 存在しなければ例外 Errno::ENOENT を返す。
40
+ def contcar
41
+ Poscar.load_file("#{@dir}/CONTCAR")
84
42
  end
85
43
 
86
- # 計算が過去に始まっていれば true を返す。
87
- # 終わっているかは判定しない。
88
- # 具体的には lock ファイルが存在すれば true を返す。
44
+ # 配下の KPOINTS を読み込んだ結果をハッシュにして返す。
89
45
  #
90
- # MEMO
91
- # (mpi 経由で?)vasp を実行すると PI12345 とかいうファイルができるが、
92
- # これはたぶん起動してから若干のタイムラグが生じる。
93
- # このタイムラグ中に別のプロセスが同時に計算したらマズい。
94
- def started?
95
- return File.exist? lock_file
46
+ # 存在しなければ例外 Errno::ENOENT を返す筈だが、
47
+ # vasp dir の判定を incar でやっているので置こる筈がない。
48
+ def incar
49
+ Incar.load_file("#{@dir}/INCAR")
96
50
  end
97
51
 
98
- # 正常に終了していれば true を返す。
99
- # 実行する前や実行中、OUTCAR が完遂していなければ false。
100
- #
101
- # MEMO
102
- # PI12345 ファイルは実行中のみ存在し、終了後 vasp (mpi?) に自動的に削除される。
103
- def normal_ended?
104
- begin
105
- return Outcar.load_file("#{@dir}/OUTCAR")[:normal_ended]
106
- rescue Errno::ENOENT
107
- return false
108
- end
52
+ # 配下の KPOINTS を読み込んだ結果をハッシュにして返す。
53
+ def kpoints
54
+ Kpoints.load_file("#{@dir}/KPOINTS")
109
55
  end
110
56
 
111
- # normal_ended? が false なら false。
112
- # normal_ended? が true のうち、
113
- # 結果を使って次に計算すべきなら true を、そうでなければ false を返す。
114
- #
115
- # 計算すべき、の条件はモードによって異なる。
116
- # NSW = 0 もしくは NSW = 1 のとき、必ず false。
117
- # - :single_point モードならば、常に false。
118
- # - :geom_opt_lattice モードならば、ionic step が 2 以上なら true。
119
- # - :geom_opt_atoms モードならば、ionic step が NSW と同じなら true。
120
- #
121
- def to_be_continued?
122
- begin
123
- outcar = Outcar.load_file("#{@dir}/OUTCAR")
124
- rescue Errno::ENOENT
125
- return false
126
- end
127
- ionic_steps = outcar[:ionic_steps]
128
- return false unless outcar[:normal_ended]
129
- return false if @incar["NSW"].to_i <= 1
130
- if @mode == :geom_opt_lattice
131
- return ionic_steps != 1
132
- elsif @mode == :geom_opt_atoms
133
- return ionic_steps == @incar["NSW"].to_i
134
- else
135
- return false
136
- end
137
- end
57
+ private
138
58
 
139
59
  # vasp を投げる。
140
60
  # 計算実行時に lock を生成する。
@@ -148,135 +68,173 @@ class VaspDir
148
68
  # machinefile を生成しないとどのホストで計算するか、安定しない。
149
69
  # そのうち mpiexec from torque に対応するが、
150
70
  # まずは mpirun で動くように作る。
151
- def calculate
152
- raise LockedError if started?
153
-
154
- File.open(lock_file, "w") do |lock_io|
155
- lock_io.puts "HOST: #{ENV["HOST"]}"
156
- lock_io.puts "START: #{Time.now.to_s}"
157
- lock_io.flush
158
-
159
- num_cores = 4 if /^Se\d\d/ =~ ENV["HOST"]
160
- num_cores = 4 if /^Ge\d\d/ =~ ENV["HOST"]
161
- num_cores = 4 if /^Ga\d\d/ =~ ENV["HOST"]
162
- num_cores = 4 if /^At$/ =~ ENV["HOST"]
163
- num_cores = 2 if /^yggdrasil$/ =~ ENV["HOST"]
164
-
165
- # machines を生成
166
- File.open("#{@dir}/machines", "w") do |io|
167
- io.puts "localhost:#{num_cores}"
168
- end
169
-
170
- command = "cd #{@dir};" +
171
- "/usr/local/calc/mpich-1.2.7-ifc7/bin/mpirun " +
172
- "-np #{num_cores} " +
173
- "-machinefile machines " +
174
- "/usr/local/calc/vasp/vasp4631mpi" +
175
- "> stdout"
176
-
177
- if $TEST
178
- generated_files = [
179
- "CHG",
180
- "CHGCAR",
181
- "CONTCAR",
182
- "DOSCAR",
183
- "EIGENVAL",
184
- "IBZKPT",
185
- "OSZICAR",
186
- "OUTCAR",
187
- "PCDAT",
188
- "WAVECAR",
189
- "XDATCAR",
190
- "machines",
191
- "vasprun.xml",
192
- "lock",
193
- ]
194
- generated_files.map!{|i| "#{@dir}/#{i}"}
195
- command = "touch #{generated_files.join(" ")}"
196
- end
197
-
198
- status = system command
199
- if status
200
- lock_io.puts "STATUS: normal ended."
201
- else
202
- lock_io.puts "STATUS: irregular ended, status #{$?}."
203
- end
71
+ def send_command
72
+ #File.open(lock_file, "w") do |lock_io|
73
+ # lock_io.puts "HOST: #{ENV["HOST"]}"
74
+ # lock_io.puts "START: #{Time.now.to_s}"
75
+ # lock_io.flush
76
+
77
+ # num_cores = 4 if /^Se\d\d/ =~ ENV["HOST"]
78
+ # num_cores = 4 if /^Ge\d\d/ =~ ENV["HOST"]
79
+ # num_cores = 4 if /^Ga\d\d/ =~ ENV["HOST"]
80
+ # num_cores = 4 if /^At$/ =~ ENV["HOST"]
81
+ # num_cores = 2 if /^yggdrasil$/ =~ ENV["HOST"]
82
+
83
+ # # machines を生成
84
+ # File.open("#{@dir}/machines", "w") do |io|
85
+ # io.puts "localhost:#{num_cores}"
86
+ # end
87
+ #end
88
+ num_cores = 4
89
+ command = "cd #{@dir};" +
90
+ "/usr/local/calc/mpich-1.2.7-ifc7/bin/mpirun " +
91
+ "-np #{num_cores} " +
92
+ "-machinefile machines " +
93
+ "/usr/local/calc/vasp/vasp4631mpi" +
94
+ "> stdout"
95
+
96
+ if $TEST
97
+ generated_files = [
98
+ "CHG",
99
+ "CHGCAR",
100
+ "CONTCAR",
101
+ "DOSCAR",
102
+ "EIGENVAL",
103
+ "IBZKPT",
104
+ "OSZICAR",
105
+ "OUTCAR",
106
+ "PCDAT",
107
+ "WAVECAR",
108
+ "XDATCAR",
109
+ "machines",
110
+ "vasprun.xml",
111
+ "lock",
112
+ ]
113
+ generated_files.map!{|i| "#{@dir}/#{i}"}
114
+ command = "touch #{generated_files.join(" ")}"
204
115
  end
205
- end
206
-
207
- # 次の計算ディレクトリを作成し、
208
- # その VaspDir クラスで self を置き換える。
209
- # 計算が正常終了していなければ、例外 VaspDirNotEndedError を生じる。
210
- # 次の計算ディレクトリが既に存在していれば例外 Errno::EEXIST が投げられる。
211
- def next
212
- raise NotEndedError unless normal_ended?
213
- raise ConvergedError unless to_be_continued?
214
- #postfix = /try(\d+)$/
215
- POSTFIX =~ @dir
216
- try_num = $1.to_i
217
- next_dir = @dir.sub(POSTFIX, sprintf("try%02d", try_num + 1))
218
- Dir.mkdir next_dir
219
- FileUtils.cp( "#{@dir}/INCAR" , "#{next_dir}/INCAR")
220
- FileUtils.cp( "#{@dir}/KPOINTS", "#{next_dir}/KPOINTS")
221
- FileUtils.cp( "#{@dir}/POTCAR" , "#{next_dir}/POTCAR")
222
- FileUtils.cp( "#{@dir}/CONTCAR", "#{next_dir}/POSCAR")
223
- initialize(next_dir)
224
- end
225
-
226
- # Postprocess.
227
- def teardown
228
- # Do nothing.
229
- end
230
116
 
231
- # Return number of electronic steps.
232
- def internal_steps
233
- return outcar[:electronic_steps] if outcar
234
- return 0
117
+ system command
118
+ #status = system command
119
+ #if status
120
+ # lock_io.puts "STATUS: normal ended."
121
+ #else
122
+ # lock_io.puts "STATUS: irregular ended, status #{$?}."
123
+ #end
235
124
  end
236
125
 
237
- # Return number of ionic steps.
238
- def external_steps
239
- return outcar[:ionic_steps] if outcar
240
- return 0
241
- end
242
-
243
- # Return elapsed time.
244
- def elapsed_time
245
- return outcar[:elapsed_time] if outcar
246
- return 0.0
247
- end
248
-
249
- # 配下の OUTCAR を Outcar インスタンスにして返す。
250
- # 存在しなければ例外 Errno::ENOENT を返す。
251
- def outcar
252
- Outcar.load_file("#{@dir}/OUTCAR")
253
- end
126
+ #INCAR 解析とかして、モードを調べる。
127
+ #- 格子定数の構造最適化モード(ISIF = 3)
128
+ #- 格子定数を固定した構造最適化モード(ISIF = 2)
129
+ ##- k 点探索モードは無理だろう。
130
+ def set_parameters
131
+ #pp @dir; exit;
132
+ %w(INCAR KPOINTS POSCAR POTCAR).each do |file|
133
+ infile = "#{@dir}/#{file}"
134
+ raise InitializeError, infile unless FileTest.exist? infile
135
+ end
254
136
 
255
- # 配下の CONTCAR を Cell2 インスタンスにして返す。
256
- # 存在しなければ例外 Errno::ENOENT を返す。
257
- def contcar
258
- Poscar.load_file("#{@dir}/CONTCAR")
137
+ #@incar = Incar.load_file("#{@dir}/INCAR")
138
+ #case @incar["IBRION"]
139
+ #when "-1"
140
+ # @mode = :single_point
141
+ ##when "1"
142
+ ## @mode = :molecular_dynamics
143
+ #when "2"
144
+ # if (@incar["ISIF"] == "2")
145
+ # @mode = :geom_opt_atoms
146
+ # elsif (@incar["ISIF"] == "3")
147
+ # @mode = :geom_opt_lattice
148
+ # else
149
+ # @mode = :geom_opt
150
+ # end
151
+ #else
152
+ # @mode = nil
153
+ #end
154
+
155
+ @lockdir = "lock"
156
+ @alive_time = 3600
157
+ @outfiles = ["OUTCAR"] # Files only to output should be indicated.
259
158
  end
260
159
 
261
- # 配下の KPOINTS を読み込んだ結果をハッシュにして返す。
160
+ # 正常に終了していれば true を返す。
161
+ # 実行する前や実行中、OUTCAR が完遂していなければ false。
262
162
  #
263
- # 存在しなければ例外 Errno::ENOENT を返す筈だが、
264
- # vasp dir の判定を incar でやっているので置こる筈がない。
265
- def incar
266
- Incar.load_file("#{@dir}/INCAR")
267
- end
268
-
269
- # 配下の KPOINTS を読み込んだ結果をハッシュにして返す。
270
- def kpoints
271
- Kpoints.load_file("#{@dir}/KPOINTS")
272
- end
273
-
274
- private
275
-
276
- # Return lock file name.
277
- def lock_file
278
- return "#{@dir}/#{LOCK_FILE}"
163
+ # MEMO
164
+ # PI12345 ファイルは実行中のみ存在し、終了後 vasp (mpi?) に自動的に削除される。
165
+ def finished?
166
+ begin
167
+ return Outcar.load_file("#{@dir}/OUTCAR")[:normal_ended]
168
+ rescue Errno::ENOENT
169
+ return false
170
+ end
279
171
  end
280
172
 
281
173
  end
282
174
 
175
+ #class VaspGeometryOptimization < Comana
176
+ # # 次の計算ディレクトリを作成し、
177
+ # # その VaspDir クラスで self を置き換える。
178
+ # # 計算が正常終了していなければ、例外 VaspDirNotEndedError を生じる。
179
+ # # 次の計算ディレクトリが既に存在していれば例外 Errno::EEXIST が投げられる。
180
+ # def next
181
+ # raise NotEndedError unless normal_ended?
182
+ # raise ConvergedError unless to_be_continued?
183
+ # #postfix = /try(\d+)$/
184
+ # POSTFIX =~ @dir
185
+ # try_num = $1.to_i
186
+ # next_dir = @dir.sub(POSTFIX, sprintf("try%02d", try_num + 1))
187
+ # Dir.mkdir next_dir
188
+ # FileUtils.cp( "#{@dir}/INCAR" , "#{next_dir}/INCAR")
189
+ # FileUtils.cp( "#{@dir}/KPOINTS", "#{next_dir}/KPOINTS")
190
+ # FileUtils.cp( "#{@dir}/POTCAR" , "#{next_dir}/POTCAR")
191
+ # FileUtils.cp( "#{@dir}/CONTCAR", "#{next_dir}/POSCAR")
192
+ # initialize(next_dir)
193
+ # end
194
+ #
195
+ # # Return number of electronic steps.
196
+ # def internal_steps
197
+ # return outcar[:electronic_steps] if outcar
198
+ # return 0
199
+ # end
200
+ #
201
+ # # Return number of ionic steps.
202
+ # def external_steps
203
+ # return outcar[:ionic_steps] if outcar
204
+ # return 0
205
+ # end
206
+ #
207
+ # # Return elapsed time.
208
+ # def elapsed_time
209
+ # return outcar[:elapsed_time] if outcar
210
+ # return 0.0
211
+ # end
212
+ #
213
+ # # normal_ended? が false なら false。
214
+ # # normal_ended? が true のうち、
215
+ # # 結果を使って次に計算すべきなら true を、そうでなければ false を返す。
216
+ # #
217
+ # # 計算すべき、の条件はモードによって異なる。
218
+ # # NSW = 0 もしくは NSW = 1 のとき、必ず false。
219
+ # # - :single_point モードならば、常に false。
220
+ # # - :geom_opt_lattice モードならば、ionic step が 2 以上なら true。
221
+ # # - :geom_opt_atoms モードならば、ionic step が NSW と同じなら true。
222
+ # #
223
+ # def to_be_continued?
224
+ # begin
225
+ # outcar = Outcar.load_file("#{@dir}/OUTCAR")
226
+ # rescue Errno::ENOENT
227
+ # return false
228
+ # end
229
+ # ionic_steps = outcar[:ionic_steps]
230
+ # return false unless outcar[:normal_ended]
231
+ # return false if @incar["NSW"].to_i <= 1
232
+ # if @mode == :geom_opt_lattice
233
+ # return ionic_steps != 1
234
+ # elsif @mode == :geom_opt_atoms
235
+ # return ionic_steps == @incar["NSW"].to_i
236
+ # else
237
+ # return false
238
+ # end
239
+ # end
240
+ #