4 # Created by Toshi Nagata on 2009/11/22.
5 # Copyright 2009 Toshi Nagata. All rights reserved.
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation version 2 of the License.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
18 def Molecule.read_gamess_basis_sets(fname)
19 # $gamess_basis = Hash.new unless $gamess_basis
20 $gamess_ecp = Hash.new unless $gamess_ecp
21 # $gamess_basis_desc = Hash.new unless $gamess_basis_desc
22 # $gamess_basis_keys = [] unless $gamess_basis_keys
23 basename = File.basename(fname, ".*")
26 File.open(fname, "r") { |fp|
28 if s =~ /^\s*!\s*/ && descname == nil
29 # Get the descriptive name from the first comment line
30 s = Regexp.last_match.post_match
32 descname = Regexp.last_match.pre_match
34 descname = (s.split)[0]
36 $gamess_basis_desc[basename] = descname
39 ss, bas = (s.split)[0..1] # Tokens delimited by whitespaces
40 next if ss == nil || ss == ""
42 # Read the ECP section
43 ecp = $gamess_ecp[basename]
46 $gamess_ecp[basename] = ecp
48 keys << basename unless keys.include?(basename)
51 ary = s.split # (PNAME, PTYPE, IZCORE, LMAX+1)
52 elem = ary[0].match(/\w{1,2}/).to_a[0] # ary[0] should begin with an element name
53 ap = Parameter.builtin.elements.find { |p| p.name.casecmp(elem) == 0 }
54 raise MolbyError, "the ECP definition does not begin with an element name: #{s}" if !ap
57 (0..Integer(ary[3])).each {
59 raise MolbyError, "the ECP definition ends unexpectedly at line #{ln} for: #{s}" if !s
61 ary = s.split # (NGPOT, comment)
63 (1..Integer(ary[0])).each {
65 raise MolbyError, "the ECP definition ends unexpectedly at line #{ln} for: #{s}" if !s
70 ecp[ap.index] = ecpdef
73 # Comments or other unrecognizable lines
75 elsif (ap = Parameter.builtin.elements.find { |p| p.name.casecmp(ss) == 0 || p.fullname.casecmp(ss) == 0 })
76 # Valid basis definition
77 if bas == nil || bas =~ /\W/
80 basis = $gamess_basis[bas]
83 $gamess_basis[bas] = basis
85 keys << bas unless keys.include?(bas)
87 while (s = fp.gets) && s =~ /\S/
90 basis[ap.index] = basdef
92 raise MolbyError, "ss is not a valid element symbol or name: #{s}"
96 unless $gamess_basis_keys.include?(basename)
97 $gamess_basis_keys.push(basename)
101 # Execute GAMESS (inferior copy of rungms script)
102 # inpname is the input file
103 # mol (optional) is the molecule from which the GAMESS input was built.
104 # If mol is specified and RUNTYP=OPTIMIZE, then the intermediate structures are
105 # displayed real-time.
106 def Molecule.execute_gamess(inpname, mol = nil)
107 gmsname = get_global_settings("gamess.executable_path")
111 if gmsname == nil || !File.exist?(gmsname)
112 gmsname = Dialog.open_panel("Please locate the GAMESS executable")
113 exit if gmsname == nil
115 gmsbase = File.basename(gmsname)
116 gmsdir = File.dirname(gmsname)
117 if gmsbase =~ /gamess\.(.*)\.(exe|x)$/i
122 error_message_box(gmsbase + " does not look like a GAMESS executable!")
127 mol = Molecule.open(inpname)
129 error_message_box("Cannot open #{inpname} as GAMESS input")
134 inpbase = File.basename(inpname)
135 inpdir = File.dirname(inpname)
136 inpbody = inpbase.sub(/\.inp$/, "")
137 logbase = inpbody + ".log"
139 set_global_settings("gamess.executable_path", gmsname)
141 ncpus = get_global_settings("gamess.ncpus").to_i
146 # Prepare the scratch directory in the home directory
147 # (Not in the document home to avoid space-containing path in Windows)
148 scrdir = $home_directory + "/molby/gamess"
150 mkdir_recursive(scrdir)
152 error_message_box("Cannot create directory #{scrdir}: " + $!.to_s)
156 scrdir = scrdir + "/" + inpbody + "." + $$.to_s + ".0"
158 while File.exist?(scrdir)
159 scrdir = scrdir.sub(".#{n}", ".#{n + 1}")
164 if $platform == "win"
166 scrdir.gsub!("/", sep)
167 gmsdir.gsub!("/", sep)
172 # Get the host name etc.
173 hostname = backquote("hostname").chomp
174 if $platform == "win"
175 s = backquote("cmd.exe /c dir #{scrdir}")
176 freebytes = s.split("\n").pop.match(/([0-9,]+)[^0-9]*$/).to_a[1]
178 freebytes = (freebytes.gsub(",","").to_i / 1024).to_s + " Kbytes"
180 freebytes = "(unknown)"
182 uname = backquote("cmd.exe /c ver").to_s.gsub("\n", "")
184 freebytes = `df -k #{scrdir}`
185 uname = `uname`.chomp
188 # Redirect standard output to the log file
189 logname = scrdir + sep + logbase
190 fpout = File.open(logname, "w")
191 fpout.print "----- GAMESS execution script -----\n"
192 fpout.print "This job is running on host #{hostname}\n"
193 fpout.print "under operating system #{uname} at #{Time.now.to_s}\n"
194 fpout.print "Available scratch disk space (Kbyte units) at beginning of the job is\n"
195 fpout.print freebytes
197 # Copy the input file
198 scrprefix = scrdir + sep + inpbody
199 filecopy(inpname, scrprefix + ".F05")
201 # Prepare environmental variables
202 auxdir = "#{gmsdir}#{sep}auxdata"
203 ENV["ERICFMT"] = "#{auxdir}#{sep}ericfmt.dat"
204 ENV["MCPPATH"] = "#{auxdir}#{sep}MCP"
205 ENV["BASPATH"] = "#{auxdir}#{sep}BASES"
206 ENV["QUANPOL"] = "#{auxdir}#{sep}QUANPOL"
207 ENV["EXTBAS"] = "/dev/null"
208 ENV["IRCDATA"] = "#{scrprefix}.irc"
209 ENV["PUNCH"] = "#{scrprefix}.dat"
210 ENV["INPUT"] = "#{scrprefix}.F05"
211 ENV["AOINTS"] = "#{scrprefix}.F08"
212 ENV["MOINTS"] = "#{scrprefix}.F09"
213 ENV["DICTNRY"] = "#{scrprefix}.F10"
214 ENV["DRTFILE"] = "#{scrprefix}.F11"
215 ENV["CIVECTR"] = "#{scrprefix}.F12"
216 ENV["CASINTS"] = "#{scrprefix}.F13"
217 ENV["CIINTS"] = "#{scrprefix}.F14"
218 ENV["WORK15"] = "#{scrprefix}.F15"
219 ENV["WORK16"] = "#{scrprefix}.F16"
220 ENV["CSFSAVE"] = "#{scrprefix}.F17"
221 ENV["FOCKDER"] = "#{scrprefix}.F18"
222 ENV["WORK19"] = "#{scrprefix}.F19"
223 ENV["DASORT"] = "#{scrprefix}.F20"
224 ENV["DFTINTS"] = "#{scrprefix}.F21"
225 ENV["DFTGRID"] = "#{scrprefix}.F22"
226 ENV["JKFILE"] = "#{scrprefix}.F23"
227 ENV["ORDINT"] = "#{scrprefix}.F24"
228 ENV["EFPIND"] = "#{scrprefix}.F25"
229 ENV["PCMDATA"] = "#{scrprefix}.F26"
230 ENV["PCMINTS"] = "#{scrprefix}.F27"
231 ENV["MLTPL"] = "#{scrprefix}.F28"
232 ENV["MLTPLT"] = "#{scrprefix}.F29"
233 ENV["DAFL30"] = "#{scrprefix}.F30"
234 ENV["SOINTX"] = "#{scrprefix}.F31"
235 ENV["SOINTY"] = "#{scrprefix}.F32"
236 ENV["SOINTZ"] = "#{scrprefix}.F33"
237 ENV["SORESC"] = "#{scrprefix}.F34"
238 ENV["SIMEN"] = "#{scrprefix}.simen"
239 ENV["SIMCOR"] = "#{scrprefix}.simcor"
240 ENV["GCILIST"] = "#{scrprefix}.F37"
241 ENV["HESSIAN"] = "#{scrprefix}.F38"
242 ENV["SOCCDAT"] = "#{scrprefix}.F40"
243 ENV["AABB41"] = "#{scrprefix}.F41"
244 ENV["BBAA42"] = "#{scrprefix}.F42"
245 ENV["BBBB43"] = "#{scrprefix}.F43"
246 ENV["MCQD50"] = "#{scrprefix}.F50"
247 ENV["MCQD51"] = "#{scrprefix}.F51"
248 ENV["MCQD52"] = "#{scrprefix}.F52"
249 ENV["MCQD53"] = "#{scrprefix}.F53"
250 ENV["MCQD54"] = "#{scrprefix}.F54"
251 ENV["MCQD55"] = "#{scrprefix}.F55"
252 ENV["MCQD56"] = "#{scrprefix}.F56"
253 ENV["MCQD57"] = "#{scrprefix}.F57"
254 ENV["MCQD58"] = "#{scrprefix}.F58"
255 ENV["MCQD59"] = "#{scrprefix}.F59"
256 ENV["MCQD60"] = "#{scrprefix}.F60"
257 ENV["MCQD61"] = "#{scrprefix}.F61"
258 ENV["MCQD62"] = "#{scrprefix}.F62"
259 ENV["MCQD63"] = "#{scrprefix}.F63"
260 ENV["MCQD64"] = "#{scrprefix}.F64"
261 ENV["NMRINT1"] = "#{scrprefix}.F61"
262 ENV["NMRINT2"] = "#{scrprefix}.F62"
263 ENV["NMRINT3"] = "#{scrprefix}.F63"
264 ENV["NMRINT4"] = "#{scrprefix}.F64"
265 ENV["NMRINT5"] = "#{scrprefix}.F65"
266 ENV["NMRINT6"] = "#{scrprefix}.F66"
267 ENV["DCPHFH2"] = "#{scrprefix}.F67"
268 ENV["DCPHF21"] = "#{scrprefix}.F68"
269 ENV["GVVPT"] = "#{scrprefix}.F69"
271 # next files are used only during coupled cluster runs, so let's
272 # display the numerous definitions only if they are to be used.
273 ENV["CCREST"] = "#{scrprefix}.F70"
274 ENV["CCDIIS"] = "#{scrprefix}.F71"
275 ENV["CCINTS"] = "#{scrprefix}.F72"
276 ENV["CCT1AMP"] = "#{scrprefix}.F73"
277 ENV["CCT2AMP"] = "#{scrprefix}.F74"
278 ENV["CCT3AMP"] = "#{scrprefix}.F75"
279 ENV["CCVM"] = "#{scrprefix}.F76"
280 ENV["CCVE"] = "#{scrprefix}.F77"
281 ENV["EOMSTAR"] = "#{scrprefix}.F80"
282 ENV["EOMVEC1"] = "#{scrprefix}.F81"
283 ENV["EOMVEC2"] = "#{scrprefix}.F82"
284 ENV["EOMHC1"] = "#{scrprefix}.F83"
285 ENV["EOMHC2"] = "#{scrprefix}.F84"
286 ENV["EOMHHHH"] = "#{scrprefix}.F85"
287 ENV["EOMPPPP"] = "#{scrprefix}.F86"
288 ENV["EOMRAMP"] = "#{scrprefix}.F87"
289 ENV["EOMRTMP"] = "#{scrprefix}.F88"
290 ENV["EOMDG12"] = "#{scrprefix}.F89"
291 ENV["MMPP"] = "#{scrprefix}.F90"
292 ENV["MMHPP"] = "#{scrprefix}.F91"
293 ENV["MMCIVEC"] = "#{scrprefix}.F92"
294 ENV["MMCIVC1"] = "#{scrprefix}.F93"
295 ENV["MMCIITR"] = "#{scrprefix}.F94"
296 ENV["MMNEXM"] = "#{scrprefix}.F95"
297 ENV["MMNEXE"] = "#{scrprefix}.F96"
298 ENV["MMNREXM"] = "#{scrprefix}.F97"
299 ENV["MMNREXE"] = "#{scrprefix}.F98 "
301 # next are for TDHFX code, not used by current GAMESS
303 ENV["OLI201"] = "#{scrprefix}.F201"
304 ENV["OLI202"] = "#{scrprefix}.F202"
305 ENV["OLI203"] = "#{scrprefix}.F203"
306 ENV["OLI204"] = "#{scrprefix}.F204"
307 ENV["OLI205"] = "#{scrprefix}.F205"
308 ENV["OLI206"] = "#{scrprefix}.F206"
309 ENV["OLI207"] = "#{scrprefix}.F207"
310 ENV["OLI208"] = "#{scrprefix}.F208"
311 ENV["OLI209"] = "#{scrprefix}.F209"
312 ENV["OLI210"] = "#{scrprefix}.F210"
313 ENV["OLI211"] = "#{scrprefix}.F211"
314 ENV["OLI212"] = "#{scrprefix}.F212"
315 ENV["OLI213"] = "#{scrprefix}.F213"
316 ENV["OLI214"] = "#{scrprefix}.F214"
317 ENV["OLI215"] = "#{scrprefix}.F215"
318 ENV["OLI216"] = "#{scrprefix}.F216"
319 ENV["OLI217"] = "#{scrprefix}.F217"
320 ENV["OLI218"] = "#{scrprefix}.F218"
321 ENV["OLI219"] = "#{scrprefix}.F219"
322 ENV["OLI220"] = "#{scrprefix}.F220"
323 ENV["OLI221"] = "#{scrprefix}.F221"
324 ENV["OLI222"] = "#{scrprefix}.F222"
325 ENV["OLI223"] = "#{scrprefix}.F223"
326 ENV["OLI224"] = "#{scrprefix}.F224"
327 ENV["OLI225"] = "#{scrprefix}.F225"
328 ENV["OLI226"] = "#{scrprefix}.F226"
329 ENV["OLI227"] = "#{scrprefix}.F227"
330 ENV["OLI228"] = "#{scrprefix}.F228"
331 ENV["OLI229"] = "#{scrprefix}.F229"
332 ENV["OLI230"] = "#{scrprefix}.F230"
333 ENV["OLI231"] = "#{scrprefix}.F231"
334 ENV["OLI232"] = "#{scrprefix}.F232"
335 ENV["OLI233"] = "#{scrprefix}.F233"
336 ENV["OLI234"] = "#{scrprefix}.F234"
337 ENV["OLI235"] = "#{scrprefix}.F235"
338 ENV["OLI236"] = "#{scrprefix}.F236"
339 ENV["OLI237"] = "#{scrprefix}.F237"
340 ENV["OLI238"] = "#{scrprefix}.F238"
341 ENV["OLI239"] = "#{scrprefix}.F239"
343 if $platform == "win"
347 fpout.print "Microsoft MPI will be running GAMESS on 1 node.\n"
348 fpout.print "The binary kicked off by 'mpiexec' is gamess.#{gmsvers}.exe\n"
349 fpout.print "MS-MPI will run #{ncpus} compute process\n"
350 # File containing environmental variables
351 envfil = "#{scrprefix}.GMS.ENV"
352 fp = File.open(envfil, "w")
353 ENV.each { |k, v| fp.print "#{k}=#{v}\n" }
355 # File containing arguments to mpiexec
356 procfil = "#{scrprefix}.processes.mpd"
357 fp = File.open(procfil, "w")
358 fp.print "-env ENVFIL #{envfil} -n #{ncpus} #{gmsdir}#{sep}gamess.#{gmsvers}.exe\n"
363 fplog = File.open(logname, "r")
369 term_callback = lambda { |m, n|
370 msg = "GAMESS execution on #{inpbase} "
377 msg += "failed with status #{n}."
381 msg += "\n(In directory #{inpdir})"
382 ext_to_keep = [".dat", ".rst", ".trj", ".efp", ".gamma", ".log"]
383 ext_to_keep.each { |ex|
384 if File.exists?("#{scrprefix}#{ex}")
385 filecopy("#{scrprefix}#{ex}", "#{inpdir}#{sep}#{inpbody}#{ex}")
388 Dir.foreach(scrdir) { |file|
389 if file != "." && file != ".." && !ext_to_keep.include?(File.extname(file))
390 File.delete("#{scrdir}#{sep}#{file}")
393 erase_old_logs(scrdir, "latest", 5)
394 message_box(msg, hmsg, :ok, icon)
397 timer_callback = lambda { |m, n|
398 fplog.seek(0, IO::SEEK_END)
402 fplog.seek(size, IO::SEEK_SET)
403 fplog.each_line { |line|
404 if line[-1, 1] == "\n"
405 lines.push(last_line + line)
416 while i < lines.count
418 if line =~ /GEOMETRY SEARCH POINT NSERCH= *(\d+)/
421 elsif line =~ /NSERCH:/
424 dummy, n, grad = line.match(/NSERCH:[^0-9]*([0-9]+).*GRAD[^0-9]*([-.0-9]+)/).to_a
425 mol.show_text("Search: #{n}\nGradient: #{grad}")
428 elsif nserch > 0 && line =~ /ddikick\.x/
431 elsif mol && nserch > 0 && line =~ /COORDINATES OF ALL ATOMS/
432 # There should be (natoms + 2) lines
433 if i + mol.natoms + 3 <= lines.count
435 (i + 3...i + 3 + mol.natoms).each { |j|
436 name, charge, x, y, z = lines[j].split
437 coords.push(Vector3D[x.to_f, y.to_f, z.to_f])
439 mol.create_frame([coords])
441 last_i = i + mol.natoms + 2
442 i = last_i # Skip the processed lines
451 lines[0..last_i] = nil
457 if $platform == "win"
458 cmdline = "cmd.exe /c \"mpiexec -configfile #{procfil} >>#{logname}\""
460 hosts = "localhost " * ncpus
461 cmdline = "/bin/sh -c '#{gmsdir}/ddikick.x #{gmsdir}/gamess.#{gmsvers}.x #{inpbody} -ddi #{ncpus} #{ncpus} #{hosts} -scr #{scrdir} < /dev/null >>#{logname}'"
465 pid = mol.call_subprocess_async(cmdline, term_callback, timer_callback)
467 error_message_box("GAMESS failed to start. Please examine GAMESS installation.")
471 pid = call_subprocess(cmdline, "Running GAMESS")
472 term_callback(nil, pid)
477 def export_gamess(fname, hash)
479 def reorder_array(ary, ordered_sub_ary)
480 return ordered_sub_ary + (ary - ordered_sub_ary)
484 basename = File.basename(fname, ".*")
487 icharg = hash["charge"]
489 runtyp = ["ENERGY", "PROP", "OPTIMIZE"][Integer(hash["runtype"])]
490 scftyp = ["RHF", "ROHF", "UHF"][Integer(hash["scftype"])]
491 bssname = hash["basis"]
492 bssname2 = hash["secondary_basis"]
493 if hash["use_secondary_basis"] != 0 && bssname2 != bssname
495 element2 = hash["secondary_elements"].split(/[\s,]+/).map { |name| name.capitalize }
500 basis = $gamess_basis[bssname]
501 basis2 = $gamess_basis[bssname2]
503 raise MolbyError, "Unknown basis set name??? \"#{bssname}\" or \"#{bssname2}\""
506 # Use effective core potentials?
507 ecp = $gamess_ecp[bssname]
508 ecp2 = $gamess_ecp[bssname2]
509 ecp_read = (ecp || ecp2 ? "ECP=READ " : "")
511 # Use only one built-in basis set?
516 gbasis = "PM3 NGAUSS=3"
518 gbasis = "STO NGAUSS=3"
520 gbasis = "N21 NGAUSS=3"
522 gbasis = "N31 NGAUSS=6"
524 gbasis = "N31 NGAUSS=6 NDFUNC=1"
526 gbasis = "N31 NGAUSS=6 NDFUNC=1 NPFUNC=1"
528 gbasis = "N311 NGAUSS=6"
530 gbasis = "N311 NGAUSS=6 NDFUNC=1 NPFUNC=1"
534 # Count non-dummy atoms
537 natoms += 1 if ap.atomic_number != 0
540 # Fill hash with default values
541 h = (hash["CONTRL"] ||= Hash.new)
542 h["COORD"] ||= "UNIQUE"
543 h["EXETYP"] ||= "RUN"
544 h["ICHARG"] ||= icharg.to_s
546 h["INTTYP"] ||= "HONDO"
549 h["MOLPLT"] ||= ".T."
551 h["MULT"] ||= mult.to_s
552 h["QMTTOL"] ||= "1e-08"
553 h["RUNTYP"] ||= runtyp
555 h["DFTTYP"] ||= hash["dfttype"]
557 if hash["use_internal"] != 0 && (hash["runtype"] == 2 || h["RUNTYP"] == "OPTIMIZE")
558 nzvar = natoms * 3 - 6 # TODO: 3N-5 for linear molecules
559 h["NZVAR"] = nzvar.to_s
563 h["SCFTYP"] ||= scftyp
569 h = (hash["SCF"] ||= Hash.new)
570 h["CONV"] ||= "1.0E-06"
571 h["DIRSCF"] ||= ".T."
575 h = (hash["STATPT"] ||= Hash.new)
577 h["OPTTOL"] ||= "1.0E-06"
579 h = (hash["SYSTEM"] ||= Hash.new)
582 h["TIMLIM"] ||= "50000"
584 h = (hash["GUESS"] ||= Hash.new)
585 h["GUESS"] ||= "HUCKEL"
588 h = (hash["BASIS"] ||= Hash.new)
589 h["GBASIS"] ||= gbasis
593 h = (hash["ZMAT"] ||= Hash.new)
599 h = (hash["ELPOT"] ||= Hash.new)
601 h["OUTPUT"] ||= "PUNCH"
603 h = (hash["PDC"] ||= Hash.new)
604 h["CONSTR"] ||= "NONE"
605 h["PTSEL"] ||= "CONNOLLY"
608 File.open(fname, "wb") { |fp|
609 fp.print "! GAMESS input\n"
610 fp.print "! Generated by Molby at #{now}\n"
611 fp.print "! Basis set: " + $gamess_basis_desc[bssname] + "\n"
613 fp.print "! [" + element2.join(", ") + "]: " + $gamess_basis_desc[bssname2] + "\n"
615 controls = reorder_array(hash.keys.select { |k| hash[k].is_a?(Hash) },
616 ["CONTRL", "SCF", "STATPT", "SYSTEM", "GUESS", "BASIS", "ZMAT", "ELPOT", "PDC"])
619 next if h == nil || h.size == 0
621 ordered = ["COORD", "EXETYP", "ICHARG", "ICUT", "INTTYP", "ITOL", "MAXIT", "MOLPLT", "MPLEVL",
622 "MULT", "QMTTOL", "RUNTYP", "SCFTYP", "ECP", "UNITS", "DFTTYP", "NZVAR"]
624 ordered = ["CONV", "DIRSCF", "FDIFF", "DAMP"]
626 ordered = ["NSTEP", "OPTTOL"]
628 ordered = ["MEMDDI", "MWORDS", "TIMLIM"]
634 ordered = ["DLC", "AUTO"]
636 ordered = ["IEPOT", "OUTPUT", "WHERE"]
638 ordered = ["CONSTR", "PTSEL"]
642 keys = reorder_array(h.keys, ordered)
644 keys.each_with_index { |kk, i|
646 next if v == nil || v == ""
648 fp.printf " $%-6s", k
652 fp.printf " %s=%s", kk, h[kk].to_s
659 fp.print " $DATA\n#{basename}\nC1 0\n"
662 next if ap.atomic_number == 0
663 fp.printf "%-6s %4d %10.6f %10.6f %10.6f\n", ap.name, ap.atomic_number, ap.r.x, ap.r.y, ap.r.z
664 if use_2nd && element2.include?(ap.element)
665 secondary[ap.index] = true
668 # Basis specification followed by a blank line
669 bas = (secondary[ap.index] ? basis2 : basis)
671 bas = bas[ap.atomic_number]
674 raise MolbyError, "Basis set is not defined for atom #{ap.index}, element #{ap.element}"
685 an = ap.atomic_number
687 ecpp = (secondary[ap.index] ? ecp2 : ecp)
688 e = ecp_ary[an] || (ecpp && ecpp[an])
690 # Cache the PNAME of the $ECP entry and re-use it
691 ecp_ary[an] ||= (e.split)[0] + "\n"
693 e = ap.element.upcase + "-ECP NONE\n"
703 def cmd_create_gamess_input
706 raise MolbyError, "cannot create GAMESS input; the molecule is empty"
709 # Descriptive text and internal string for popup menus
710 # bset_desc = ["PM3", "STO-3G", "3-21G", "6-31G", "6-31G(d)", "6-31G(d,p)", "6-311G", "6-311G(d,p)", "LanL2DZ"]
711 # bset_internal = ["PM3", "STO3G", "321G", "631G", "631Gd", "631Gdp", "6311G", "6311Gdp", "LanL2DZ"]
712 bset_desc = $gamess_basis_keys.map { |key| $gamess_basis_desc[key] }
714 dft_internal = ["B3LYP"]
716 defaults = {"scftype"=>0, "runtype"=>0, "charge"=>"0", "mult"=>"1",
717 "basis"=>4, "use_secondary_basis"=>0, "secondary_elements"=>"",
718 "secondary_basis"=>8, "esp"=>0, "ncpus"=>"1"}
720 hash = Dialog.run("GAMESS Export") {
721 def load_basis_set_sub(item)
722 fname = Dialog.open_panel("Select a file containing GAMESS basis set:")
724 Molecule.read_gamess_basis_sets(fname)
725 bset_desc_new = $gamess_basis_keys.map { |key| $gamess_basis_desc[key] }
726 sel1 = attr("basis", :value)
727 sel2 = attr("secondary_basis", :value)
728 set_attr("basis", :subitems=>bset_desc_new)
729 set_attr("basis", :value=>sel1)
730 set_attr("secondary_basis", :subitems=>bset_desc_new)
731 set_attr("secondary_basis", :value=>sel2)
734 def select_gamess_path(item)
736 fname = Dialog.open_panel("Locate GAMESS executable:")
737 return if fname == nil
738 bname = File.basename(fname)
739 if bname =~ /gamess\.(.*)\.(exe|x)$/i
740 set_attr("executable_path", :value=>fname)
743 error_message_box("\"#{bname}\" does not look like a GAMESS executable! Please try again.")
748 item(:text, :title=>"SCF type"),
749 item(:popup, :subitems=>["RHF", "ROHF", "UHF"], :tag=>"scftype"),
750 item(:text, :title=>"Run type"),
751 item(:popup, :subitems=>["Energy", "Property", "Optimize"], :tag=>"runtype",
752 :action=>lambda { |it| set_attr("use_internal", :enabled=>(it[:value] == 2)) } ),
754 item(:checkbox, :title=>"Use internal coordinates for structure optimization", :tag=>"use_internal"),
757 item(:text, :title=>"Charge"),
758 item(:textfield, :width=>80, :tag=>"charge"),
759 item(:text, :title=>"Multiplicity"),
760 item(:textfield, :width=>80, :tag=>"mult"),
762 item(:checkbox, :title=>"Use DFT", :tag=>"dft",
763 :action=>lambda { |it| set_attr("dfttype", :enabled=>(it[:value] != 0)) } ),
765 item(:text, :title=>"DFT type"),
766 item(:popup, :subitems=>dft_desc, :tag=>"dfttype"),
771 item(:text, :title=>"Basis set"),
772 item(:popup, :subitems=>bset_desc, :tag=>"basis"),
776 item(:button, :title=>"Load Basis Set...", :action=>:load_basis_set_sub),
779 item(:checkbox, :title=>"Use secondary basis set", :tag=>"use_secondary_basis",
780 :action=>lambda { |it|
781 flag = (it[:value] != 0)
782 set_attr("secondary_elements", :enabled=>flag)
783 set_attr("secondary_basis", :enabled=>flag)
787 item(:text, :title=>" Elements"),
788 item(:textfield, :width=>80, :tag=>"secondary_elements"),
789 item(:text, :title=>"Basis set"),
790 item(:popup, :subitems=>bset_desc, :tag=>"secondary_basis"),
795 item(:checkbox, :title=>"Calculate electrostatic potential (ESP)", :tag=>"esp"),
801 item(:checkbox, :title=>"Execute GAMESS on this machine", :tag=>"execute_local",
802 :action=>lambda { |it|
803 flag = (it[:value] != 0)
804 set_attr("executable_path", :enabled=>flag)
805 set_attr("select_path", :enabled=>flag)
806 set_attr("ncpus", :enabled=>flag)
810 item(:text, :title=>" Path"),
811 item(:textfield, :width=>300, :tag=>"executable_path"),
815 item(:button, :title=>"Select Path...", :tag=>"select_path", :action=>:select_gamess_path),
818 item(:text, :title=>" N of CPUs"),
819 item(:textfield, :width=>80, :tag=>"ncpus"),
829 values[tag] = (get_global_settings("gamess.#{tag}") || defaults[tag])
830 it[:value] = values[tag]
833 set_attr("secondary_elements", :enabled=>(values["use_secondary_basis"] == 1))
834 set_attr("secondary_basis", :enabled=>(values["use_secondary_basis"] == 1))
835 set_attr("dfttype", :enabled=>(values["dft"] == 1))
836 set_attr("use_internal", :enabled=>(values["runtype"] == 2))
837 set_attr("executable_path", :enabled=>(values["execute_local"] == 1))
838 set_attr("select_path", :enabled=>(values["execute_local"] == 1))
839 set_attr("ncpus", :enabled=>(values["execute_local"] == 1))
841 hash.each_pair { |key, value|
842 next if key == :status
843 set_global_settings("gamess.#{key}", value)
845 if hash[:status] == 0
846 # Specify basis by internal keys
847 hash["basis"] = $gamess_basis_keys[hash["basis"]]
848 hash["secondary_basis"] = $gamess_basis_keys[hash["secondary_basis"]]
849 hash["dfttype"] = dft_internal[hash["dfttype"]]
850 basename = (self.path ? File.basename(self.path, ".*") : self.name)
851 fname = Dialog.save_panel("Export GAMESS input file:", self.dir, basename + ".inp", "GAMESS input file (*.inp)|*.inp|All files|*.*")
853 export_gamess(fname, hash)
854 if hash["execute_local"] == 1
855 Molecule.execute_gamess(fname, self)
863 grid = default_MO_grid
867 item(:text, :title=>"This molecule does not contain MO information."))
872 if mos == nil || mos.length == 0
875 item(:text, :title=>"Please select MO(s) in the MO Info table."))
881 item(:text, :title=>"Please specify cube dimensions (in bohr unit):"),
883 item(:text, :title=>"Origin"),
884 item(:textfield, :width=>100, :height=>20, :tag=>"originx", :value=>sprintf("%.6f", grid[0].x)),
885 item(:textfield, :width=>100, :height=>20, :tag=>"originy", :value=>sprintf("%.6f", grid[0].y)),
886 item(:textfield, :width=>100, :height=>20, :tag=>"originz", :value=>sprintf("%.6f", grid[0].z)),
887 item(:text, :title=>"Delta"),
888 item(:textfield, :width=>100, :height=>20, :tag=>"deltax", :value=>sprintf("%.6f", grid[1])),
889 item(:textfield, :width=>100, :height=>20, :tag=>"deltay", :value=>sprintf("%.6f", grid[2])),
890 item(:textfield, :width=>100, :height=>20, :tag=>"deltaz", :value=>sprintf("%.6f", grid[3])),
891 item(:text, :title=>"Step"),
892 item(:textfield, :width=>100, :height=>20, :tag=>"stepx", :value=>grid[4].to_s),
893 item(:textfield, :width=>100, :height=>20, :tag=>"stepy", :value=>grid[5].to_s),
894 item(:textfield, :width=>100, :height=>20, :tag=>"stepz", :value=>grid[6].to_s)))
896 if hash[:status] == 0
897 path = self.path || self.name
898 dir = self.dir || Dir.pwd
899 origin = Vector3D[hash["originx"], hash["originy"], hash["originz"]]
906 basename = File.basename(path, ".*")
908 mo_type = self.mo_type
910 fname1 = fname2 = nil
911 alpha = (mo_type != "UHF" ? "" : "alpha ")
912 a = (mo_type != "UHF" ? "" : "a")
913 fname1 = Dialog.save_panel("Cube file name for #{alpha}MO #{n}", dir, basename + "_#{n}#{a}.cube", "Gaussian cube file (*.cube)|*.cube")
914 if (mo_type == "UHF")
915 fname2 = Dialog.save_panel("Cube file name for beta MO #{n}", dir, basename + "_#{n}b.cube", "Gaussian cube file (*.cube)|*.cube")
917 filenames.push([n, fname1, fname2])
919 filenames.each { |pair|
921 alpha = (mo_type != "UHF" ? "" : "alpha ")
922 show_progress_panel("Creating cube file for #{alpha}MO #{n}...")
924 cubegen(pair[1], n, origin, dx, dy, dz, nx, ny, nz, true)
926 if pair[2] && mo_type == "UHF"
927 set_progress_message("Creating cube file for beta MO #{n}...")
928 cubegen(pair[2], n, origin, dx, dy, dz, nx, ny, nz, true, true)
939 "STO3G" => " STO 3\n",
940 "321G" => " N21 3\n",
941 "631G" => " N31 6\n" }
942 $gamess_basis_desc = {
947 $gamess_basis_keys = ["PM3", "STO3G", "321G", "631G"]
949 ["631Gd", "631Gdp", "631+Gd", "631++Gdp", "6311Gdp", "6311+Gd", "6311++Gdp", "6311++G2d2p", "6311++G3df3pd", "LanL2DZ"].each { |n|
950 Molecule.read_gamess_basis_sets("basis_sets/#{n}.txt")
953 register_menu("QChem\tCreate GAMESS Input...",
954 :cmd_create_gamess_input, :non_empty)
955 register_menu("QChem\tCreate MOPAC6 Input...",
956 :cmd_create_mopac_input, :non_empty) # mopac6.rb
957 register_menu("QChem\tCreate MO Cube...",
958 :cmd_create_cube, lambda { |m| m && m.mo_type } )