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