crystalcell 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +1 -0
- data/VERSION +1 -1
- data/crystalcell.gemspec +81 -0
- data/lib/crystalcell/atom.rb +118 -118
- data/lib/crystalcell/cell.rb +584 -584
- data/lib/crystalcell/element.rb +135 -135
- data/lib/crystalcell/latticeaxes.rb +194 -188
- data/lib/crystalcell/periodiccell.rb +244 -244
- data/test/test_atom.rb +198 -198
- data/test/test_cell.rb +1450 -1478
- data/test/test_element.rb +642 -642
- data/test/test_latticeaxes.rb +283 -278
- data/test/test_periodiccell.rb +948 -948
- metadata +4 -3
@@ -6,271 +6,271 @@ require "pp"
|
|
6
6
|
# Coordinates of atoms are kept in the region of 0 <= x_i < 1 of internal coordinate.
|
7
7
|
class CrystalCell::PeriodicCell < CrystalCell::Cell
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
15
|
-
|
16
|
-
#ある内部座標から、別のある座標とそれと周期的に等価な座標への距離が
|
17
|
-
#tolerance 以下のものを探し、条件を満たすセルの方向を配列にまとめて返す。
|
18
|
-
#
|
19
|
-
#内部的に、一度 0以上1未満の座標に変換しようかと思ったが、
|
20
|
-
#境界付近で問題が生じうる。
|
21
|
-
#
|
22
|
-
#周囲 27 セルしか考慮しない。
|
23
|
-
#美しさを求めるならば tolerance を完全に含む大きさのスーパーセルにすべきだが、
|
24
|
-
#実装が面倒なわりに滅多に使われることがなさそうなので。
|
25
|
-
#出力の順番は、上位の要素が小さなものから順。
|
26
|
-
#(距離の短いものから順という考え方もなくはないが。)
|
27
|
-
#
|
28
|
-
#tolerance を省略( = nil を与えれば )、27セルの中にある全ての方向を返す。
|
29
|
-
def directions_within_distance( pos0, pos1, tolerance = nil )
|
30
|
-
if pos0.class != Vector3DInternal
|
31
|
-
raise TypeError, "pos0 is not a Vector3DInternal class instance."
|
32
|
-
end
|
33
|
-
if pos1.class != Vector3DInternal
|
34
|
-
raise TypeError, "pos1 is not a Vector3DInternal class instance."
|
9
|
+
class TypeError < Exception; end
|
10
|
+
|
11
|
+
def initialize( *args )
|
12
|
+
super( *args )
|
13
|
+
reset_positions_inside
|
35
14
|
end
|
36
15
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
16
|
+
#ある内部座標から、別のある座標とそれと周期的に等価な座標への距離が
|
17
|
+
#tolerance 以下のものを探し、条件を満たすセルの方向を配列にまとめて返す。
|
18
|
+
#
|
19
|
+
#内部的に、一度 0以上1未満の座標に変換しようかと思ったが、
|
20
|
+
#境界付近で問題が生じうる。
|
21
|
+
#
|
22
|
+
#周囲 27 セルしか考慮しない。
|
23
|
+
#美しさを求めるならば tolerance を完全に含む大きさのスーパーセルにすべきだが、
|
24
|
+
#実装が面倒なわりに滅多に使われることがなさそうなので。
|
25
|
+
#出力の順番は、上位の要素が小さなものから順。
|
26
|
+
#(距離の短いものから順という考え方もなくはないが。)
|
27
|
+
#
|
28
|
+
#tolerance を省略( = nil を与えれば )、27セルの中にある全ての方向を返す。
|
29
|
+
def directions_within_distance( pos0, pos1, tolerance = nil )
|
30
|
+
if pos0.class != Vector3DInternal
|
31
|
+
raise TypeError, "pos0 is not a Vector3DInternal class instance."
|
53
32
|
end
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
33
|
+
if pos1.class != Vector3DInternal
|
34
|
+
raise TypeError, "pos1 is not a Vector3DInternal class instance."
|
35
|
+
end
|
36
|
+
|
37
|
+
pos0 = pos0.map{ |i| i - i.floor }.to_a.to_v3di
|
38
|
+
pos1 = pos1.map{ |i| i - i.floor }.to_a.to_v3di
|
39
|
+
|
40
|
+
#pp pos0
|
41
|
+
|
42
|
+
results = []
|
43
|
+
(-1).upto(1) do |x|
|
44
|
+
(-1).upto(1) do |y|
|
45
|
+
(-1).upto(1) do |z|
|
46
|
+
shift = Vector3DInternal[ x.to_f, y.to_f, z.to_f ]
|
47
|
+
d = distance( pos0, ( pos1 + shift))
|
48
|
+
#tolerance が nil ならば距離判定なしで登録。
|
49
|
+
#tolerance が非 nil ならばその値で距離判定して登録。
|
50
|
+
if ( ( ! tolerance ) || ( d < tolerance ) )
|
51
|
+
results << [ x, y, z]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
return results
|
77
57
|
end
|
78
|
-
|
79
|
-
|
80
|
-
|
58
|
+
|
59
|
+
# 周期性を考慮して、
|
60
|
+
# 1個目の内部座標( pos0 ) から見て、
|
61
|
+
# 一番近い 2個目の内部座標に等価なサイトの属するセルの方向を返す。
|
62
|
+
# 返り値は Vector3DInternal で
|
63
|
+
# 内部座標が 0.0 <= r < 1.0 になっていることを前提とする。
|
64
|
+
# (なお、この外側であってもこの範囲に入るように周期移動する。)
|
65
|
+
# 座標 0.0 付近の境界は計算誤差の為におかしなことになり易いので注意が必要。
|
66
|
+
#
|
67
|
+
# NOTE: nearest_direction というメソッド名はどうかと思う。
|
68
|
+
# nearest_lattice_vector とか?
|
69
|
+
# 良い名前があれば、リファクタリング対象。
|
70
|
+
#
|
71
|
+
# NOTE: 0〜1の外側なら内側に入れる、という処理は混乱し易い。
|
72
|
+
# 例外にした方が良いのではないだろうか。
|
73
|
+
def nearest_direction( pos0, pos1 )
|
74
|
+
if pos0.class != Vector3DInternal
|
75
|
+
raise TypeError,
|
76
|
+
"pos0.class is not a Vector3DInternal"
|
77
|
+
end
|
78
|
+
if pos1.class != Vector3DInternal
|
79
|
+
raise TypeError,
|
80
|
+
"pos1.class is not a Vector3DInternal"
|
81
|
+
end
|
82
|
+
|
83
|
+
pos0 = pos0.map{ |i| i - i.floor }.to_a.to_v3di
|
84
|
+
pos1 = pos1.map{ |i| i - i.floor }.to_a.to_v3di
|
85
|
+
|
86
|
+
#set first value
|
87
|
+
min = distance( pos0, pos1 )
|
88
|
+
result = Vector3DInternal[ 0, 0, 0 ]
|
89
|
+
|
90
|
+
#find
|
91
|
+
(-1).upto(1) do |x|
|
92
|
+
(-1).upto(1) do |y|
|
93
|
+
(-1).upto(1) do |z|
|
94
|
+
shift = Vector3DInternal[ x.to_f, y.to_f, z.to_f ]
|
95
|
+
d = (pos0 - (pos1 + shift)).to_v3d(@axes).r
|
96
|
+
|
97
|
+
if d < min
|
98
|
+
result = Vector3DInternal[ x, y, z]
|
99
|
+
min = d
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
return result
|
81
105
|
end
|
82
106
|
|
83
|
-
|
84
|
-
|
107
|
+
#周期性を考慮し、2つの地点間の最短距離を返す。
|
108
|
+
#pos0, pos1 には内部座標を指定する。
|
109
|
+
#内部的には周囲 3x3x3 のセル中の27地点のうち最も近いものを得る。
|
110
|
+
#旧 minimum_distance
|
111
|
+
def nearest_distance( pos0, pos1 )
|
112
|
+
[pos0, pos1].each_with_index do |pos, index|
|
113
|
+
unless pos.class == Vector3DInternal
|
114
|
+
raise TypeError,
|
115
|
+
"#{index} th argument: #{pos.inspect}, #{pos.class}"
|
116
|
+
end
|
117
|
+
end
|
85
118
|
|
86
|
-
|
87
|
-
|
88
|
-
|
119
|
+
pos0 = Vector3DInternal[* pos0.map{ |i| i - i.floor }]
|
120
|
+
pos1 = Vector3DInternal[* pos1.map{ |i| i - i.floor }]
|
121
|
+
direction = nearest_direction( pos0, pos1 )
|
122
|
+
3.times do |i|
|
123
|
+
pos1[ i ] += direction[ i ]
|
124
|
+
end
|
125
|
+
distance( pos0, pos1 )
|
126
|
+
end
|
89
127
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
128
|
+
#条件にマッチした原子間距離を見つけて、端点の内部座標の組を要素とする配列を返す。
|
129
|
+
#返される配列は3重配列になる。
|
130
|
+
#e.g.,
|
131
|
+
# [
|
132
|
+
# [ [0.1, 0.1, 0.1], [0.2, 0.2, 0.2] ],
|
133
|
+
# [ [0.1, 0.1, 0.1], [0.3, 0.4, 0.5] ],
|
134
|
+
# [ [0.9, 0.9, 0.9], [0.8, 0.8, 0.8] ]
|
135
|
+
# ]
|
136
|
+
#@bonds への登録はしない。
|
137
|
+
#elem0, elem1 は bond の両端の原子の組み合わせを指定。
|
138
|
+
#elem0, elem1 はメソッド内部で反転したものもチェックするので、順序が反対でも同じ結果になる。
|
139
|
+
#O-O のように同じ元素を指定することもでき、
|
140
|
+
#この場合向きの異なる 2つの bond が重複したりしない。
|
141
|
+
#d_min, d_max は距離の範囲を指定する。
|
142
|
+
#境界値そのものが問題になることは少ないだろう。
|
143
|
+
#d_min <= d <= d_max(以上、以下) としておくが、計算誤差のためにこれはほぼ無意味だ。
|
144
|
+
#見つけて配列として返すだけで、登録はしない。
|
145
|
+
#
|
146
|
+
#以下の案は棄却。
|
147
|
+
# - いかなる元素でもマッチ。
|
148
|
+
# - 距離の上限を無効。
|
149
|
+
#理由は、
|
150
|
+
# - プログラムが煩雑になる。
|
151
|
+
# - 引数の型が統一されない。
|
152
|
+
# - ほとんど使用する機会がなさそう。
|
153
|
+
# 大抵は元素を指定するし、元素を指定しない bond を描く状況は考えにくい。
|
154
|
+
# これが必要ならメソッドの外で組み合わせを作ってそれぞれで呼べば良い。
|
155
|
+
# - 大抵は距離の上限を定めるし、上限なしではハリネズミになるだけ。
|
156
|
+
# また、プログラム上は距離の上限を 3x3x3 スーパーセルに制限したりするが、
|
157
|
+
# 論理的に距離の上限なしってのは無限のセルを対象にすることになり、整合性がとれない。
|
158
|
+
def find_bonds( elem0, elem1, d_min, d_max )
|
159
|
+
results = []
|
160
|
+
atoms.each do |inner_atom|
|
161
|
+
atoms_in_supercell( -1, 1, -1, 1, -1, 1 ).each do |outer_atom|
|
162
|
+
#元素の種類による判定
|
163
|
+
ie = inner_atom.element
|
164
|
+
oe = outer_atom.element
|
165
|
+
next unless ( (( ie == elem0 ) && ( oe == elem1 )) || (( ie == elem1 ) && ( oe == elem0 ))) #elem0, elem1 と同じ構成
|
166
|
+
|
167
|
+
#距離による判定
|
168
|
+
ip = inner_atom.position
|
169
|
+
op = outer_atom.position
|
170
|
+
next if distance( ip, op ) < d_min
|
171
|
+
next if distance( ip, op ) > d_max
|
172
|
+
next if distance( ip, op ) == 0.0 #同一サイト判定
|
173
|
+
|
174
|
+
#重複判定, 正順か逆順が既に含まれていれば無視。
|
175
|
+
next if ( results.include?( [ ip, op ] ) || results.include?( [ op, ip ] ) )
|
176
|
+
|
177
|
+
results << [ ip, op ]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
return results
|
181
|
+
end
|
96
182
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
183
|
+
#引数 distance 以下の間の距離にある原子のペアを列挙して返す。
|
184
|
+
#この際、あくまで unique なものを返し、A-B があれば B-A はリストに含まれない。
|
185
|
+
#
|
186
|
+
#返す形式は以下のような形式。
|
187
|
+
#[ [0, 1, [0, 0, 0], [0, 1, [0, 0, 1] ]
|
188
|
+
#最初の 0, 1 はそれぞれ配列 @atoms 内の番号で、
|
189
|
+
#0番目の原子からから同じセル内の 1番目の原子
|
190
|
+
#0番目の原子からから[0,0,1]方向に隣接するセル内の 1番目の原子を意味する。
|
191
|
+
#起点となる原子の番号と(上記 0 )と目的地の原子の番号(上記 1)が同じこともありうる。
|
192
|
+
#異なる場合は起点となる原子の番号が、目的地の原子の番号より若くなる。
|
193
|
+
#
|
194
|
+
#自分と同じ番号の場合は、同じセルを除外する。
|
195
|
+
#すなわち、[0, 0, [0, 0, 0] や [1, 1, [0, 0, 0] は含まれない。
|
196
|
+
def pairs_within_distance( distance )
|
197
|
+
results = []
|
198
|
+
n_atom = @atoms.size
|
199
|
+
n_atom.times do |i|
|
200
|
+
pos_i = @atoms[i].position
|
201
|
+
|
202
|
+
n_atom.times do |j|
|
203
|
+
pos_j = @atoms[j].position
|
204
|
+
|
205
|
+
directions_within_distance( pos_i, pos_j, distance ).each do |dir|
|
206
|
+
#next if ( i==j && dir==[0,0,0] ) #距離0の自分自身。下の条件に含まれる。
|
207
|
+
next if ( dir==[0,0,0] && i >= j ) #同じセル内は番号が若い方からのみ。
|
208
|
+
results << [ i, j, dir ]
|
209
|
+
end
|
210
|
+
end
|
101
211
|
end
|
102
|
-
|
212
|
+
return results
|
103
213
|
end
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
#内部的には周囲 3x3x3 のセル中の27地点のうち最も近いものを得る。
|
110
|
-
#旧 minimum_distance
|
111
|
-
def nearest_distance( pos0, pos1 )
|
112
|
-
[pos0, pos1].each_with_index do |pos, index|
|
113
|
-
unless pos.class == Vector3DInternal
|
114
|
-
raise TypeError,
|
115
|
-
"#{index} th argument: #{pos.inspect}, #{pos.class}"
|
116
|
-
end
|
214
|
+
|
215
|
+
# Functions as like CrystalCell::Cell.add_atom, but the coordinates are converted to the region of 0 <= x_i < 1.
|
216
|
+
def add_atom( *args )
|
217
|
+
super( *args )
|
218
|
+
reset_positions_inside
|
117
219
|
end
|
118
220
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
221
|
+
# Functions as like CrystalCell::Cell.rotate!, but the coordinates are converted to the region of 0 <= x_i < 1.
|
222
|
+
# Dependent function 'rotate' functions the same.
|
223
|
+
def rotate!( *args )
|
224
|
+
super( *args )
|
225
|
+
reset_positions_inside
|
124
226
|
end
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
# [
|
132
|
-
# [ [0.1, 0.1, 0.1], [0.2, 0.2, 0.2] ],
|
133
|
-
# [ [0.1, 0.1, 0.1], [0.3, 0.4, 0.5] ],
|
134
|
-
# [ [0.9, 0.9, 0.9], [0.8, 0.8, 0.8] ]
|
135
|
-
# ]
|
136
|
-
#@bonds への登録はしない。
|
137
|
-
#elem0, elem1 は bond の両端の原子の組み合わせを指定。
|
138
|
-
#elem0, elem1 はメソッド内部で反転したものもチェックするので、順序が反対でも同じ結果になる。
|
139
|
-
#O-O のように同じ元素を指定することもでき、
|
140
|
-
#この場合向きの異なる 2つの bond が重複したりしない。
|
141
|
-
#d_min, d_max は距離の範囲を指定する。
|
142
|
-
#境界値そのものが問題になることは少ないだろう。
|
143
|
-
#d_min <= d <= d_max(以上、以下) としておくが、計算誤差のためにこれはほぼ無意味だ。
|
144
|
-
#見つけて配列として返すだけで、登録はしない。
|
145
|
-
#
|
146
|
-
#以下の案は棄却。
|
147
|
-
# - いかなる元素でもマッチ。
|
148
|
-
# - 距離の上限を無効。
|
149
|
-
#理由は、
|
150
|
-
# - プログラムが煩雑になる。
|
151
|
-
# - 引数の型が統一されない。
|
152
|
-
# - ほとんど使用する機会がなさそう。
|
153
|
-
# 大抵は元素を指定するし、元素を指定しない bond を描く状況は考えにくい。
|
154
|
-
# これが必要ならメソッドの外で組み合わせを作ってそれぞれで呼べば良い。
|
155
|
-
# - 大抵は距離の上限を定めるし、上限なしではハリネズミになるだけ。
|
156
|
-
# また、プログラム上は距離の上限を 3x3x3 スーパーセルに制限したりするが、
|
157
|
-
# 論理的に距離の上限なしってのは無限のセルを対象にすることになり、整合性がとれない。
|
158
|
-
def find_bonds( elem0, elem1, d_min, d_max )
|
159
|
-
results = []
|
160
|
-
atoms.each do |inner_atom|
|
161
|
-
atoms_in_supercell( -1, 1, -1, 1, -1, 1 ).each do |outer_atom|
|
162
|
-
#元素の種類による判定
|
163
|
-
ie = inner_atom.element
|
164
|
-
oe = outer_atom.element
|
165
|
-
next unless ( (( ie == elem0 ) && ( oe == elem1 )) || (( ie == elem1 ) && ( oe == elem0 ))) #elem0, elem1 と同じ構成
|
166
|
-
|
167
|
-
#距離による判定
|
168
|
-
ip = inner_atom.position
|
169
|
-
op = outer_atom.position
|
170
|
-
next if distance( ip, op ) < d_min
|
171
|
-
next if distance( ip, op ) > d_max
|
172
|
-
next if distance( ip, op ) == 0.0 #同一サイト判定
|
173
|
-
|
174
|
-
#重複判定, 正順か逆順が既に含まれていれば無視。
|
175
|
-
next if ( results.include?( [ ip, op ] ) || results.include?( [ op, ip ] ) )
|
176
|
-
|
177
|
-
results << [ ip, op ]
|
178
|
-
end
|
227
|
+
|
228
|
+
# Functions as like CrystalCell::Cell.translate!, but the coordinates are converted to the region of 0 <= x_i < 1.
|
229
|
+
# Dependent function 'translate' functions the same.
|
230
|
+
def translate!( *args )
|
231
|
+
super( *args )
|
232
|
+
reset_positions_inside
|
179
233
|
end
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
#[ [0, 1, [0, 0, 0], [0, 1, [0, 0, 1] ]
|
188
|
-
#最初の 0, 1 はそれぞれ配列 @atoms 内の番号で、
|
189
|
-
#0番目の原子からから同じセル内の 1番目の原子
|
190
|
-
#0番目の原子からから[0,0,1]方向に隣接するセル内の 1番目の原子を意味する。
|
191
|
-
#起点となる原子の番号と(上記 0 )と目的地の原子の番号(上記 1)が同じこともありうる。
|
192
|
-
#異なる場合は起点となる原子の番号が、目的地の原子の番号より若くなる。
|
193
|
-
#
|
194
|
-
#自分と同じ番号の場合は、同じセルを除外する。
|
195
|
-
#すなわち、[0, 0, [0, 0, 0] や [1, 1, [0, 0, 0] は含まれない。
|
196
|
-
def pairs_within_distance( distance )
|
197
|
-
results = []
|
198
|
-
n_atom = @atoms.size
|
199
|
-
n_atom.times do |i|
|
200
|
-
pos_i = @atoms[i].position
|
201
|
-
|
202
|
-
n_atom.times do |j|
|
203
|
-
pos_j = @atoms[j].position
|
204
|
-
|
205
|
-
directions_within_distance( pos_i, pos_j, distance ).each do |dir|
|
206
|
-
#next if ( i==j && dir==[0,0,0] ) #距離0の自分自身。下の条件に含まれる。
|
207
|
-
next if ( dir==[0,0,0] && i >= j ) #同じセル内は番号が若い方からのみ。
|
208
|
-
results << [ i, j, dir ]
|
234
|
+
|
235
|
+
# Return a new instance converted to CrystalCell::Cell class.
|
236
|
+
def to_cell
|
237
|
+
tmp = CrystalCell::Cell.new( @axes.to_a )
|
238
|
+
tmp.comment = self.comment
|
239
|
+
@atoms.each do |atom|
|
240
|
+
tmp.add_atom(atom)
|
209
241
|
end
|
210
|
-
|
242
|
+
return tmp
|
211
243
|
end
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
# Functions as like CrystalCell::Cell.rotate!, but the coordinates are converted to the region of 0 <= x_i < 1.
|
222
|
-
# Dependent function 'rotate' functions the same.
|
223
|
-
def rotate!( *args )
|
224
|
-
super( *args )
|
225
|
-
reset_positions_inside
|
226
|
-
end
|
227
|
-
|
228
|
-
# Functions as like CrystalCell::Cell.translate!, but the coordinates are converted to the region of 0 <= x_i < 1.
|
229
|
-
# Dependent function 'translate' functions the same.
|
230
|
-
def translate!( *args )
|
231
|
-
super( *args )
|
232
|
-
reset_positions_inside
|
233
|
-
end
|
234
|
-
|
235
|
-
# Return a new instance converted to CrystalCell::Cell class.
|
236
|
-
def to_cell
|
237
|
-
tmp = CrystalCell::Cell.new( @axes.to_a )
|
238
|
-
tmp.comment = self.comment
|
239
|
-
@atoms.each do |atom|
|
240
|
-
tmp.add_atom(atom)
|
244
|
+
|
245
|
+
undef center_of_atoms
|
246
|
+
|
247
|
+
# superclass の inverse_axis! を行ったあと、
|
248
|
+
# 原子の座標をセル内部に移す。
|
249
|
+
def inverse_axis!( axis_id )
|
250
|
+
result = Marshal.load( Marshal.dump( self ) )
|
251
|
+
super( axis_id )
|
252
|
+
reset_positions_inside
|
241
253
|
end
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
super( axis_id )
|
252
|
-
reset_positions_inside
|
253
|
-
end
|
254
|
-
|
255
|
-
private
|
256
|
-
|
257
|
-
# Reset internal coordinates of all atoms inside the region of 0 <= x_i < 1.
|
258
|
-
def reset_positions_inside
|
259
|
-
@atoms.each do |atom|
|
260
|
-
coords = atom.position
|
261
|
-
atom.set_position(coords.map {|coord| coord - coord.floor}.to_a.to_v3di)
|
254
|
+
|
255
|
+
private
|
256
|
+
|
257
|
+
# Reset internal coordinates of all atoms inside the region of 0 <= x_i < 1.
|
258
|
+
def reset_positions_inside
|
259
|
+
@atoms.each do |atom|
|
260
|
+
coords = atom.position
|
261
|
+
atom.set_position(coords.map {|coord| coord - coord.floor}.to_a.to_v3di)
|
262
|
+
end
|
262
263
|
end
|
263
|
-
end
|
264
264
|
|
265
265
|
end
|
266
266
|
|
267
267
|
class CrystalCell::Cell
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
268
|
+
#require "Crystal/PeriodicCell.rb"
|
269
|
+
# Return a new instance converted to PeriodicCell class.
|
270
|
+
def to_pcell
|
271
|
+
atoms = Marshal.load(Marshal.dump(@atoms))
|
272
|
+
result = CrystalCell::PeriodicCell.new( @axes.to_a, atoms )
|
273
|
+
result.comment = self.comment
|
274
|
+
return result
|
275
|
+
end
|
276
276
|
end
|