lib/vasputils/vaspdir.rb in vasputils-0.0.12 vs lib/vasputils/vaspdir.rb in vasputils-0.1.1

- old
+ new

@@ -11,206 +11,223 @@ # Class for VASP executable directory, # including input and output files. # class VaspUtils::VaspDir < Comana::ComputationManager - MACHINEFILE = "machines" + MACHINEFILE = "machines" - class InitializeError < Exception; end - class NoVaspBinaryError < Exception; end - class PrepareNextError < Exception; end - class ExecuteError < Exception; end - class InvalidValueError < Exception; end - class AlreadyExistError < Exception; end + #class InitializeError < Comana::ComputationManager::InitializeError; end + class InitializeError < StandardError; end + class NoVaspBinaryError < StandardError; end + class PrepareNextError < StandardError; end + class ExecuteError < StandardError; end + class InvalidValueError < StandardError; end + class AlreadyExistError < StandardError; end - def initialize(dir) - super(dir) - @lockdir = "lock_vaspdir" - %w(INCAR KPOINTS POSCAR POTCAR).each do |file| - infile = "#{@dir}/#{file}" - raise InitializeError, infile unless FileTest.exist? infile - end + def initialize(dir) + super(dir) + @lockdir = "lock_execute" + %w(INCAR KPOINTS POSCAR POTCAR).each do |file| + infile = "#{@dir}/#{file}" + raise InitializeError, infile unless FileTest.exist? infile end + end - # 配下の OUTCAR を Outcar インスタンスにして返す。 - # 存在しなければ例外 Errno::ENOENT を返す。 - def outcar - VaspUtils::Outcar.load_file("#{@dir}/OUTCAR") - end + # 配下の OUTCAR を Outcar インスタンスにして返す。 + # 存在しなければ例外 Errno::ENOENT を返す。 + def outcar + VaspUtils::Outcar.load_file("#{@dir}/OUTCAR") + end - # 配下の POSCAR を CrystalCell::Cell インスタンスにして返す。 - # 存在しなければ例外 Errno::ENOENT を返す。 - def poscar - VaspUtils::Poscar.load_file("#{@dir}/POSCAR") - end + # 配下の POSCAR を CrystalCell::Cell インスタンスにして返す。 + # 存在しなければ例外 Errno::ENOENT を返す。 + def poscar + VaspUtils::Poscar.load_file("#{@dir}/POSCAR") + end - # 配下の CONTCAR を CrystalCell::Cell インスタンスにして返す。 - # 存在しなければ例外 Errno::ENOENT を返す。 - def contcar - VaspUtils::Poscar.load_file("#{@dir}/CONTCAR") - end + # 配下の CONTCAR を CrystalCell::Cell インスタンスにして返す。 + # 存在しなければ例外 Errno::ENOENT を返す。 + def contcar + VaspUtils::Poscar.load_file("#{@dir}/CONTCAR") + end - # 配下の KPOINTS を読み込んだ結果をハッシュにして返す。 - # - # 存在しなければ例外 Errno::ENOENT を返す筈だが、 - # vasp dir の判定を incar でやっているので生じる筈がない。 - def incar - VaspUtils::Incar.load_file("#{@dir}/INCAR") - end + # 配下の INCAR を表現する Incar クラスインスタンスを返す。 + # 存在しなければ例外 Errno::ENOENT を返す筈だが、 + # vasp dir の判定を incar でやっているので生じる筈がない。 + def incar + VaspUtils::Incar.load_file("#{@dir}/INCAR") + end - # 配下の KPOINTS を読み込んだ結果をハッシュにして返す。 - def kpoints - VaspUtils::Kpoints.load_file("#{@dir}/KPOINTS") - end + # 配下の KPOINTS を表現する Kpoints クラスインスタンスを返す。 + def kpoints + VaspUtils::Kpoints.load_file("#{@dir}/KPOINTS") + end - # 正常に終了していれば true を返す。 - # 実行する前や実行中、OUTCAR が完遂していなければ false。 - # - # MEMO - # PI12345 ファイルは実行中のみ存在し、終了後 vasp (mpi?) に自動的に削除される。 - def finished? - begin - return VaspUtils::Outcar.load_file("#{@dir}/OUTCAR")[:normal_ended] - rescue Errno::ENOENT - return false - end - end + # 配下の vasprun.xml を表現する VasprunXml クラスインスタンスを返す。 + def vasprun_xml + VaspUtils::VasprunXml.load_file("#{@dir}/vasprun.xml") + end - def reset_init(io = $stdout) - #fullpath = File.expand_path @dir - keep_files = ["INCAR", "KPOINTS", "POSCAR", "POTCAR"] - remove_files = [] - Dir.entries( @dir ).sort.each do |file| - next if file == "." - next if file == ".." - remove_files << file unless keep_files.include? file - end - if remove_files.size == 0 - io.puts " No remove files." - return - else - #pp @dir; exit - #puts " Remove files:" - #remove_files.each { |file| puts " #{file}" } + # 正常に終了していれば true を返す。 + # 実行する前や実行中、OUTCAR が完遂していなければ false。 + # MEMO: PI12345 ファイルは実行中のみ存在し、終了後 vasp (mpi?) に自動的に削除される。 + def finished? + begin + return VaspUtils::Outcar.load_file("#{@dir}/OUTCAR")[:normal_ended] + rescue Errno::ENOENT + return false + end + end - #puts " Keep files:" - #keep_files.each { |file| puts " #{file}" } + # VASP の出力ファイルを削除する。 + #入力のみに使うもの、残す + # INCAR KPOINTS POSCAR POTCAR + #主に出力。消す。 + # CHG CHGCAR CONTCAR DOSCAR EIGENVAL EIGENVALUE ELFCAR + # EXHCAR IBZKPT LOCPOT OSZICAR OUTCAR PCDAT PRJCAR PROCAR + # PROOUT STOPCAR TMPCAR WAVECAR XDATCAR vasprun.xml + # + #付随する出力ファイル。残す。 + # machines stderr stdout + def reset_clean(io = $stdout) + remove_files = %w( + CHG CHGCAR CONTCAR DOSCAR EIGENVAL EIGENVALUE + ELFCAR EXHCAR IBZKPT LOCPOT OSZICAR OUTCAR PCDAT + PRJCAR PROCAR + PROOUT STOPCAR TMPCAR WAVECAR XDATCAR vasprun.xml + ) + remove_files.each do |file| + io.puts " Removing: #{file}" + FileUtils.rm_rf "#{@dir}/#{file}" + end + end - remove_files.each do |file| - io.puts " Removing: #{file}" - FileUtils.rm_rf "#{@dir}/#{file}" - end - end + # Delete all except for four files, INCAR, KPOINTS, POSCAR, POTCAR. + def reset_initialize(io = $stdout) + keep_files = ["INCAR", "KPOINTS", "POSCAR", "POTCAR"] + remove_files = [] + Dir.entries( @dir ).sort.each do |file| + next if file == "." + next if file == ".." + remove_files << file unless keep_files.include? file end - # 'tgt_name' is a String. - # 'conditions' is a Hash. - # E.g., {:encut => 500.0, :ka => 2, :kb => 4} - def mutate(tgt_name, condition) - raise AlreadyExistError, "Already exist: #{tgt_name}" if File.exist? tgt_name + if remove_files.size == 0 + io.puts " No remove files." + return + else + remove_files.each do |file| + io.puts " Removing: #{file}" + FileUtils.rm_rf "#{@dir}/#{file}" + end + end + end - Dir.mkdir tgt_name + # 'tgt_name' is a String. + # 'conditions' is a Hash. + # E.g., {:encut => 500.0, :ka => 2, :kb => 4} + def mutate(tgt_name, condition) + raise AlreadyExistError, "Already exist: #{tgt_name}" if File.exist? tgt_name - ##POSCAR - FileUtils.cp("#{@dir}/POSCAR", "#{tgt_name}/POSCAR") + Dir.mkdir tgt_name - ##POTCAR - FileUtils.cp("#{@dir}/POTCAR", "#{tgt_name}/POTCAR") + ##POSCAR + FileUtils.cp("#{@dir}/POSCAR", "#{tgt_name}/POSCAR") - ##INCAR - new_incar = incar - new_incar["ENCUT"] = condition[:encut] if condition[:encut] - File.open("#{tgt_name}/INCAR", "w") do |io| - VaspUtils::Incar.dump(new_incar, io) - end + ##POTCAR + FileUtils.cp("#{@dir}/POTCAR", "#{tgt_name}/POTCAR") - ##KPOINTS - new_kpoints = kpoints - new_kpoints[:mesh][0] = condition[:ka] if condition[:ka] - new_kpoints[:mesh][1] = condition[:kb] if condition[:kb] - new_kpoints[:mesh][2] = condition[:kc] if condition[:kc] - if condition[:kab] - new_kpoints[:mesh][0] = condition[:kab] - new_kpoints[:mesh][1] = condition[:kab] - end - if condition[:kbc] - new_kpoints[:mesh][1] = condition[:kbc] - new_kpoints[:mesh][2] = condition[:kbc] - end - if condition[:kca] - new_kpoints[:mesh][2] = condition[:kca] - new_kpoints[:mesh][0] = condition[:kca] - end - if condition[:kabc] - new_kpoints[:mesh][0] = condition[:kabc] - new_kpoints[:mesh][1] = condition[:kabc] - new_kpoints[:mesh][2] = condition[:kabc] - end - File.open("#{tgt_name}/KPOINTS", "w") do |io| - VaspUtils::Kpoints.dump(new_kpoints, io) - end + ##INCAR + new_incar = incar + new_incar["ENCUT"] = condition[:encut] if condition[:encut] + File.open("#{tgt_name}/INCAR", "w") do |io| + new_incar.dump(io) end - private + ##KPOINTS + new_kpoints = kpoints + new_kpoints.mesh[0] = condition[:ka] if condition[:ka] + new_kpoints.mesh[1] = condition[:kb] if condition[:kb] + new_kpoints.mesh[2] = condition[:kc] if condition[:kc] + if condition[:kab] + new_kpoints.mesh[0] = condition[:kab] + new_kpoints.mesh[1] = condition[:kab] + end + if condition[:kbc] + new_kpoints.mesh[1] = condition[:kbc] + new_kpoints.mesh[2] = condition[:kbc] + end + if condition[:kca] + new_kpoints.mesh[2] = condition[:kca] + new_kpoints.mesh[0] = condition[:kca] + end + if condition[:kabc] + new_kpoints.mesh[0] = condition[:kabc] + new_kpoints.mesh[1] = condition[:kabc] + new_kpoints.mesh[2] = condition[:kabc] + end + File.open("#{tgt_name}/KPOINTS", "w") do |io| + new_kpoints.dump(io) + end + end - # vasp を投げる。 - def calculate - #HOSTNAME is for GridEngine - hostname = (ENV["HOST"] || ENV["HOSTNAME"]).sub(/\..*$/, "") #ignore domain name + private - begin - clustersettings = Comana::ClusterSetting.load_file("#{ENV["HOME"]}/.clustersetting") - info = clustersettings.settings_host(hostname) - rescue - puts "No vasp path in #{ENV["HOME"]}/.clustersetting" - pp info - raise NoVaspBinaryError - end + # vasp を投げる。 + def calculate + #HOSTNAME is for GridEngine + hostname = (ENV["HOST"] || ENV["HOSTNAME"]).sub(/\..*$/, "") #ignore domain name - if ENV["SGE_EXECD_PIDFILE"] #grid engine 経由のとき - nslots = ENV["NSLOTS"] - lines = open(ENV["PE_HOSTFILE"], "r").readlines.collect do |line| - line =~ /^(\S+)\s+(\S+)/ - "#{$1} cpu=#{$2}" - end - generate_machinefile(lines) - else - nslots = 1 - lines = ["localhost cpu=1"] - generate_machinefile(lines) - end + begin + clustersettings = Comana::ClusterSetting.load_file("#{ENV["HOME"]}/.clustersetting") + info = clustersettings.settings_host(hostname) + rescue + puts "No vasp path in #{ENV["HOME"]}/.clustersetting" + pp info + raise NoVaspBinaryError + end - raise InvalidValueError, - "`clustersettings' is #{clustersettings.inspect}." unless clustersettings - raise InvalidValueError, "`info' is #{info.inspect}." unless info - raise InvalidValueError, "`info['mpi']' is #{info['mpi']}" unless info['mpi'] - raise InvalidValueError, "`info['vasp']' is #{info['vasp']}" unless info['vasp'] - raise InvalidValueError, "`MACHINEFILE' is #{MACHINEFILE}" unless MACHINEFILE - raise InvalidValueError, "`nslots' is #{nslots}" unless nslots - raise InvalidValueError, "`nslots' is #{nslots}" unless nslots + if ENV["SGE_EXECD_PIDFILE"] #grid engine 経由のとき + nslots = ENV["NSLOTS"] + lines = open(ENV["PE_HOSTFILE"], "r").readlines.collect do |line| + line =~ /^(\S+)\s+(\S+)/ + "#{$1} cpu=#{$2}" + end + generate_machinefile(lines) + else + nslots = 1 + lines = ["localhost cpu=1"] + generate_machinefile(lines) + end - #pp "#{info["mpi"]} -machinefile #{MACHINEFILE} -np #{nslots} #{info["vasp"]}" - command = "cd #{@dir};" - command += "#{info["mpi"]} -machinefile #{MACHINEFILE} -np #{nslots} #{info["vasp"]}" - command += "> stdout" + raise InvalidValueError, + "`clustersettings' is #{clustersettings.inspect}." unless clustersettings + raise InvalidValueError, "`info' is #{info.inspect}." unless info + raise InvalidValueError, "`info['mpi']' is #{info['mpi']}" unless info['mpi'] + raise InvalidValueError, "`info['vasp']' is #{info['vasp']}" unless info['vasp'] + raise InvalidValueError, "`MACHINEFILE' is #{MACHINEFILE}" unless MACHINEFILE + raise InvalidValueError, "`nslots' is #{nslots}" unless nslots + raise InvalidValueError, "`nslots' is #{nslots}" unless nslots - io = File.open("#{@dir}/runvasp.log", "w") - io.puts command - io.close + command = "cd #{@dir};" + command += "#{info["mpi"]} -machinefile #{MACHINEFILE} -np #{nslots} #{info["vasp"]}" + command += "| tee stdout" - end_status = system command - raise ExecuteError, "end_status is #{end_status.inspect}" unless end_status - end + io = File.open("#{@dir}/executevasp.log", "w") + io.puts command + io.close - def prepare_next - #do_nothing - raise PrepareNextError, "VaspDir doesn't need next." - end + end_status = system command + raise ExecuteError, "end_status is #{end_status.inspect}" unless end_status + end - def generate_machinefile(lines) - io = File.open("#{@dir}/#{MACHINEFILE}", "w") - io.puts lines - io.close - end + def prepare_next + raise PrepareNextError, "VaspDir doesn't need next." + end + def generate_machinefile(lines) + io = File.open("#{@dir}/#{MACHINEFILE}", "w") + io.puts lines + io.close + end end