From: toshinagata1964 Date: Fri, 14 Jun 2013 08:30:22 +0000 (+0000) Subject: Local execution of GAMESS is implemented X-Git-Tag: v1.0.2~277 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=87ca6c39960dccbe04a4099fab1779df1ba7865e;p=molby%2FMolby.git Local execution of GAMESS is implemented git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/molby/trunk@360 a2be9bc6-48de-4e38-9406-05402d4bc13c --- diff --git a/Scripts/gamess.rb b/Scripts/gamess.rb index fce71cb..6b8f667 100755 --- a/Scripts/gamess.rb +++ b/Scripts/gamess.rb @@ -97,6 +97,357 @@ class Molecule $gamess_basis_keys.push(basename) end end + + # Execute GAMESS (inferior copy of rungms script) + # inpname is the input file + # mol (optional) is the molecule from which the GAMESS input was built. + # If mol is specified and RUNTYP=OPTIMIZE, then the intermediate structures are + # displayed real-time. + def Molecule.execute_gamess(inpname, mol = nil) + gmsname = get_global_settings("gamess.executable_path") + gmsdir = nil + gmsvers = nil + while 1 + if gmsname == nil || !File.exist?(gmsname) + gmsname = Dialog.open_panel("Please locate the GAMESS executable") + exit if gmsname == nil + end + gmsbase = File.basename(gmsname) + gmsdir = File.dirname(gmsname) + if gmsbase =~ /gamess\.(.*)\.(exe|x)$/i + gmsvers = $1 + break + else + gmsname = nil + error_message_box(gmsbase + " does not look like a GAMESS executable!") + end + end + + inpbase = File.basename(inpname) + inpdir = File.dirname(inpname) + inpbody = inpbase.sub(/\.inp$/, "") + logbase = inpbody + ".log" + + set_global_settings("gamess.executable_path", gmsname) + + # Prepare the scratch directory in the home directory + # (Not in the document home to avoid space-containing path in Windows) + scrdir = document_home.sub(/\/My Documents/, "") + "/gamess" + n = 0 + while File.exist?(scrdir) && !File.directory?(scrdir) + if n == 0 + scrdir += ".1" + else + scrdir = scrdir.sub(".#{n}", ".#{n + 1}") + end + n += 1 + end + if !File.exist?(scrdir) + Dir.mkdir(scrdir) + end + scrdir = scrdir + "/" + inpbody + "." + $$.to_s + ".0" + n = 0 + while File.exist?(scrdir) + scrdir = scrdir.sub(".#{n}", ".#{n + 1}") + n += 1 + end + Dir.mkdir(scrdir) + + if $platform == "win" + sep = "\\" + scrdir.gsub!("/", sep) + gmsdir.gsub!("/", sep) + else + sep = "/" + end + + # Get the host name etc. + hostname = `hostname`.chomp + if $platform == "win" + freebytes = `dir #{scrdir}`.split("\n").pop.match(/([0-9,]+)[^0-9]*$/).to_a[1] + if freebytes + freebytes = (freebytes.gsub(",","").to_i / 1024).to_s + " Kbytes" + else + freebytes = "(unknown)" + end + uname = `ver`.to_s.gsub("\n", "") + else + freebytes = `df -k #{scrdir}` + uname = `uname`.chomp + end + + # Redirect standard output to the log file + logname = scrdir + sep + logbase + fpout = File.open(logname, "w") + fpout.print "----- GAMESS execution script -----\n" + fpout.print "This job is running on host #{hostname}\n" + fpout.print "under operating system #{uname} at #{Time.now.to_s}\n" + fpout.print "Available scratch disk space (Kbyte units) at beginning of the job is\n" + fpout.print freebytes + + # Copy the input file + scrprefix = scrdir + sep + inpbody + filecopy(inpname, scrprefix + ".F05") + + # Prepare environmental variables + auxdir = "#{gmsdir}#{sep}auxdata" + ENV["ERICFMT"] = "#{auxdir}#{sep}ericfmt.dat" + ENV["MCPPATH"] = "#{auxdir}#{sep}MCP" + ENV["BASPATH"] = "#{auxdir}#{sep}BASES" + ENV["QUANPOL"] = "#{auxdir}#{sep}QUANPOL" + ENV["EXTBAS"] = "/dev/null" + ENV["IRCDATA"] = "#{scrprefix}.irc" + ENV["PUNCH"] = "#{scrprefix}.dat" + ENV["INPUT"] = "#{scrprefix}.F05" + ENV["AOINTS"] = "#{scrprefix}.F08" + ENV["MOINTS"] = "#{scrprefix}.F09" + ENV["DICTNRY"] = "#{scrprefix}.F10" + ENV["DRTFILE"] = "#{scrprefix}.F11" + ENV["CIVECTR"] = "#{scrprefix}.F12" + ENV["CASINTS"] = "#{scrprefix}.F13" + ENV["CIINTS"] = "#{scrprefix}.F14" + ENV["WORK15"] = "#{scrprefix}.F15" + ENV["WORK16"] = "#{scrprefix}.F16" + ENV["CSFSAVE"] = "#{scrprefix}.F17" + ENV["FOCKDER"] = "#{scrprefix}.F18" + ENV["WORK19"] = "#{scrprefix}.F19" + ENV["DASORT"] = "#{scrprefix}.F20" + ENV["DFTINTS"] = "#{scrprefix}.F21" + ENV["DFTGRID"] = "#{scrprefix}.F22" + ENV["JKFILE"] = "#{scrprefix}.F23" + ENV["ORDINT"] = "#{scrprefix}.F24" + ENV["EFPIND"] = "#{scrprefix}.F25" + ENV["PCMDATA"] = "#{scrprefix}.F26" + ENV["PCMINTS"] = "#{scrprefix}.F27" + ENV["MLTPL"] = "#{scrprefix}.F28" + ENV["MLTPLT"] = "#{scrprefix}.F29" + ENV["DAFL30"] = "#{scrprefix}.F30" + ENV["SOINTX"] = "#{scrprefix}.F31" + ENV["SOINTY"] = "#{scrprefix}.F32" + ENV["SOINTZ"] = "#{scrprefix}.F33" + ENV["SORESC"] = "#{scrprefix}.F34" + ENV["SIMEN"] = "#{scrprefix}.simen" + ENV["SIMCOR"] = "#{scrprefix}.simcor" + ENV["GCILIST"] = "#{scrprefix}.F37" + ENV["HESSIAN"] = "#{scrprefix}.F38" + ENV["SOCCDAT"] = "#{scrprefix}.F40" + ENV["AABB41"] = "#{scrprefix}.F41" + ENV["BBAA42"] = "#{scrprefix}.F42" + ENV["BBBB43"] = "#{scrprefix}.F43" + ENV["MCQD50"] = "#{scrprefix}.F50" + ENV["MCQD51"] = "#{scrprefix}.F51" + ENV["MCQD52"] = "#{scrprefix}.F52" + ENV["MCQD53"] = "#{scrprefix}.F53" + ENV["MCQD54"] = "#{scrprefix}.F54" + ENV["MCQD55"] = "#{scrprefix}.F55" + ENV["MCQD56"] = "#{scrprefix}.F56" + ENV["MCQD57"] = "#{scrprefix}.F57" + ENV["MCQD58"] = "#{scrprefix}.F58" + ENV["MCQD59"] = "#{scrprefix}.F59" + ENV["MCQD60"] = "#{scrprefix}.F60" + ENV["MCQD61"] = "#{scrprefix}.F61" + ENV["MCQD62"] = "#{scrprefix}.F62" + ENV["MCQD63"] = "#{scrprefix}.F63" + ENV["MCQD64"] = "#{scrprefix}.F64" + ENV["NMRINT1"] = "#{scrprefix}.F61" + ENV["NMRINT2"] = "#{scrprefix}.F62" + ENV["NMRINT3"] = "#{scrprefix}.F63" + ENV["NMRINT4"] = "#{scrprefix}.F64" + ENV["NMRINT5"] = "#{scrprefix}.F65" + ENV["NMRINT6"] = "#{scrprefix}.F66" + ENV["DCPHFH2"] = "#{scrprefix}.F67" + ENV["DCPHF21"] = "#{scrprefix}.F68" + ENV["GVVPT"] = "#{scrprefix}.F69" + + # next files are used only during coupled cluster runs, so let's + # display the numerous definitions only if they are to be used. + ENV["CCREST"] = "#{scrprefix}.F70" + ENV["CCDIIS"] = "#{scrprefix}.F71" + ENV["CCINTS"] = "#{scrprefix}.F72" + ENV["CCT1AMP"] = "#{scrprefix}.F73" + ENV["CCT2AMP"] = "#{scrprefix}.F74" + ENV["CCT3AMP"] = "#{scrprefix}.F75" + ENV["CCVM"] = "#{scrprefix}.F76" + ENV["CCVE"] = "#{scrprefix}.F77" + ENV["EOMSTAR"] = "#{scrprefix}.F80" + ENV["EOMVEC1"] = "#{scrprefix}.F81" + ENV["EOMVEC2"] = "#{scrprefix}.F82" + ENV["EOMHC1"] = "#{scrprefix}.F83" + ENV["EOMHC2"] = "#{scrprefix}.F84" + ENV["EOMHHHH"] = "#{scrprefix}.F85" + ENV["EOMPPPP"] = "#{scrprefix}.F86" + ENV["EOMRAMP"] = "#{scrprefix}.F87" + ENV["EOMRTMP"] = "#{scrprefix}.F88" + ENV["EOMDG12"] = "#{scrprefix}.F89" + ENV["MMPP"] = "#{scrprefix}.F90" + ENV["MMHPP"] = "#{scrprefix}.F91" + ENV["MMCIVEC"] = "#{scrprefix}.F92" + ENV["MMCIVC1"] = "#{scrprefix}.F93" + ENV["MMCIITR"] = "#{scrprefix}.F94" + ENV["MMNEXM"] = "#{scrprefix}.F95" + ENV["MMNEXE"] = "#{scrprefix}.F96" + ENV["MMNREXM"] = "#{scrprefix}.F97" + ENV["MMNREXE"] = "#{scrprefix}.F98 " + # + # next are for TDHFX code, not used by current GAMESS + # + ENV["OLI201"] = "#{scrprefix}.F201" + ENV["OLI202"] = "#{scrprefix}.F202" + ENV["OLI203"] = "#{scrprefix}.F203" + ENV["OLI204"] = "#{scrprefix}.F204" + ENV["OLI205"] = "#{scrprefix}.F205" + ENV["OLI206"] = "#{scrprefix}.F206" + ENV["OLI207"] = "#{scrprefix}.F207" + ENV["OLI208"] = "#{scrprefix}.F208" + ENV["OLI209"] = "#{scrprefix}.F209" + ENV["OLI210"] = "#{scrprefix}.F210" + ENV["OLI211"] = "#{scrprefix}.F211" + ENV["OLI212"] = "#{scrprefix}.F212" + ENV["OLI213"] = "#{scrprefix}.F213" + ENV["OLI214"] = "#{scrprefix}.F214" + ENV["OLI215"] = "#{scrprefix}.F215" + ENV["OLI216"] = "#{scrprefix}.F216" + ENV["OLI217"] = "#{scrprefix}.F217" + ENV["OLI218"] = "#{scrprefix}.F218" + ENV["OLI219"] = "#{scrprefix}.F219" + ENV["OLI220"] = "#{scrprefix}.F220" + ENV["OLI221"] = "#{scrprefix}.F221" + ENV["OLI222"] = "#{scrprefix}.F222" + ENV["OLI223"] = "#{scrprefix}.F223" + ENV["OLI224"] = "#{scrprefix}.F224" + ENV["OLI225"] = "#{scrprefix}.F225" + ENV["OLI226"] = "#{scrprefix}.F226" + ENV["OLI227"] = "#{scrprefix}.F227" + ENV["OLI228"] = "#{scrprefix}.F228" + ENV["OLI229"] = "#{scrprefix}.F229" + ENV["OLI230"] = "#{scrprefix}.F230" + ENV["OLI231"] = "#{scrprefix}.F231" + ENV["OLI232"] = "#{scrprefix}.F232" + ENV["OLI233"] = "#{scrprefix}.F233" + ENV["OLI234"] = "#{scrprefix}.F234" + ENV["OLI235"] = "#{scrprefix}.F235" + ENV["OLI236"] = "#{scrprefix}.F236" + ENV["OLI237"] = "#{scrprefix}.F237" + ENV["OLI238"] = "#{scrprefix}.F238" + ENV["OLI239"] = "#{scrprefix}.F239" + + if $platform == "win" + fpout.print "Microsoft MPI will be running GAMESS on 1 node.\n" + fpout.print "The binary kicked off by 'mpiexec' is gamess.#{gmsvers}.exe\n" + fpout.print "MS-MPI will run 1 compute process\n" + # File containing environmental variables + envfil = "#{scrprefix}.GMS.ENV" + fp = File.open(envfil, "w") + ENV.each { |k, v| fp.print "#{k}=#{v}\n" } + fp.close + # File containing arguments to mpiexec + procfil = "#{scrprefix}.processes.mpd" + fp = File.open(procfil, "w") + fp.print "-env ENVFIL #{envfil} -n 2 #{gmsdir}#{sep}gamess.#{gmsvers}.exe\n" + fp.close + end + + fpout.close + fplog = File.open(logname, "r") + size = 0 + lines = [] + last_line = "" + + # Callback proc + callback = proc { + fplog.seek(0, IO::SEEK_END) + sizec = fplog.tell + if sizec > size + # Read new lines + fplog.seek(size, IO::SEEK_SET) + fplog.each_line { |line| + if line[-1, 1] == "\n" + lines.push(last_line + line) + last_line = "" + else + last_line += line + break + end + } + size = fplog.tell + last_i = nil + i = 0 + nserch = -1 + while i < lines.count + line = lines[i] + if line =~ /GEOMETRY SEARCH POINT NSERCH= *(\d+)/ + nserch = $1.to_i + last_i = i + elsif line =~ /NSERCH:/ + print line + if mol + dummy, n, grad = line.match(/NSERCH:[^0-9]*([0-9]+).*GRAD[^0-9]*([-.0-9]+)/).to_a + mol.show_text("Search: #{n}\nGradient: #{grad}") + end + elsif nserch > 0 && line =~ /ddikick\.x/ + last_i = -1 + break + elsif mol && nserch > 0 && line =~ /COORDINATES OF ALL ATOMS/ + # There should be (natoms + 2) lines + if i + mol.natoms + 3 <= lines.count + coords = [] + (i + 3...i + 3 + mol.natoms).each { |j| + name, charge, x, y, z = lines[j].split + coords.push(Vector3D[x.to_f, y.to_f, z.to_f]) + } + mol.create_frame([coords]) + mol.display + last_i = i + mol.natoms + 2 + i = last_i # Skip the processed lines + end + end + i += 1 + end + if last_i == -1 + lines.clear + break + elsif last_i + lines[0..last_i] = nil + end + end + true + } + + show_console_window + if mol + mol.make_front + end + + if $platform == "win" + status = call_subprocess("cmd.exe /c \"mpiexec -configfile #{procfil} >>#{logname}\"", "GAMESS") + else + status = call_subprocess("/bin/sh -c '#{gmsdir}/ddikick.x #{gmsdir}/gamess.#{gmsvers}.x #{inpbody} -ddi 1 1 localhost -scr #{scrdir} < /dev/null >>#{logname}'", "GAMESS", callback) + end + + if status != 0 + if status == -1 + error_message_box("GAMESS failed to start. Please examine GAMESS installation.") + exit + elsif status == -2 + error_message_box("GAMESS execution interrupted.") + else + error_message_box("GAMESS failed with exit status #{status}.") + end + end + + ext_to_keep = [".dat", ".rst", ".trj", ".efp", ".gamma", ".log"] + ext_to_keep.each { |ex| + if File.exists?("#{scrprefix}#{ex}") + filecopy("#{scrprefix}#{ex}", "#{inpdir}#{sep}#{inpbody}#{ex}") + end + } + Dir.foreach(scrdir) { |file| + if file != "." && file != ".." && !ext_to_keep.include?(File.extname(file)) + File.delete("#{scrdir}#{sep}#{file}") + end + } + + end def export_gamess(fname, hash) @@ -338,7 +689,7 @@ class Molecule defaults = {"scftype"=>0, "runtype"=>0, "charge"=>"0", "mult"=>"1", "basis"=>4, "use_secondary_basis"=>0, "secondary_elements"=>"", - "secondary_basis"=>8, "esp"=>0} + "secondary_basis"=>8, "esp"=>0, "ncpus"=>"1"} hash = Dialog.run("GAMESS Export") { def load_basis_set_sub(item) @@ -354,6 +705,19 @@ class Molecule set_attr("secondary_basis", :value=>sel2) end end + def select_gamess_path(item) + while 1 + fname = Dialog.open_panel("Locate GAMESS executable:") + return if fname == nil + bname = File.basename(fname) + if bname =~ /gamess\.(.*)\.(exe|x)$/i + set_attr("executable_path", :value=>fname) + return + else + error_message_box("\"#{bname}\" does not look like a GAMESS executable! Please try again.") + end + end + end layout(4, item(:text, :title=>"SCF type"), item(:popup, :subitems=>["RHF", "ROHF", "UHF"], :tag=>"scftype"), @@ -406,6 +770,30 @@ class Molecule -1, -1, -1, item(:line), + -1, -1, -1, + + item(:checkbox, :title=>"Execute GAMESS on this machine", :tag=>"execute_local", + :action=>proc { |it| + flag = (it[:value] != 0) + set_attr("executable_path", :enabled=>flag) + set_attr("select_path", :enabled=>flag) + set_attr("ncpus", :enabled=>flag) + }), + -1, -1, -1, + + item(:text, :title=>" Path"), + item(:textfield, :width=>300, :tag=>"executable_path"), + -1, -1, + + -1, + item(:button, :title=>"Select Path...", :tag=>"select_path", :action=>:select_gamess_path), + -1, -1, + + item(:text, :title=>" N of CPUs"), + item(:textfield, :width=>80, :tag=>"ncpus"), + -1, -1, + + item(:line), -1, -1, -1 ) values = Hash.new @@ -420,6 +808,9 @@ class Molecule set_attr("secondary_basis", :enabled=>(values["use_secondary_basis"] == 1)) set_attr("dfttype", :enabled=>(values["dft"] == 1)) set_attr("use_internal", :enabled=>(values["runtype"] == 2)) + set_attr("executable_path", :enabled=>(values["execute_local"] == 1)) + set_attr("select_path", :enabled=>(values["execute_local"] == 1)) + set_attr("ncpus", :enabled=>(values["execute_local"] == 1)) } hash.each_pair { |key, value| next if key == :status @@ -431,9 +822,12 @@ class Molecule hash["secondary_basis"] = $gamess_basis_keys[hash["secondary_basis"]] hash["dfttype"] = dft_internal[hash["dfttype"]] basename = (self.path ? File.basename(self.path, ".*") : self.name) - fname = Dialog.save_panel("GAMESS input file name", self.dir, basename + ".inp", "GAMESS input file (*.inp)|*.inp|All files|*.*") + fname = Dialog.save_panel("Export GAMESS input file:", self.dir, basename + ".inp", "GAMESS input file (*.inp)|*.inp|All files|*.*") return nil if !fname export_gamess(fname, hash) + if hash["execute_local"] == 1 + Molecule.execute_gamess(fname, self) + end else nil end