Molecular Modeling Software
リビジョン | fe3b322085a44b7209e92ffa6e8072faf848e1fe (tree) |
---|---|
日時 | 2014-04-04 20:21:15 |
作者 | toshinagata1964 <toshinagata1964@a2be...> |
コミッター | toshinagata1964 |
GAMESS dialog is modified so that manual editing is possible. (Still not quite consistent though.)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/molby/trunk@525 a2be9bc6-48de-4e38-9406-05402d4bc13c
@@ -142,6 +142,7 @@ Ruby_NewFileStringValue(const char *fstr) | ||
142 | 142 | char * |
143 | 143 | Ruby_EncodedStringValuePtr(VALUE *valp) |
144 | 144 | { |
145 | + rb_string_value(valp); | |
145 | 146 | *valp = rb_str_encode(*valp, rb_enc_from_encoding(rb_default_external_encoding()), 0, Qnil); |
146 | 147 | return RSTRING_PTR(*valp); |
147 | 148 | } |
@@ -13,6 +13,21 @@ | ||
13 | 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | 14 | # GNU General Public License for more details. |
15 | 15 | |
16 | +class MemoryIO < IO | |
17 | + def initialize | |
18 | + @buffer = "" | |
19 | + end | |
20 | + def write(s) | |
21 | + @buffer << s | |
22 | + end | |
23 | + def buffer | |
24 | + @buffer | |
25 | + end | |
26 | + def empty | |
27 | + @buffer = "" | |
28 | + end | |
29 | +end | |
30 | + | |
16 | 31 | class Molecule |
17 | 32 | |
18 | 33 | def Molecule.read_gamess_basis_sets(fname) |
@@ -211,6 +226,8 @@ class Molecule | ||
211 | 226 | ENV["QUANPOL"] = "#{auxdir}#{sep}QUANPOL" |
212 | 227 | ENV["EXTBAS"] = "/dev/null" |
213 | 228 | ENV["IRCDATA"] = "#{scrbody}.irc" |
229 | + ENV["RESTART"] = "#{scrbody}.rst" | |
230 | + ENV["TRAJECT"] = "#{scrbody}.trj" | |
214 | 231 | ENV["PUNCH"] = "#{scrbody}.dat" |
215 | 232 | ENV["INPUT"] = "#{scrbody}.F05" |
216 | 233 | ENV["AOINTS"] = "#{scrbody}.F08" |
@@ -486,16 +503,20 @@ class Molecule | ||
486 | 503 | end |
487 | 504 | |
488 | 505 | now = Time.now.to_s |
489 | - basename = File.basename(fname, ".*") | |
506 | + if fname | |
507 | + basename = File.basename(fname, ".*") | |
508 | + else | |
509 | + basename = File.basename(self.name, ".*") | |
510 | + end | |
490 | 511 | |
491 | 512 | # Various settings |
492 | 513 | icharg = hash["charge"] |
493 | 514 | mult = hash["mult"] |
494 | - runtyp = ["ENERGY", "PROP", "OPTIMIZE"][Integer(hash["runtype"])] | |
495 | - scftyp = ["RHF", "ROHF", "UHF"][Integer(hash["scftype"])] | |
515 | + runtyp = ["ENERGY", "PROP", "OPTIMIZE"][hash["runtype"].to_i] | |
516 | + scftyp = ["RHF", "ROHF", "UHF"][hash["scftype"].to_i] | |
496 | 517 | bssname = hash["basis"] |
497 | 518 | bssname2 = hash["secondary_basis"] |
498 | - if hash["use_secondary_basis"] != 0 && bssname2 != bssname | |
519 | + if hash["use_secondary_basis"].to_i != 0 && bssname2 != bssname | |
499 | 520 | use_2nd = true |
500 | 521 | element2 = hash["secondary_elements"].split(/[\s,]+/).map { |name| name.capitalize } |
501 | 522 | else |
@@ -504,9 +525,6 @@ class Molecule | ||
504 | 525 | end |
505 | 526 | basis = $gamess_basis[bssname] |
506 | 527 | basis2 = $gamess_basis[bssname2] |
507 | - if !basis || !basis2 | |
508 | - raise MolbyError, "Unknown basis set name??? \"#{bssname}\" or \"#{bssname2}\"" | |
509 | - end | |
510 | 528 | |
511 | 529 | # Use effective core potentials? |
512 | 530 | ecp = $gamess_ecp[bssname] |
@@ -561,7 +579,7 @@ class Molecule | ||
561 | 579 | end |
562 | 580 | if hash["use_internal"] != 0 && (hash["runtype"] == 2 || h["RUNTYP"] == "OPTIMIZE") |
563 | 581 | nzvar = natoms * 3 - 6 # TODO: 3N-5 for linear molecules |
564 | - h["NZVAR"] = nzvar.to_s | |
582 | + h["NZVAR"] ||= nzvar.to_s | |
565 | 583 | else |
566 | 584 | nzvar = 0 |
567 | 585 | end |
@@ -569,7 +587,7 @@ class Molecule | ||
569 | 587 | if ecp_read != "" |
570 | 588 | h["ECP"] ||= "READ" |
571 | 589 | end |
572 | - h["UNITS"] = "ANGS" | |
590 | + h["UNITS"] ||= "ANGS" | |
573 | 591 | |
574 | 592 | h = (hash["SCF"] ||= Hash.new) |
575 | 593 | h["CONV"] ||= "1.0E-06" |
@@ -610,18 +628,24 @@ class Molecule | ||
610 | 628 | h["PTSEL"] ||= "CONNOLLY" |
611 | 629 | end |
612 | 630 | |
613 | - File.open(fname, "wb") { |fp| | |
631 | + if fname | |
632 | + fp = File.open(fname, "wb") | |
633 | + else | |
634 | + fp = MemoryIO.new | |
635 | + end | |
636 | + if fp | |
614 | 637 | fp.print "! GAMESS input\n" |
615 | 638 | fp.print "! Generated by Molby at #{now}\n" |
616 | - fp.print "! Basis set: " + $gamess_basis_desc[bssname] + "\n" | |
639 | + fp.print "! Basis set: " + ($gamess_basis_desc[bssname] || "(not specified)") + "\n" | |
617 | 640 | if use_2nd |
618 | - fp.print "! [" + element2.join(", ") + "]: " + $gamess_basis_desc[bssname2] + "\n" | |
641 | + fp.print "! [" + element2.join(", ") + "]: " + ($gamess_basis_desc[bssname2] || "(not specified)") + "\n" | |
619 | 642 | end |
620 | - controls = reorder_array(hash.keys.select { |k| hash[k].is_a?(Hash) }, | |
621 | - ["CONTRL", "SCF", "STATPT", "SYSTEM", "GUESS", "BASIS", "ZMAT", "ELPOT", "PDC"]) | |
643 | + ordered = ["CONTRL", "SCF", "STATPT", "SYSTEM", "GUESS", "BASIS", "ZMAT", "ELPOT", "PDC"] | |
644 | + controls = reorder_array(hash.keys.select { |k| k != "key_order" && hash[k].is_a?(Hash) }, | |
645 | + hash["key_order"] || ordered) | |
622 | 646 | controls.each { |k| |
623 | 647 | h = hash[k] |
624 | - next if h == nil || h.size == 0 | |
648 | + next if h == nil || h.size == 0 || (h["key_order"] && h.size == 1) | |
625 | 649 | if k == "CONTRL" |
626 | 650 | ordered = ["COORD", "EXETYP", "ICHARG", "ICUT", "INTTYP", "ITOL", "MAXIT", "MOLPLT", "MPLEVL", |
627 | 651 | "MULT", "QMTTOL", "RUNTYP", "SCFTYP", "ECP", "UNITS", "DFTTYP", "NZVAR"] |
@@ -644,7 +668,7 @@ class Molecule | ||
644 | 668 | else |
645 | 669 | ordered = [] |
646 | 670 | end |
647 | - keys = reorder_array(h.keys, ordered) | |
671 | + keys = reorder_array(h.keys, h["key_order"] || ordered) | |
648 | 672 | n = 0 |
649 | 673 | keys.each_with_index { |kk, i| |
650 | 674 | v = h[kk] |
@@ -675,11 +699,12 @@ class Molecule | ||
675 | 699 | if bas.is_a?(Array) |
676 | 700 | bas = bas[ap.atomic_number] |
677 | 701 | end |
678 | - if !bas | |
679 | - raise MolbyError, "Basis set is not defined for atom #{ap.index}, element #{ap.element}" | |
702 | + if bas | |
703 | + fp.print bas | |
704 | + fp.print "\n" | |
705 | + else | |
706 | + puts "Warning: basis set is not defined for atom #{ap.index}, element #{ap.element}" | |
680 | 707 | end |
681 | - fp.print bas | |
682 | - fp.print "\n" | |
683 | 708 | end |
684 | 709 | } |
685 | 710 | fp.print " $END\n" |
@@ -701,12 +726,36 @@ class Molecule | ||
701 | 726 | } |
702 | 727 | fp.print " $END\n" |
703 | 728 | end |
729 | + end | |
730 | + if fname == nil | |
731 | + s = fp.buffer | |
732 | + fp.empty | |
733 | + return s | |
734 | + else | |
735 | + fp.close | |
736 | + return fname | |
737 | + end | |
738 | + end | |
739 | + | |
740 | + def cmd_edit_gamess_input(s) | |
741 | + h = Dialog.run("Edit GAMESS Input", "OK", "Cancel", :resizable=>true) { | |
742 | + layout(1, | |
743 | + item(:textview, :value=>s, :tag=>"edit", :width=>400, :height=>400, :flex=>[0,0,0,0,1,1]), | |
744 | + :flex=>[0,0,0,0,1,1] | |
745 | + ) | |
746 | + set_min_size(300, 300) | |
704 | 747 | } |
705 | - fname | |
748 | + if h[:status] == 0 | |
749 | + return h["edit"] | |
750 | + else | |
751 | + return nil | |
752 | + end | |
706 | 753 | end |
707 | 754 | |
708 | 755 | def cmd_create_gamess_input |
709 | 756 | |
757 | + mol = self | |
758 | + | |
710 | 759 | if natoms == 0 |
711 | 760 | raise MolbyError, "cannot create GAMESS input; the molecule is empty" |
712 | 761 | end |
@@ -722,6 +771,79 @@ class Molecule | ||
722 | 771 | "basis"=>4, "use_secondary_basis"=>0, "secondary_elements"=>"", |
723 | 772 | "secondary_basis"=>8, "esp"=>0, "ncpus"=>"1"} |
724 | 773 | |
774 | + gamess_input_direct = nil | |
775 | + | |
776 | + user_input = Hash.new | |
777 | + ["CONTRL", "SCF", "STATPT", "SYSTEM", "GUESS", "BASIS"].each { |k| | |
778 | + user_input[k] = Hash.new | |
779 | + } | |
780 | + if ".inp".casecmp(self.name[-4, 4]) == 0 | |
781 | + # Read input and analyze commands | |
782 | + fp = open(self.path, "r") | |
783 | + key = hh = nil | |
784 | + if fp | |
785 | + while ln = fp.gets | |
786 | + ln.strip! | |
787 | + break if "$DATA".casecmp(ln[0, 5]) == 0 | |
788 | + ln.split.each { |s| | |
789 | + if s[0] == "$" | |
790 | + # New key | |
791 | + key = s[1..-1].upcase | |
792 | + hh = user_input[key] = Hash.new | |
793 | + (user_input["key_order"] ||= []).push(key) | |
794 | + else | |
795 | + k, v = s.split("=") | |
796 | + if key && hh | |
797 | + k.upcase! | |
798 | + hh[k] = v | |
799 | + (hh["key_order"] ||= []).push(k) | |
800 | + end | |
801 | + end | |
802 | + } | |
803 | + end # end while | |
804 | + fp.close | |
805 | + user_input["charge"] = user_input["CONTRL"]["ICHARG"] | |
806 | + user_input["mult"] = user_input["CONTRL"]["MULT"] | |
807 | + user_input["runtype"] = ((i = ["ENERGY", "PROP", "OPTIMIZE"].find_index(user_input["CONTRL"]["RUNTYP"])) ? i.to_s : nil) | |
808 | + user_input["scftype"] = ((i = ["RHF", "ROHF", "UHF"].find_index(user_input["CONTRL"]["SCFTYP"])) ? i.to_s : nil) | |
809 | + dft_type = dft_internal.find_index(user_input["CONTRL"]["DFTTYP"]) | |
810 | + if dft_type | |
811 | + user_input["dfttype"] = dft_type.to_s | |
812 | + user_input["dft"] = 1 | |
813 | + end | |
814 | + bssname = nil | |
815 | + user_input["basis"] = "-1" | |
816 | + case user_input["BASIS"]["GBASIS"] | |
817 | + when "PM3" | |
818 | + bssname = "PM3" | |
819 | + when "STO" | |
820 | + bssname = "STO3G" | |
821 | + when "N21" | |
822 | + bssname = "321G" | |
823 | + when "N31" | |
824 | + if user_input["NDFUNC"] == "1" | |
825 | + if user_input["NPFUNC"] == "1" | |
826 | + bssname = "631Gdp" | |
827 | + else | |
828 | + bssname = "631Gd" | |
829 | + end | |
830 | + else | |
831 | + bssname = "631G" | |
832 | + end | |
833 | + when "N311" | |
834 | + if user_input["NDFUNC"] == "1" && user_input["NPFUNC"] == "1" | |
835 | + bssname = "6311Gdp" | |
836 | + else | |
837 | + bssname = "6311G" | |
838 | + end | |
839 | + end | |
840 | + if bssname | |
841 | + user_input["basis"] = $gamess_basis_keys.find_index(bssname).to_s | |
842 | + end | |
843 | + puts user_input.inspect | |
844 | + end | |
845 | + end | |
846 | + | |
725 | 847 | hash = Dialog.run("GAMESS Export") { |
726 | 848 | def load_basis_set_sub(item) |
727 | 849 | fname = Dialog.open_panel("Select a file containing GAMESS basis set:") |
@@ -774,7 +896,7 @@ class Molecule | ||
774 | 896 | -1, -1, -1, |
775 | 897 | |
776 | 898 | item(:text, :title=>"Basis set"), |
777 | - item(:popup, :subitems=>bset_desc, :tag=>"basis"), | |
899 | + item(:popup, :subitems=>bset_desc + ["(no select)"], :tag=>"basis"), | |
778 | 900 | -1, |
779 | 901 | -1, |
780 | 902 |
@@ -825,13 +947,33 @@ class Molecule | ||
825 | 947 | -1, -1, |
826 | 948 | |
827 | 949 | item(:line), |
950 | + -1, -1, -1, | |
951 | + | |
952 | + item(:button, :title=>"Edit GAMESS Input and Go", :action=>lambda { |it| | |
953 | + h = Hash.new | |
954 | + each_item { |it2| | |
955 | + if (tag = it2[:tag]) != nil | |
956 | + h[tag] = it2[:value] | |
957 | + end | |
958 | + } | |
959 | + h["basis"] = $gamess_basis_keys[h["basis"]] | |
960 | + h["secondary_basis"] = $gamess_basis_keys[h["secondary_basis"]] | |
961 | + h["dfttype"] = dft_internal[h["dfttype"]] | |
962 | + gamess_input_direct = mol.cmd_edit_gamess_input(mol.export_gamess(nil, h)) | |
963 | + if gamess_input_direct | |
964 | + end_modal(0) | |
965 | + end | |
966 | + }), | |
828 | 967 | -1, -1, -1 |
829 | 968 | ) |
830 | 969 | values = Hash.new |
831 | 970 | each_item { |it| |
832 | 971 | tag = it[:tag] |
833 | 972 | if tag |
834 | - values[tag] = (get_global_settings("gamess.#{tag}") || defaults[tag]) | |
973 | + values[tag] = (user_input[tag] || get_global_settings("gamess.#{tag}") || defaults[tag]) | |
974 | + if tag == "basis" && values[tag] == "-1" | |
975 | + values[tag] = (bset_desc.count).to_s | |
976 | + end | |
835 | 977 | it[:value] = values[tag] |
836 | 978 | end |
837 | 979 | } |
@@ -853,15 +995,21 @@ class Molecule | ||
853 | 995 | hash["secondary_basis"] = $gamess_basis_keys[hash["secondary_basis"]] |
854 | 996 | hash["dfttype"] = dft_internal[hash["dfttype"]] |
855 | 997 | basename = (self.path ? File.basename(self.path, ".*") : self.name) |
856 | - fname = Dialog.save_panel("Export GAMESS input file:", self.dir, basename + ".inp", "GAMESS input file (*.inp)|*.inp|All files|*.*") | |
998 | + fname = Dialog.save_panel("Export GAMESS input file:", self.dir, basename + ".inp", "GAMESS input file (*.inp)|*.inp|All files|*.*") | |
857 | 999 | return nil if !fname |
858 | - export_gamess(fname, hash) | |
1000 | + if gamess_input_direct | |
1001 | + puts "gamess_input_direct = \"#{gamess_input_direct}\"" | |
1002 | + File.open(fname, "w") { |fp| fp.print(gamess_input_direct) } | |
1003 | + else | |
1004 | + export_gamess(fname, hash) | |
1005 | + end | |
859 | 1006 | if hash["execute_local"] == 1 |
860 | 1007 | Molecule.execute_gamess(fname, self) |
861 | 1008 | end |
862 | 1009 | else |
863 | 1010 | nil |
864 | 1011 | end |
1012 | + | |
865 | 1013 | end |
866 | 1014 | |
867 | 1015 | def cmd_create_cube |
@@ -280,9 +280,6 @@ class Molecule | ||
280 | 280 | else |
281 | 281 | v3 = v2.cross(v1).normalize |
282 | 282 | end |
283 | - #if cs > 1.0 | |
284 | - puts "cs = #{cs}" | |
285 | - #end | |
286 | 283 | angle = Math.atan2(Math.sqrt_safe(1.0 - cs*cs), cs) * Rad2Deg |
287 | 284 | mol.rotate(v3, angle, mol.atoms[base2].r) |
288 | 285 | end |