4 # Created by Toshi Nagata on 2013/11/01.
5 # Copyright 2013 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.
19 # inpname is the input file
20 # mol (optional) is the molecule from which the MOPAC input was built.
21 def Molecule.execute_mopac(inpname, mol = nil)
24 mopexe = "#{ResourcePath}/mopac/mopac606"
26 inpname = File.expand_path(inpname)
27 inpbase = File.basename(inpname)
28 inpdir = File.dirname(inpname)
29 inpbody = inpbase.sub(/\.\w*$/, "")
31 # Prepare the scratch directory in the home directory
32 scrdir = document_home.sub(/\/My Documents/, "") + "/mopac"
34 while File.exist?(scrdir) && !File.directory?(scrdir)
38 scrdir = scrdir.sub(".#{n}", ".#{n + 1}")
42 if !File.exist?(scrdir)
45 scrdir = scrdir + "/" + inpbody + "." + $$.to_s + ".0"
47 while File.exist?(scrdir)
48 scrdir = scrdir.sub(".#{n}", ".#{n + 1}")
53 # Copy the input file to the scratch directory
55 filecopy(inpname, scrdir + "/FOR005")
56 term_callback = lambda { |m, n|
57 if File.exist?("#{scrdir}/FOR006")
58 filecopy("#{scrdir}/FOR006", "#{inpdir}/#{inpbody}.out")
60 msg = "MOPAC execution on #{inpbase} "
67 msg += "failed with status #{n}."
71 msg += "\n(In directory #{inpdir})"
72 message_box(msg, hmsg, :ok, icon)
73 erase_old_logs(scrdir, "latest", 5) # Keep latest 5 logs
80 pid = mol.call_subprocess_async(mopexe, term_callback, timer_callback, "NUL", "NUL")
82 pid = call_subprocess(mopexe, "Running MOPAC", nil, "NUL", "NUL")
83 term_callback.call(nil, pid)
87 error_message_box("MOPAC failed to run.")
94 if !@mopac_settings || (com = @mopac_settings["commands"]) == nil
96 (@mopac_settings ||= Hash.new)["commands"] = com
99 str += sprintf("# %-76.76s\n", self.name)
100 str += sprintf("# %-76.76s\n", "Generated by Molby at #{Time.now.to_s}")
101 # Create geometry input
106 geom += atoms[0].element + "\n"
109 geom += sprintf("%s %.6f 1\n", atoms[1].element, r)
111 con = atoms[2].connects
114 a = calc_angle(2, 0, 1)
118 a = calc_angle(2, 1, 0)
121 geom += sprintf("%s %.6f 1 %.3f 1 %s\n", atoms[2].element, r, a, c)
128 geom += sprintf("%s %.6f 1 %.6f 1 %.6f 1\n", ap.element, ap.x, ap.y, ap.z)
131 return str + geom + "\n"
134 def cmd_create_mopac_input
137 h = Dialog.run("Create MOPAC6 Input") {
139 item(:text, :title=>"MOPAC input"),
140 item(:textview, :width=>480, :height=>200, :tag=>"mopac_commands"),
142 item(:text, :title=>"Action: "),
143 item(:radio, :title=>"Save only", :tag=>"save_only", :value=>1),
145 item(:radio, :title=>"Save and Run MOPAC", :tag=>"save_and_run")
148 radio_group("save_only", "save_and_run")
149 item_with_tag("mopac_commands")[:font] = [:fixed, 10]
150 item_with_tag("mopac_commands")[:value] = mol.create_mopac
152 # Record the command lines for next invocation
153 mop = h["mopac_commands"]
154 com = (mop.split(/[\r\n]/))[0..0].join("\n")
155 (@mopac_settings ||= Hash.new)["commands"] = com
157 basename = (self.path ? File.basename(self.path, ".*") : self.name)
158 fname = Dialog.save_panel("Export MOPAC input file:", self.dir, basename + ".mopin", "MOPAC input file (*.mopin)|*.mopin|All files|*.*")
160 open(fname, "w") { |fp|
163 if h["save_and_run"] == 1
164 Molecule.execute_mopac(fname, self)
170 # if lookup_menu("Create MOPAC6 Input...") < 0
171 # register_menu("", "")
172 # register_menu("Create MOPAC6 Input...", :cmd_create_mopac)