File: pes.rb

package info (click to toggle)
psicode 3.4.0-5
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 46,400 kB
  • ctags: 18,552
  • sloc: cpp: 291,425; ansic: 12,788; fortran: 10,489; perl: 3,206; sh: 2,702; makefile: 2,207; ruby: 2,178; yacc: 110; lex: 53
file content (145 lines) | stat: -rw-r--r-- 4,695 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# Code that simplifies computing a potential energy surface

# Add pes ability to Task
module Psi
  class Task
    # Function arguments:
    #  :num_disps => #          (required)
    #  :report => true or false (default => true)
    #  :col_labels => array     (required, column headings)
    #  :file => string          (optional)
    #  :format => formatstring  (optional) if "csv" saves the file in csv format.
    #
    # Expects a yield block that runs the single point and returns the information to collect.
    #
    # Returns the information that was collected
    def pes(*args)
      # Convert the array to a hash
      args_hash = args[0]

      format = "normal"
      format = args_hash[:format] if args_hash.has_key?(:format)
      
      # Make sure num_disps is provided
      if args_hash.has_key?(:num_disps) == false
        puts "Error: In function \"pes\", :num_disps required."
        exit 1
      end

      # Check to see if :report is given and if it is true :col_label is required
      if args_hash.has_key?(:report) and args_hash[:report] == true
        if args_hash.has_key?(:col_labels) == false
          puts "Error: In function \"pes\", :col_labels is required if :report => true."
          exit 1
        end
      end

      # Create the result array
      result = []

      # Loop over the displacements
      puts "Beginning PES scan..."
      Psi::indent_puts
      (1..args_hash[:num_disps]).each do |ndisp|
        puts "Displacement #{ndisp}"
        Psi::indent_puts
        result += yield(ndisp)
        Psi::unindent_puts
      end
      Psi::unindent_puts

      # Report the results
      if args_hash.has_key?(:report) and args_hash[:report] == true
        puts "Results from PES scan:"
        args_hash[:col_labels].each do |label|
          printf(sprintf(" %-14s ", label.to_s))
        end
        printf "\n"

        col_count = (args_hash[:col_labels].length) - 1
        row_count = (result.length / args_hash[:col_labels].length) - 1

        (0..row_count).each do |row|
          (0..col_count).each do |col|
            indx = row * (col_count+1) + col
            if result[indx].instance_of? Fixnum or result[indx].instance_of? Bignum
              printf(sprintf(" %-14d ", result[indx]))
            elsif result[indx].instance_of? Float
              printf(sprintf(" %-14.9f ", result[indx]))
            else
              printf(sprintf(" %-14s ", result[indx].to_s))
            end
          end
          printf "\n"
        end
      end

      # Does the user want the data saved to a file?
      if args_hash.has_key?(:file)
        File.open(args_hash[:file], "w") do |file|
          args_hash[:col_labels].each do |label|
            if format == "normal"
              file.printf(sprintf(" %-14s ", label.to_s))
            elsif format == "csv"
              file.printf(label.to_s + ",")
            end
          end
          file.printf "\n"

          col_count = (args_hash[:col_labels].length) - 1
          row_count = (result.length / args_hash[:col_labels].length) - 1

          (0..row_count).each do |row|
            (0..col_count).each do |col|
              indx = row * (col_count+1) + col
              if format == "normal"
                if result[indx].instance_of? Fixnum or result[indx].instance_of? Bignum
                  file.printf(sprintf(" %-14d ", result[indx]))
                elsif result[indx].instance_of? Float
                  file.printf(sprintf(" %-14.9f ", result[indx]))
                else
                  file.printf(sprintf(" %-14s ", result[indx].to_s))
                end
              elsif format == "csv"
                file.printf(result[indx].to_s + ",")
              end
            end
            file.printf "\n"
          end
        end
      end

      # If the user provided :col_labels, convert result into a more 
      # manageable form
      if args_hash.has_key?(:col_labels)
        new_result = {}
        # Add empty arrays to the new hash
        args_hash[:col_labels].each do |label|
          new_result[label] = []
        end

        # Go through added the data to the appropriate array
        col_count = (args_hash[:col_labels].length) - 1
        row_count = (result.length / args_hash[:col_labels].length) - 1

        (0..row_count).each do |row|
          (0..col_count).each do |col|
            new_result[args_hash[:col_labels][col]] << result[row * (col_count+1) + col]
          end
        end

        result = new_result
      end

      return result
    end
  end
end

# Provide global ability to pes
def pes(*args)
  args_hash = args[0]
  Psi::global_task.pes(args_hash) do |disp|
    yield disp
  end
end