vasputils 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
+ #