lib/vasputils/poscar.rb in vasputils-0.0.3 vs lib/vasputils/poscar.rb in vasputils-0.0.4
- old
+ new
@@ -16,153 +16,153 @@
# こうしておくことで POTCAR がない環境でも POSCAR を扱うことができる。
#
# VASP 5 系を使うようになれば事情が変わるだろう。
class Poscar
- class ElementMismatchError < Exception; end
- class ParseError < Exception; end
+ class ElementMismatchError < Exception; end
+ class ParseError < Exception; end
- # io を読み込んで Cell クラスインスタンスを返す。
- # 構文解析できなければ例外 Poscar::ParseError を投げる。
- def self.parse(io)
- # analyze POSCAR.
+ # io を読み込んで Cell クラスインスタンスを返す。
+ # 構文解析できなければ例外 Poscar::ParseError を投げる。
+ def self.parse(io)
+ # analyze POSCAR.
- begin
- #line 1: comment (string)
- comment = io.readline.chomp
+ begin
+ #line 1: comment (string)
+ comment = io.readline.chomp
- #line 2: universal scaling factor (float)
- scale = io.readline.to_f
- raise "Poscar.load_file cannot use negative scaling factor.\n" if scale < 0
+ #line 2: universal scaling factor (float)
+ scale = io.readline.to_f
+ raise "Poscar.load_file cannot use negative scaling factor.\n" if scale < 0
- #line 3-5: axes (3x3 Array of float)
- axes = []
- 3.times do |i| #each axis of a, b, c.
- vec = io.readline.strip.split(/\s+/) #in x,y,z directions
- axes << vec.collect! { |i| i.to_f * scale } #multiply scaling factor
- end
+ #line 3-5: axes (3x3 Array of float)
+ axes = []
+ 3.times do |i| #each axis of a, b, c.
+ vec = io.readline.strip.split(/\s+/) #in x,y,z directions
+ axes << vec.collect! { |i| i.to_f * scale } #multiply scaling factor
+ end
- #line 6: numbers of elements. e.g.,[1, 1, 2]
- nums_elements = io.readline.strip.split( /\s+/ ).map{|i| i.to_i}
+ #line 6: numbers of elements. e.g.,[1, 1, 2]
+ nums_elements = io.readline.strip.split( /\s+/ ).map{|i| i.to_i}
- #line 7-(8): 'Selective dynamics' or not (bool)
- line = io.readline
- if line =~ /^\s*s/i
- selective_dynamics = true
- line = io.readline # when this situation, reading one more line is nessesarry
- end
+ #line 7-(8): 'Selective dynamics' or not (bool)
+ line = io.readline
+ if line =~ /^\s*s/i
+ selective_dynamics = true
+ line = io.readline # when this situation, reading one more line is nessesarry
+ end
- if (line =~ /^\s*d/i ) # allow only 'Direct' now
- direct = true
- else
- raise "Not 'direct' indication."
- end
+ if (line =~ /^\s*d/i ) # allow only 'Direct' now
+ direct = true
+ else
+ raise "Not 'direct' indication."
+ end
- #line 9(8): position
- #e.g., positions_of_elements
- #e.g., movable_flags_of_elements
+ #line 9(8): position
+ #e.g., positions_of_elements
+ #e.g., movable_flags_of_elements
- atoms = []
- nums_elements.size.times do |elem_index|
- nums_elements[elem_index].times do |index|
- items = io.readline.strip.split( /\s+/ )
- pos = items[0..2].map {|coord| coord.to_f}
- #pp pos
+ atoms = []
+ nums_elements.size.times do |elem_index|
+ nums_elements[elem_index].times do |index|
+ items = io.readline.strip.split( /\s+/ )
+ pos = items[0..2].map {|coord| coord.to_f}
+ #pp pos
- mov_flags = []
- if items.size >= 6 then
- items[3..5].each do |i|
- ( i =~ /^t/i ) ? mov_flags << true : mov_flags << false
- end
- atoms << Atom.new(elem_index, pos, mov_flags)
- else
- atoms << Atom.new(elem_index, pos)
- end
- end
- end
- rescue EOFError
- raise ParseError, "end of file reached"
- end
+ mov_flags = []
+ if items.size >= 6 then
+ items[3..5].each do |i|
+ ( i =~ /^t/i ) ? mov_flags << true : mov_flags << false
+ end
+ atoms << Atom.new(elem_index, pos, mov_flags)
+ else
+ atoms << Atom.new(elem_index, pos)
+ end
+ end
+ end
+ rescue EOFError
+ raise ParseError, "end of file reached"
+ end
- cell = Cell.new(axes, atoms )
- cell.comment = comment
- cell
- end
+ cell = Cell.new(axes, atoms )
+ cell.comment = comment
+ cell
+ end
- # file で与えられた名前のファイルを読み込んで Cell クラスインスタンスを返す。
- # 構文解析できなければ例外 Poscar::ParseError を投げる。
- def self.load_file(file)
- io = File.open(file, "r")
- self.parse(io)
- end
+ # file で与えられた名前のファイルを読み込んで Cell クラスインスタンスを返す。
+ # 構文解析できなければ例外 Poscar::ParseError を投げる。
+ def self.load_file(file)
+ io = File.open(file, "r")
+ self.parse(io)
+ end
- # POSCAR 形式で書き出す。
- # cell は Cell クラスインスタンスと同等のメソッドを持つもの。
- # elems は書き出す元素の順番。
- # elems が cell の持つ元素リストとマッチしなければ
- # 例外 Poscar::ElementMismatchError を投げる。
- # io は書き出すファイルハンドル。
- def self.dump(cell, elems, io)
- unless (Mapping::map?(cell.elements.uniq, elems){ |i, j| i == j })
- raise ElementMismatchError,
- "elems [#{elems.join(",")}] mismatches to cell.elements [#{cell.elements.join(",")}."
- end
+ # POSCAR 形式で書き出す。
+ # cell は Cell クラスインスタンスと同等のメソッドを持つもの。
+ # elems は書き出す元素の順番。
+ # elems が cell の持つ元素リストとマッチしなければ
+ # 例外 Poscar::ElementMismatchError を投げる。
+ # io は書き出すファイルハンドル。
+ def self.dump(cell, elems, io)
+ unless (Mapping::map?(cell.elements.uniq, elems){ |i, j| i == j })
+ raise ElementMismatchError,
+ "elems [#{elems.join(",")}] mismatches to cell.elements [#{cell.elements.join(",")}."
+ end
- io.puts cell.comment
- io.puts "1.0" #scale
- 3.times do |i|
- io.printf( " % 18.15f % 18.15f % 18.15f\n", cell.axes[i][0], cell.axes[i][1], cell.axes[i][2]
- )
- end
+ io.puts cell.comment
+ io.puts "1.0" #scale
+ 3.times do |i|
+ io.printf( " % 18.15f % 18.15f % 18.15f\n", cell.axes[i][0], cell.axes[i][1], cell.axes[i][2]
+ )
+ end
- # collect information
- elem_list = Hash.new
- elems.each do |elem|
- elem_list[ elem ] = cell.atoms.select{ |atom| atom.element == elem }
- end
- io.puts(elems.map { |elem| elem_list[elem].size }.join(" "))
+ # collect information
+ elem_list = Hash.new
+ elems.each do |elem|
+ elem_list[ elem ] = cell.atoms.select{ |atom| atom.element == elem }
+ end
+ io.puts(elems.map { |elem| elem_list[elem].size }.join(" "))
- # Selective dynamics
- # どれか1つでも getMovableFlag が真であれば Selective dynamics をオンにする
- selective_dynamics = false
- cell.atoms.each do |atom|
- if atom.movable_flags
- selective_dynamics = true
- io.puts "Selective dynamics"
- break
- end
- end
+ # Selective dynamics
+ # どれか1つでも getMovableFlag が真であれば Selective dynamics をオンにする
+ selective_dynamics = false
+ cell.atoms.each do |atom|
+ if atom.movable_flags
+ selective_dynamics = true
+ io.puts "Selective dynamics"
+ break
+ end
+ end
- elems.each do |elem|
- elem_list[ elem ].each do |atom|
- if atom.movable_flags
- selective_dynamics = true
- break
- end
- end
- break if selective_dynamics
- end
+ elems.each do |elem|
+ elem_list[ elem ].each do |atom|
+ if atom.movable_flags
+ selective_dynamics = true
+ break
+ end
+ end
+ break if selective_dynamics
+ end
- io.puts "Direct"
+ io.puts "Direct"
- # positions of atoms
- elems.each do |elem|
- elem_list[ elem ].each do |atom|
- tmp = sprintf(
- " % 18.15f % 18.15f % 18.15f",
- * atom.position )
- if selective_dynamics
- if atom.movable_flags == nil
- tmp += " T T T"
- else
- atom.movable_flags.each do |mov|
- ( mov == true ) ? tmp += " T" : tmp += " F"
- end
- end
- end
- io.puts tmp
- end
- end
- end
+ # positions of atoms
+ elems.each do |elem|
+ elem_list[ elem ].each do |atom|
+ tmp = sprintf(
+ " % 18.15f % 18.15f % 18.15f",
+ * atom.position )
+ if selective_dynamics
+ if atom.movable_flags == nil
+ tmp += " T T T"
+ else
+ atom.movable_flags.each do |mov|
+ ( mov == true ) ? tmp += " T" : tmp += " F"
+ end
+ end
+ end
+ io.puts tmp
+ end
+ end
+ end
end