pw 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/cell/cell.rb +31 -0
- data/lib/cell/lib/atom.rb +54 -0
- data/lib/cell/lib/boundary.rb +40 -0
- data/lib/cell/lib/private.rb +80 -0
- data/lib/cell/lib/redef.rb +83 -0
- data/lib/cell/lib/write.rb +31 -0
- data/lib/helper/array.rb +24 -0
- data/lib/helper/numeric.rb +30 -0
- data/lib/helper/object.rb +24 -0
- data/lib/pw.rb +49 -1
- metadata +14 -4
data/lib/cell/cell.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative "./lib/atom.rb"
|
2
|
+
require_relative "../helper/numeric"
|
3
|
+
require_relative "./lib/write"
|
4
|
+
require_relative "./lib/boundary"
|
5
|
+
require_relative "./lib/private"
|
6
|
+
require_relative "./lib/redef"
|
7
|
+
class Cell < Array
|
8
|
+
attr_reader :min, :max, :celldm, :units
|
9
|
+
def initialize params = {}
|
10
|
+
add_to_atoms params[:atoms] unless params[:atoms].nil?
|
11
|
+
params[:units].lowercase! if params[:units].is_a? String
|
12
|
+
@units = params[:units] || :crystal
|
13
|
+
@celldm = (@units == :crystal ? [1,1,1] : params[:celldm].dup) rescue @celldm = []
|
14
|
+
@realcelldm = (@units == :bohr ? params[:celldm].map{|v| v*0.52918} : params[:celldm]) rescue @realcelldm = []
|
15
|
+
@min = []
|
16
|
+
@max = []
|
17
|
+
end
|
18
|
+
def celldm= *args
|
19
|
+
arr = args.flatten
|
20
|
+
@celldm = (@units == :crystal ? [1,1,1] : arr)
|
21
|
+
@realcelldm = (@units == :bohr ? arr.map{|v| v*0.52918} : arr)
|
22
|
+
update_atoms_celldm
|
23
|
+
end
|
24
|
+
def units= unit
|
25
|
+
unit.lowercase! if unit.is_a? String
|
26
|
+
unit = unit.to_sym
|
27
|
+
return self if unit == @units
|
28
|
+
change_units unit
|
29
|
+
@units = unit
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class Atom
|
2
|
+
attr_accessor :uid, :fixed, :celldm
|
3
|
+
attr_reader :coor
|
4
|
+
def initialize params = {}
|
5
|
+
@name = params[:name].to_sym rescue @name = :X
|
6
|
+
@coor = params[:coor].dup rescue @coor = []
|
7
|
+
@uid = params[:uid] || nil
|
8
|
+
@fixed = params[:fixed]||false
|
9
|
+
@celldm = params[:celldm] || nil
|
10
|
+
# element = params[:element] || #TODO element constants. dont forget fixing dup
|
11
|
+
end
|
12
|
+
def coor= *c; @coor = c.flatten;end
|
13
|
+
def name= nm; @name = nm.to_sym; end
|
14
|
+
def name; @name.to_s; end
|
15
|
+
def x; @coor[0]; end
|
16
|
+
def y; @coor[1]; end
|
17
|
+
def z; @coor[2]; end
|
18
|
+
def x= num; @coor[0] = num; end
|
19
|
+
def y= num; @coor[1] = num; end
|
20
|
+
def z= num; @coor[2] = num; end
|
21
|
+
def move! *args
|
22
|
+
args.flatten!
|
23
|
+
args = args * 3 if args.length == 1
|
24
|
+
for i in 0..2;coor[i]+=args[i];end
|
25
|
+
return self
|
26
|
+
end
|
27
|
+
def move *args
|
28
|
+
a = self.dup
|
29
|
+
return a.move!(*args)
|
30
|
+
end
|
31
|
+
def to_s
|
32
|
+
l = (@fixed ? " 0 0 0" : "")
|
33
|
+
output = "%-4s%14.9f%14.9f%14.9f%s" % [@name, coor[0], coor[1], coor[2], l]
|
34
|
+
return output
|
35
|
+
end
|
36
|
+
def dup
|
37
|
+
Atom.new(:name => @name, :coor => @coor, :uid => @uid, :fixed => @fixed, :celldm => @celldm)
|
38
|
+
end
|
39
|
+
def dist other
|
40
|
+
if other.is_a? Atom
|
41
|
+
arr = other.coor
|
42
|
+
elsif other.is_a? Array and other.length = 3
|
43
|
+
arr = other
|
44
|
+
else
|
45
|
+
return nil
|
46
|
+
end
|
47
|
+
d = []
|
48
|
+
for i in 0..2
|
49
|
+
d.push (@coor[i] - arr[i]).abs
|
50
|
+
d[i] = @celldm[i] - d[i] if (!@celldm.nil? and d[i] > @celldm[i]/2)
|
51
|
+
end
|
52
|
+
return (d[0]**2+d[1]**2+d[2]**2).sqrt
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Cell < Array
|
2
|
+
def dist x, y
|
3
|
+
$stderr.puts "Distance in crystal units is usually not meaningful!" if @units == :crystal
|
4
|
+
arr = wrap(0)
|
5
|
+
return arr[x].dist arr[y]
|
6
|
+
end
|
7
|
+
def wrap! tol = 0.5
|
8
|
+
self.each do |atom|
|
9
|
+
(0..2).each {|i| atom.coor[i] -= @celldm[i] while atom.coor[i] - @celldm[i] > tol}
|
10
|
+
(0..2).each {|i| atom.coor[i] += @celldm[i] while atom.coor[i] < -tol}
|
11
|
+
end
|
12
|
+
scan_mins_maxes
|
13
|
+
return self
|
14
|
+
end
|
15
|
+
def wrap tol = 0.5
|
16
|
+
arr = self.dup
|
17
|
+
return arr.wrap!(tol)
|
18
|
+
end
|
19
|
+
def move! *args
|
20
|
+
args.flatten!
|
21
|
+
args*=3 if args.length == 1
|
22
|
+
self.each do |atom|
|
23
|
+
atom.move! args
|
24
|
+
end
|
25
|
+
for i in 0..2;@max[i]+=args[i];@min[i]+=args[i];end
|
26
|
+
return self
|
27
|
+
end
|
28
|
+
def move *args
|
29
|
+
arr = self.dup
|
30
|
+
return arr.move! *args
|
31
|
+
end
|
32
|
+
def reset_order!
|
33
|
+
self.old_sort!{|x,y| x.uid <=> y.uid}
|
34
|
+
return self
|
35
|
+
end
|
36
|
+
def reset_order
|
37
|
+
arr = self.dup
|
38
|
+
return arr.reset_order!
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
class Cell < Array
|
2
|
+
private
|
3
|
+
def cell_bindings arg, i = self.length
|
4
|
+
arg.uid = i
|
5
|
+
arg.celldm = @celldm
|
6
|
+
return arg
|
7
|
+
end
|
8
|
+
def add_to_atoms args
|
9
|
+
args.each do |atom|
|
10
|
+
unless self << atom.dup
|
11
|
+
$stderr.puts "#{atom} is not an Atom"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
def update_mins_maxes arg
|
16
|
+
for i in 0..2
|
17
|
+
(@min[i] = arg[i] if @min[i] > arg[i]) rescue @min[i] = arg[i]
|
18
|
+
(@max[i] = arg[i] if @max[i] < arg[i]) rescue @max[i] = arg[i]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
def update_atoms_celldm
|
22
|
+
self.each do |atom|
|
23
|
+
atom.celldm = @celldm
|
24
|
+
end
|
25
|
+
end
|
26
|
+
def scan_mins_maxes
|
27
|
+
@min = self[0].coor.dup
|
28
|
+
@max = self[0].coor.dup
|
29
|
+
self.each do |atom|
|
30
|
+
for i in 0..2
|
31
|
+
(@min[i] = atom.coor[i] if @min[i] > atom.coor[i]) rescue @min[i] = atom.coor[i]
|
32
|
+
(@max[i] = atom.coor[i] if @max[i] < atom.coor[i]) rescue @max[i] = atom.coor[i]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
def change_units unit
|
37
|
+
if unit == :crystal
|
38
|
+
self.map!{|atom| atom.coor = toCry(atom.coor);atom}
|
39
|
+
@max = toCry @max
|
40
|
+
@min = toCry @min
|
41
|
+
@celldm = [1,1,1]
|
42
|
+
elsif unit == :angstrom
|
43
|
+
@celldm = @realcelldm
|
44
|
+
if @units == :crystal
|
45
|
+
self.map!{|atom| atom.coor = fromCry(atom.coor);atom}
|
46
|
+
@max = fromCry @max
|
47
|
+
@min = fromCry @min
|
48
|
+
elsif @units == :bohr
|
49
|
+
self.map!{|atom| atom.coor = bhr2ang(atom.coor);atom}
|
50
|
+
@max = bhr2ang @max
|
51
|
+
@min = bhr2ang @min
|
52
|
+
end
|
53
|
+
elsif unit == :bohr
|
54
|
+
@celldm = @realcelldm.map{|v| v/0.52918}
|
55
|
+
if @units == :crystal
|
56
|
+
self.map!{|atom| atom.coor = fromCry(atom.coor);atom}
|
57
|
+
@max = fromCry @max
|
58
|
+
@min = fromCry @min
|
59
|
+
elsif @units == :angstrom
|
60
|
+
self.map!{|atom| atom.coor = ang2bhr(atom.coor);atom}
|
61
|
+
@max = ang2bhr @max
|
62
|
+
@min = ang2bhr @min
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
def toCry args
|
67
|
+
for i in 0..2; args[i]/=@celldm[i]; end rescue nil
|
68
|
+
return args
|
69
|
+
end
|
70
|
+
def fromCry args
|
71
|
+
for i in 0..2; args[i]*=@celldm[i]; end rescue nil
|
72
|
+
return args
|
73
|
+
end
|
74
|
+
def ang2bhr args
|
75
|
+
return args.map{|v| v / 0.52918}
|
76
|
+
end
|
77
|
+
def bhr2ang args
|
78
|
+
return args.map{|v| v * 0.52918}
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
class Cell < Array
|
2
|
+
alias :old_sort! :sort!
|
3
|
+
def sort! fields, tol = 0.5
|
4
|
+
tol = [tol, tol, tol] unless tol.is_a? Array
|
5
|
+
self.old_sort! do |a, b|
|
6
|
+
g = fields.to_s.split(//)
|
7
|
+
t = a.name <=> b.name
|
8
|
+
x = a.x.approx_sort(b.x, tol[0])
|
9
|
+
y = a.y.approx_sort(b.y, tol[1])
|
10
|
+
z = a.z.approx_sort(b.z, tol[2])
|
11
|
+
result = 0
|
12
|
+
while result == 0 and g.length > 0
|
13
|
+
result = eval(g.shift)
|
14
|
+
end
|
15
|
+
result
|
16
|
+
end
|
17
|
+
return self
|
18
|
+
end
|
19
|
+
def sort *args
|
20
|
+
arr = self.dup
|
21
|
+
return arr.sort!(*args)
|
22
|
+
end
|
23
|
+
alias :old_p :<<
|
24
|
+
def << arg
|
25
|
+
if arg.is_a?(Atom)
|
26
|
+
cell_bindings arg
|
27
|
+
update_mins_maxes arg.coor
|
28
|
+
self.old_p(arg.dup)
|
29
|
+
else false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
alias :old_unshift :unshift
|
33
|
+
def unshift arg
|
34
|
+
if arg.is_a?(Atom)
|
35
|
+
cell_bindings arg, 0
|
36
|
+
self.each{|atom| atom.uid+=1}
|
37
|
+
update_mins_maxes arg.coor
|
38
|
+
self.old_unshift(arg.dup)
|
39
|
+
else false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
alias :old_push :push
|
43
|
+
def push arg
|
44
|
+
if arg.is_a?(Atom)
|
45
|
+
cell_bindings arg
|
46
|
+
update_mins_maxes arg.coor
|
47
|
+
self.old_push(arg.dup)
|
48
|
+
else false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
alias :old_insert :insert
|
52
|
+
def insert arg, index
|
53
|
+
if arg.is_a?(Atom)
|
54
|
+
cell_bindings arg, index
|
55
|
+
update_mins_maxes arg.coor
|
56
|
+
self.each do |atom|
|
57
|
+
atom.uid+=1 if atom uid >= index
|
58
|
+
end
|
59
|
+
self.old_insert(arg.dup, index)
|
60
|
+
else false
|
61
|
+
end
|
62
|
+
end
|
63
|
+
alias :old_plus :+
|
64
|
+
def + arg
|
65
|
+
if arg.is_a?(Cell)
|
66
|
+
update_mins_maxes arg.min
|
67
|
+
update_mins_maxes arg.max
|
68
|
+
self.old_plus(arg)
|
69
|
+
else false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
def dup
|
73
|
+
if @units == :bohr
|
74
|
+
arr = Cell.new(:units => @units, :celldm => @celldm)
|
75
|
+
else
|
76
|
+
arr = Cell.new(:units => @units, :celldm => @realcelldm)
|
77
|
+
end
|
78
|
+
self.each do |atom|
|
79
|
+
arr << atom.dup
|
80
|
+
end
|
81
|
+
return arr
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Cell < Array
|
2
|
+
def to_s
|
3
|
+
output = ""
|
4
|
+
self.each do |atom|
|
5
|
+
output += "%s\n" % atom.to_s
|
6
|
+
end
|
7
|
+
return output
|
8
|
+
end
|
9
|
+
def to_pdb
|
10
|
+
arr = (@units == :angstrom ? self : self.dup)
|
11
|
+
arr.units = :angstrom
|
12
|
+
output = "CRYST1%9.3f%9.3f%9.3f 90.00 90.00 90.00 P 1\n" % arr.celldm
|
13
|
+
i = 0
|
14
|
+
arr.each do |atom|
|
15
|
+
i += 1
|
16
|
+
output += "ATOM %5d %-4s X 1 %8.3f%8.3f%8.3f 1.00 1.00 %-2s\n" % ([i, atom.name] + atom.coor + [atom.name])
|
17
|
+
end
|
18
|
+
return output
|
19
|
+
end
|
20
|
+
def to_xyz
|
21
|
+
arr = (@units == :angstrom ? self : self.dup)
|
22
|
+
arr.units = :angstrom
|
23
|
+
output = "%d\n" % arr.length
|
24
|
+
output += "Cell Dimensions %10.6f %10.6f %10.6f\n" % arr.celldm
|
25
|
+
arr.each do |atom|
|
26
|
+
output += "%-2s %10.6f %10.6f %10.6f\n" % ([atom.name] + atom.coor)
|
27
|
+
end
|
28
|
+
return output
|
29
|
+
end
|
30
|
+
# def to_cif
|
31
|
+
end
|
data/lib/helper/array.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
class Array
|
2
|
+
def numbers!
|
3
|
+
i = length - 1
|
4
|
+
self.reverse_each do |elem|
|
5
|
+
if elem.is_a? Array
|
6
|
+
self[i] = elem.numbers!
|
7
|
+
else
|
8
|
+
elem.numeric? ? self[i] = Float(elem):self.delete_at(i)
|
9
|
+
end
|
10
|
+
i -= 1
|
11
|
+
end
|
12
|
+
return self
|
13
|
+
end
|
14
|
+
def numerify!
|
15
|
+
self.each_index do |i|
|
16
|
+
if self[i].is_a? Array
|
17
|
+
self[i] = self[i].numerify!
|
18
|
+
else
|
19
|
+
self[i] = Float(self[i]) if self[i].numeric?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
return self
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Numeric
|
2
|
+
(Math.methods - Module.methods - ["hypot", "ldexp"]).each do |method|
|
3
|
+
define_method method do
|
4
|
+
Math.send method, self
|
5
|
+
end
|
6
|
+
end
|
7
|
+
def approx_sort other, tol = self.to_f/10
|
8
|
+
d = self - other
|
9
|
+
if d > tol
|
10
|
+
return 1
|
11
|
+
elsif -d > tol
|
12
|
+
return -1
|
13
|
+
else
|
14
|
+
return 0
|
15
|
+
end
|
16
|
+
end
|
17
|
+
def numeric?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
class Object
|
22
|
+
def numeric?
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
class String
|
27
|
+
def numeric?
|
28
|
+
Float(self) != nil rescue false
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Object
|
2
|
+
def deep_clone
|
3
|
+
return @deep_cloning_obj if @deep_cloning
|
4
|
+
@deep_cloning_obj = clone
|
5
|
+
@deep_cloning_obj.instance_variables.each do |var|
|
6
|
+
val = @deep_cloning_obj.instance_variable_get(var)
|
7
|
+
begin
|
8
|
+
@deep_cloning = true
|
9
|
+
val = val.deep_clone
|
10
|
+
rescue TypeError
|
11
|
+
next
|
12
|
+
ensure
|
13
|
+
@deep_cloning = false
|
14
|
+
end
|
15
|
+
@deep_cloning_obj.instance_variable_set(var, val)
|
16
|
+
end
|
17
|
+
deep_cloning_obj = @deep_cloning_obj
|
18
|
+
@deep_cloning_obj = nil
|
19
|
+
deep_cloning_obj
|
20
|
+
end
|
21
|
+
def to_sym
|
22
|
+
self.to_s.to_sym
|
23
|
+
end
|
24
|
+
end
|
data/lib/pw.rb
CHANGED
@@ -1,2 +1,50 @@
|
|
1
|
-
|
1
|
+
require_relative "./cell/cell"
|
2
|
+
require "fileutil"
|
3
|
+
require_relative "./helper/array.rb"
|
4
|
+
|
5
|
+
class PW
|
6
|
+
def self.input ifile
|
7
|
+
cell = nil
|
8
|
+
File.open(ifile, 'r') do |f|
|
9
|
+
nat = f.ff(/nat/).readline.split(/[ ,]/).numbers![0]
|
10
|
+
celldm = []
|
11
|
+
while f.ff(/celldm/)
|
12
|
+
celldm.push f.readline.split(/[ ,]/).numbers!
|
13
|
+
end
|
14
|
+
celldm.map!{|v| v == celldm[0] ? v * 0.52918 : v * celldm[0]}
|
15
|
+
f.ff(/ATOMIC_POSITIONS/)
|
16
|
+
unit = unit? f.readline
|
17
|
+
cell = Cell.new(:celldm => celldm, :units => unit)
|
18
|
+
f.head(nat, true).map{|v| v.split.numerify!}.each do |atom|
|
19
|
+
cell << Atom.new(:name => atom[0], :coor => atom[1,4], :fixed => !atom[4].nil?)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
return cell
|
23
|
+
end
|
24
|
+
def self.output ofile
|
25
|
+
cell = nil
|
26
|
+
File.open(ofile, 'r') do |f|
|
27
|
+
nat = f.ff(/number of atoms/).readline.split.numbers![0]
|
28
|
+
celldm = f.ff(/celldm/).readline.split.numbers!
|
29
|
+
celldm.map!{|v| v == celldm[0] ? v * 0.52918 : v * celldm[0]}
|
30
|
+
f.seek f.size
|
31
|
+
unit = unit? f.rew(/ATOMIC_POSITIONS/).readline
|
32
|
+
cell = Cell.new(:celldm => celldm, :units => unit)
|
33
|
+
f.head(nat, true).map{|v| v.split.numerify!}.each do |atom|
|
34
|
+
cell << Atom.new(:name => atom[0], :coor => atom[1,3], :fixed => !atom[4].nil?)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
return cell
|
38
|
+
end
|
39
|
+
private
|
40
|
+
def self.unit? h
|
41
|
+
if /crystal/i =~ h
|
42
|
+
unit = :crystal
|
43
|
+
elsif /angstrom/i =~ h
|
44
|
+
unit = :angstrom
|
45
|
+
elsif /bohr/i =~ h
|
46
|
+
unit = :bohr
|
47
|
+
end
|
48
|
+
return unit
|
49
|
+
end
|
2
50
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pw
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.0
|
5
4
|
prerelease:
|
5
|
+
version: 0.0.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Sencer Selcuk
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-02-04 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Quantum Espresso
|
15
15
|
email: sencerselcuk@twitter
|
@@ -17,7 +17,16 @@ executables: []
|
|
17
17
|
extensions: []
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
|
+
- lib/cell/lib/private.rb
|
21
|
+
- lib/cell/lib/redef.rb
|
22
|
+
- lib/cell/lib/boundary.rb
|
23
|
+
- lib/cell/lib/write.rb
|
24
|
+
- lib/cell/lib/atom.rb
|
25
|
+
- lib/cell/cell.rb
|
20
26
|
- lib/pw.rb
|
27
|
+
- lib/helper/object.rb
|
28
|
+
- lib/helper/numeric.rb
|
29
|
+
- lib/helper/array.rb
|
21
30
|
homepage:
|
22
31
|
licenses: []
|
23
32
|
post_install_message:
|
@@ -25,17 +34,17 @@ rdoc_options: []
|
|
25
34
|
require_paths:
|
26
35
|
- lib
|
27
36
|
required_ruby_version: !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
29
37
|
requirements:
|
30
38
|
- - ! '>='
|
31
39
|
- !ruby/object:Gem::Version
|
32
40
|
version: '0'
|
33
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
34
41
|
none: false
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
35
43
|
requirements:
|
36
44
|
- - ! '>='
|
37
45
|
- !ruby/object:Gem::Version
|
38
46
|
version: '0'
|
47
|
+
none: false
|
39
48
|
requirements: []
|
40
49
|
rubyforge_project:
|
41
50
|
rubygems_version: 1.8.23
|
@@ -43,3 +52,4 @@ signing_key:
|
|
43
52
|
specification_version: 3
|
44
53
|
summary: will be implemented
|
45
54
|
test_files: []
|
55
|
+
has_rdoc:
|