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
|