vasputils 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/bin/checkvasp +79 -0
- data/bin/runvasp +23 -5
- data/lib/vasputils/vaspdir.rb +6 -0
- data/lib/vasputils/vaspgeomopt.rb +19 -19
- data/lib/vasputils/vaspkpointsfinder.rb +72 -0
- data/memo.txt +5 -0
- data/test/test_calcinspector.rb +29 -29
- data/test/test_incar.rb +109 -109
- data/test/test_kpoints.rb +92 -92
- data/test/test_outcar.rb +154 -154
- data/test/test_poscar.rb +184 -184
- data/test/test_potcar.rb +52 -52
- data/test/test_vaspdir.rb +10 -0
- data/test/test_vaspkpointsfinder.rb +25 -0
- data/test/vaspkpointsfinder/01-01-01/try00/INCAR +17 -0
- data/test/vaspkpointsfinder/01-01-01/try00/KPOINTS +6 -0
- data/test/vaspkpointsfinder/01-01-01/try00/POSCAR +8 -0
- data/test/vaspkpointsfinder/01-01-01/try00/POTCAR +0 -0
- data/vasputils.gemspec +10 -6
- metadata +31 -29
- data/bin/lsvasp +0 -95
- data/bin/lsvaspdir +0 -63
- data/bin/lsvaspseries +0 -95
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.9
|
data/bin/checkvasp
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
# Show state of vasp geometry optimization calculations.
|
5
|
+
|
6
|
+
#require "vasputils/calcseries.rb"
|
7
|
+
require "rubygems"
|
8
|
+
gem "vasputils"
|
9
|
+
|
10
|
+
require "vasputils/vaspgeomopt.rb"
|
11
|
+
require "vasputils/vaspdir.rb"
|
12
|
+
require "pp"
|
13
|
+
#require "optparse"
|
14
|
+
|
15
|
+
LONGEST_STATE = :terminated.size
|
16
|
+
KLASSES = [VaspDir, VaspGeomOpt]
|
17
|
+
|
18
|
+
dirs = ARGV
|
19
|
+
dirs = Dir.glob("*").sort if ARGV.empty?
|
20
|
+
|
21
|
+
def guess(dir)
|
22
|
+
KLASSES.each do |klass|
|
23
|
+
begin
|
24
|
+
vd = klass.new(dir)
|
25
|
+
return klass
|
26
|
+
rescue klass::InitializeError
|
27
|
+
end
|
28
|
+
end
|
29
|
+
raise "Cannot identify class for directory #{dir}."
|
30
|
+
end
|
31
|
+
|
32
|
+
dirs.each do |dir|
|
33
|
+
next unless File.directory? dir
|
34
|
+
|
35
|
+
begin
|
36
|
+
klass = guess(dir)
|
37
|
+
klass_name = klass.to_s
|
38
|
+
rescue
|
39
|
+
klass_name = "UnknownDir"
|
40
|
+
end
|
41
|
+
|
42
|
+
printf "%-11s ", klass_name
|
43
|
+
|
44
|
+
case klass_name
|
45
|
+
when "VaspDir"
|
46
|
+
calc = klass.new(dir)
|
47
|
+
printf "%-10s ", calc.state
|
48
|
+
#pp calc.outcar
|
49
|
+
printf "%5s ", ""
|
50
|
+
begin
|
51
|
+
outcar = calc.outcar
|
52
|
+
printf "%8.3f %3d (%3d) ",
|
53
|
+
outcar[:totens][-1], outcar[:ionic_steps], outcar[:electronic_steps]
|
54
|
+
rescue
|
55
|
+
printf "%8s %3s (%3s) ", " "*8, " "*3, " "*3
|
56
|
+
end
|
57
|
+
|
58
|
+
when "VaspGeomOpt"
|
59
|
+
calc = klass.new(dir)
|
60
|
+
printf "%-10s ", calc.state
|
61
|
+
|
62
|
+
ld = calc.latest_dir
|
63
|
+
printf "%5s ", ld.dir.sub(/.*try/, "try")
|
64
|
+
begin
|
65
|
+
outcar = ld.outcar
|
66
|
+
printf "%8.3f %3d (%3d) ",
|
67
|
+
outcar[:totens][-1], outcar[:ionic_steps], outcar[:electronic_steps]
|
68
|
+
rescue
|
69
|
+
printf "%8s %3s (%3s) ", " "*8, " "*3, " "*3
|
70
|
+
end
|
71
|
+
|
72
|
+
when "UnknownDir"
|
73
|
+
printf "-" * 35
|
74
|
+
printf " "
|
75
|
+
|
76
|
+
end
|
77
|
+
puts dir
|
78
|
+
|
79
|
+
end
|
data/bin/runvasp
CHANGED
@@ -12,17 +12,35 @@ require "vasputils/vaspgeomopt.rb"
|
|
12
12
|
require "optparse"
|
13
13
|
|
14
14
|
## option analysis
|
15
|
-
|
15
|
+
opts = {}
|
16
16
|
op = OptionParser.new
|
17
|
-
op.on("-g" , "--geom-opt",
|
17
|
+
op.on("-g" , "--geom-opt", "Geometry optimization"){opts[:geom] = true}
|
18
|
+
op.on("-c" , "--cond-find", "Condition finding" ){opts[:cond] = true}
|
18
19
|
op.parse!(ARGV)
|
19
20
|
|
20
21
|
dir = ARGV[0] || "."
|
21
22
|
|
22
|
-
if
|
23
|
-
|
23
|
+
if opts[:geom] && opts[:cond]
|
24
|
+
puts "-g and -c must not be duplicated."
|
25
|
+
exit
|
26
|
+
end
|
27
|
+
|
28
|
+
if opts[:geom]
|
29
|
+
begin
|
30
|
+
calc_dir = VaspGeomOpt.new(dir)
|
31
|
+
rescue VaspGeomOpt::NoVaspDirError
|
32
|
+
puts "Not suitable for VaspGeomOpt: #{dir}"
|
33
|
+
exit
|
34
|
+
end
|
35
|
+
elsif opts[:cond]
|
36
|
+
TODO
|
24
37
|
else
|
25
|
-
|
38
|
+
begin
|
39
|
+
calc_dir = VaspDir.new(dir)
|
40
|
+
rescue VaspDir::InitializeError
|
41
|
+
puts "Not VaspDir: #{dir}"
|
42
|
+
exit
|
43
|
+
end
|
26
44
|
end
|
27
45
|
|
28
46
|
#pp calc_dir.class.ancestors
|
data/lib/vasputils/vaspdir.rb
CHANGED
@@ -40,6 +40,12 @@ class VaspDir < ComputationManager
|
|
40
40
|
Outcar.load_file("#{@dir}/OUTCAR")
|
41
41
|
end
|
42
42
|
|
43
|
+
# 配下の POSCAR を Cell2 インスタンスにして返す。
|
44
|
+
# 存在しなければ例外 Errno::ENOENT を返す。
|
45
|
+
def poscar
|
46
|
+
Poscar.load_file("#{@dir}/POSCAR")
|
47
|
+
end
|
48
|
+
|
43
49
|
# 配下の CONTCAR を Cell2 インスタンスにして返す。
|
44
50
|
# 存在しなければ例外 Errno::ENOENT を返す。
|
45
51
|
def contcar
|
@@ -70,6 +70,25 @@ class VaspGeomOpt < ComputationManager
|
|
70
70
|
return true
|
71
71
|
end
|
72
72
|
|
73
|
+
# Find latest VaspDir.
|
74
|
+
# Return a last VaspDir which has the name by name sort
|
75
|
+
# and which can be made as a VaspDir instance.
|
76
|
+
# Note: in a series of geometry optimization,
|
77
|
+
# the directory names should have a rule of naming
|
78
|
+
# which can define a method <=>.
|
79
|
+
# Usually, it is simple sort of String.
|
80
|
+
def latest_dir
|
81
|
+
Dir.glob("#{@dir}/*").sort.reverse.find do |dir|
|
82
|
+
begin
|
83
|
+
vd = VaspDir.new(dir)
|
84
|
+
return vd
|
85
|
+
rescue VaspDir::InitializeError
|
86
|
+
next
|
87
|
+
end
|
88
|
+
end
|
89
|
+
raise NoVaspDirError, @dir
|
90
|
+
end
|
91
|
+
|
73
92
|
private
|
74
93
|
|
75
94
|
# Generate next directory of latest_dir.
|
@@ -92,24 +111,5 @@ class VaspGeomOpt < ComputationManager
|
|
92
111
|
VaspDir.new(new_dir)
|
93
112
|
end
|
94
113
|
|
95
|
-
# Find latest VaspDir.
|
96
|
-
# Return a last VaspDir which has the name by name sort
|
97
|
-
# and which can be made as a VaspDir instance.
|
98
|
-
# Note: in a series of geometry optimization,
|
99
|
-
# the directory names should have a rule of naming
|
100
|
-
# which can define a method <=>.
|
101
|
-
# Usually, it is simple sort of String.
|
102
|
-
def latest_dir
|
103
|
-
Dir.glob("#{@dir}/*").sort.reverse.find do |dir|
|
104
|
-
begin
|
105
|
-
vd = VaspDir.new(dir)
|
106
|
-
return vd
|
107
|
-
rescue VaspDir::InitializeError
|
108
|
-
next
|
109
|
-
end
|
110
|
-
end
|
111
|
-
raise NoVaspDirError, @dir
|
112
|
-
end
|
113
|
-
|
114
114
|
end
|
115
115
|
|
@@ -0,0 +1,72 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
require "vasputils/vaspdir.rb"
|
5
|
+
|
6
|
+
#
|
7
|
+
#
|
8
|
+
#
|
9
|
+
class VaspKpointsFinder
|
10
|
+
|
11
|
+
|
12
|
+
def initialize(dir)
|
13
|
+
@dir = dir # redefine in subclass.
|
14
|
+
@lockdir = "lock_vaspkfind"
|
15
|
+
@alive_time = 3600
|
16
|
+
|
17
|
+
@previous_kpoints = nil
|
18
|
+
@kpoints = [ 0, 0, 0 ] #indicate ka, kb, kc
|
19
|
+
|
20
|
+
@kpoint_candidates = list_kpoints
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def calculate
|
26
|
+
@previous_kpoints = Marshal.load(Marshal.dump(@kpoints))
|
27
|
+
|
28
|
+
#@kpoints を起点として、
|
29
|
+
#ka の最適化し、精度以下となる最低の条件を @kpoints に登録。
|
30
|
+
#kb の最適化し、精度以下となる最低の条件を @kpoints に登録。
|
31
|
+
#kc の最適化し、精度以下となる最低の条件を @kpoints に登録。
|
32
|
+
3.times do |i| # each three k axis.
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
#k の gamma center / hexagonal
|
37
|
+
#k の shift
|
38
|
+
#spin の有無。当面は有りを前提。INCAR で ISPIN をチェックする。
|
39
|
+
end
|
40
|
+
|
41
|
+
# Do nothing.
|
42
|
+
def prepare_next
|
43
|
+
end
|
44
|
+
|
45
|
+
def finished?
|
46
|
+
@previous_kpoints == @kpoints
|
47
|
+
end
|
48
|
+
|
49
|
+
# Using lattice constants of POSCAR, which is an initial value.
|
50
|
+
#
|
51
|
+
def list_kpoints
|
52
|
+
#vd = VaspDir.new(Dir.glob(@dir + "/*/try00")[0])
|
53
|
+
#results = []
|
54
|
+
#vd.poscar.axes.get_lattice_constants[0..2].map do |length|
|
55
|
+
#end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
#def lowest_encut
|
61
|
+
# min_dir = Dir.glob(@dir + "/*/*").min_by { |dir| VaspDir.new(dir).incar["ENCUT"] }
|
62
|
+
# VaspDir.new(min_dir).incar["ENCUT"].to_i
|
63
|
+
#end
|
64
|
+
|
65
|
+
#def list_encuts
|
66
|
+
# results = []
|
67
|
+
# (lowest_encut/100).upto 10 do |i|
|
68
|
+
# results << i * 100
|
69
|
+
# end
|
70
|
+
# results
|
71
|
+
#end
|
72
|
+
|
data/memo.txt
CHANGED
data/test/test_calcinspector.rb
CHANGED
@@ -5,47 +5,47 @@ require "test/unit"
|
|
5
5
|
require "vasputils/calcinspector.rb"
|
6
6
|
|
7
7
|
class YetCalc
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
def started? ; return false; end
|
9
|
+
def normal_ended? ; return false; end
|
10
|
+
def to_be_continued?; return false; end
|
11
|
+
def finished? ; return false; end
|
12
12
|
end
|
13
13
|
|
14
14
|
class StartedCalc
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
def started? ; return true ; end
|
16
|
+
def normal_ended? ; return false; end
|
17
|
+
def to_be_continued?; return false; end
|
18
|
+
def finished? ; return false; end
|
19
19
|
end
|
20
20
|
|
21
21
|
class NextCalc
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
def started? ; return true ; end
|
23
|
+
def normal_ended? ; return true ; end
|
24
|
+
def to_be_continued?; return true ; end
|
25
|
+
def finished? ; return false; end
|
26
26
|
end
|
27
27
|
|
28
28
|
class FinishedCalc
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
def started? ; return true ; end
|
30
|
+
def normal_ended? ; return true ; end
|
31
|
+
def to_be_continued?; return false; end
|
32
|
+
def finished? ; return true ; end
|
33
33
|
end
|
34
34
|
|
35
35
|
class TC_ListCalculation < Test::Unit::TestCase
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
36
|
+
def setup
|
37
|
+
@dc00 = YetCalc.new
|
38
|
+
@dc01 = StartedCalc.new
|
39
|
+
@dc02 = NextCalc.new
|
40
|
+
@dc03 = FinishedCalc.new
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_self_inspect
|
44
|
+
assert_equal("YET", CalcInspector.inspect(@dc00))
|
45
|
+
assert_equal("STARTED", CalcInspector.inspect(@dc01))
|
46
|
+
assert_equal("NEXT", CalcInspector.inspect(@dc02))
|
47
|
+
assert_equal("FINISHED", CalcInspector.inspect(@dc03))
|
48
|
+
end
|
49
49
|
|
50
50
|
|
51
51
|
|
data/test/test_incar.rb
CHANGED
@@ -5,122 +5,122 @@ require "test/unit"
|
|
5
5
|
require "vasputils/incar.rb"
|
6
6
|
require "stringio"
|
7
7
|
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
8
|
+
# assert_equal( cor, data)
|
9
|
+
# assert_in_delta( cor, data, $tolerance )
|
10
|
+
# assert_raise( RuntimeError ){}
|
11
11
|
|
12
12
|
class TC_Incar < Test::Unit::TestCase
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
13
|
+
#def setup
|
14
|
+
# @k = Incar.new
|
15
|
+
#end
|
16
|
+
|
17
|
+
SAMPLE_PAIRS = {
|
18
|
+
"SYSTEM" => "Untitled",
|
19
|
+
"PREC" => "High",
|
20
|
+
"IBRION" => "2",
|
21
|
+
"NSW" => "100",
|
22
|
+
"ISIF" => "2",
|
23
|
+
"ENCUT" => "400",
|
24
|
+
"NELM" => "60",
|
25
|
+
"NELMIN" => "2",
|
26
|
+
"EDIFF" => "1.0e-05",
|
27
|
+
"EDIFFG" => "-0.02",
|
28
|
+
"VOSKOWN" => "1",
|
29
|
+
"NBLOCK" => "1",
|
30
|
+
"ISPIN" => "1",
|
31
|
+
"INIWAV" => "1",
|
32
|
+
"ISTART" => "1",
|
33
|
+
"ICHARG" => "1",
|
34
|
+
"LWAVE" => ".TRUE.",
|
35
|
+
"LCHARG" => ".TRUE.",
|
36
|
+
"ISMEAR" => "0",
|
37
|
+
"SIGMA" => "0.1",
|
38
|
+
"IALGO" => "38",
|
39
|
+
"LREAL" => "Auto",
|
40
|
+
"NGX" => "36",
|
41
|
+
"NGY" => "36",
|
42
|
+
"NGZ" => "42",
|
43
|
+
}
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
45
|
+
def test_self_parse
|
46
|
+
io = StringIO.new
|
47
|
+
io.puts "# SCF input for VASP"
|
48
|
+
io.puts "# Note that VASP uses the FIRST occurence of a keyword"
|
49
|
+
io.puts "# if single point calc, IBRION = -1, NSW = 0, and comment out ISIF"
|
50
|
+
io.puts ""
|
51
|
+
io.puts "SYSTEM = Untitled (VASP)"
|
52
|
+
io.puts " PREC = High"
|
53
|
+
io.puts " IBRION = 2 #-1:atoms not moved, 1:quasi-Newton, 2:conjugate-gradient"
|
54
|
+
io.puts " NSW = 100 #maximum number of ionic steps"
|
55
|
+
io.puts " ISIF = 2"
|
56
|
+
io.puts " ENCUT = 400"
|
57
|
+
io.puts " NELM = 60 #maximum number of electronic steps"
|
58
|
+
io.puts " NELMIN = 2 #minimum number of electronic steps"
|
59
|
+
io.puts " EDIFF = 1.0e-05"
|
60
|
+
io.puts " EDIFFG = -0.02"
|
61
|
+
io.puts " VOSKOWN = 1"
|
62
|
+
io.puts " NBLOCK = 1"
|
63
|
+
io.puts " ISPIN = 1 #1:non spin polarized, 2:spin polarized"
|
64
|
+
io.puts " INIWAV = 1"
|
65
|
+
io.puts " ISTART = 1"
|
66
|
+
io.puts " ICHARG = 1"
|
67
|
+
io.puts " LWAVE = .TRUE."
|
68
|
+
io.puts " LCHARG = .TRUE."
|
69
|
+
io.puts " ISMEAR = 0"
|
70
|
+
io.puts " SIGMA = 0.1"
|
71
|
+
io.puts " IALGO = 38 #38:KosugiAlgorithm, 48:RMM-DIIS"
|
72
|
+
io.puts " LREAL = Auto #fast & not accurate"
|
73
|
+
io.puts " NGX = 36"
|
74
|
+
io.puts " NGY = 36"
|
75
|
+
io.puts " NGZ = 42"
|
76
|
+
io.rewind
|
77
|
+
pairs = Incar.parse(io)
|
78
|
+
assert_equal(SAMPLE_PAIRS, pairs)
|
79
|
+
end
|
80
80
|
|
81
|
-
|
82
|
-
|
83
|
-
|
81
|
+
def test_self_load_file
|
82
|
+
pairs = Incar.load_file "test/incar/INCAR.00"
|
83
|
+
assert_equal(SAMPLE_PAIRS, pairs)
|
84
84
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
85
|
+
corrects = {
|
86
|
+
"SYSTEM" => "Untitled",
|
87
|
+
"PREC" => "High",
|
88
|
+
"IBRION" => "2",
|
89
|
+
"NSW" => "0",
|
90
|
+
"ISIF" => "2",
|
91
|
+
"ENCUT" => "400",
|
92
|
+
"NELM" => "60",
|
93
|
+
"NELMIN" => "2",
|
94
|
+
"EDIFF" => "1.0e-05",
|
95
|
+
"EDIFFG" => "-0.02",
|
96
|
+
"VOSKOWN" => "1",
|
97
|
+
"NBLOCK" => "1",
|
98
|
+
"ISPIN" => "1",
|
99
|
+
"INIWAV" => "1",
|
100
|
+
"ISTART" => "1",
|
101
|
+
"ICHARG" => "1",
|
102
|
+
"LWAVE" => ".TRUE.",
|
103
|
+
"LCHARG" => ".TRUE.",
|
104
|
+
"ISMEAR" => "0",
|
105
|
+
"SIGMA" => "0.1",
|
106
|
+
"IALGO" => "38",
|
107
|
+
"LREAL" => "Auto",
|
108
|
+
"NGX" => "36",
|
109
|
+
"NGY" => "36",
|
110
|
+
"NGZ" => "42",
|
111
|
+
}
|
112
|
+
pairs = Incar.load_file "test/incar/INCAR.01"
|
113
|
+
assert_equal(corrects, pairs)
|
114
114
|
|
115
|
-
|
116
|
-
|
117
|
-
|
115
|
+
# not exist
|
116
|
+
assert_raise(Errno::ENOENT){Incar.load_file("")}
|
117
|
+
end
|
118
118
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
119
|
+
#def test_dump
|
120
|
+
#
|
121
|
+
#
|
122
|
+
# TODO
|
123
|
+
#end
|
124
124
|
|
125
125
|
end
|
126
126
|
|