crysna 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/CHANGES +24 -0
  4. data/Gemfile +26 -0
  5. data/Gemfile.lock +91 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.rdoc +19 -0
  8. data/Rakefile +53 -0
  9. data/VERSION +1 -0
  10. data/bin/checkmodel +66 -0
  11. data/bin/collectcell +92 -0
  12. data/bin/fitframe +68 -0
  13. data/bin/occupiedpolyhedralsite +96 -0
  14. data/bin/occupiedscattersite +77 -0
  15. data/bin/site2poscar +66 -0
  16. data/bin/site2pov +30 -0
  17. data/bin/sitecombination +69 -0
  18. data/bin/sitemigration +80 -0
  19. data/bin/sitemigrationdistance +87 -0
  20. data/bin/siteoperation +109 -0
  21. data/bin/sitesingle +36 -0
  22. data/bin/siteuniq +32 -0
  23. data/bin/symidsite +65 -0
  24. data/bin/transitcell +46 -0
  25. data/crysna.gemspec +219 -0
  26. data/lib/crysna.rb +26 -0
  27. data/lib/crysna/atom.rb +97 -0
  28. data/lib/crysna/cell.rb +314 -0
  29. data/lib/crysna/frameatom.rb +13 -0
  30. data/lib/crysna/frameinterstitialcell.rb +309 -0
  31. data/lib/crysna/interstitialatom.rb +13 -0
  32. data/lib/crysna/modelstructure.rb +333 -0
  33. data/lib/crysna/optionmanager.rb +177 -0
  34. data/lib/crysna/site.rb +35 -0
  35. data/lib/crysna/siteconfiguration.rb +26 -0
  36. data/lib/crysna/sitenamelabeledcell.rb +220 -0
  37. data/lib/crysna/siteoperation.rb +56 -0
  38. data/lib/crysna/sitewithposition.rb +24 -0
  39. data/lib/crysna/transitionfinder.rb +448 -0
  40. data/lib/crysna/transitionfinder/cell.rb +144 -0
  41. data/lib/crysna/transitionfinder/cellmanager.rb +129 -0
  42. data/lib/crysna/transitionfinder/edge.rb +54 -0
  43. data/test/.gitignore +1 -0
  44. data/test/cell_orig/POSCAR +17 -0
  45. data/test/cell_orig/model.yaml +122 -0
  46. data/test/collectcells/.gitignore +2 -0
  47. data/test/collectcells/model.yaml +154 -0
  48. data/test/collectcells/nooutcar/minexpconfiguration.yaml +22 -0
  49. data/test/collectcells/normal-higher/OUTCAR +2406 -0
  50. data/test/collectcells/normal-higher/minexpconfiguration.yaml +22 -0
  51. data/test/collectcells/normal-lower/OUTCAR +2406 -0
  52. data/test/collectcells/normal-lower/minexpconfiguration.yaml +22 -0
  53. data/test/collectcells/normal/OUTCAR +2406 -0
  54. data/test/collectcells/normal/minexpconfiguration.yaml +22 -0
  55. data/test/collectcells/normalB/OUTCAR +2406 -0
  56. data/test/collectcells/normalB/minexpconfiguration.yaml +22 -0
  57. data/test/collectcells/unfinished/OUTCAR +40702 -0
  58. data/test/collectcells/unfinished/minexpconfiguration.yaml +22 -0
  59. data/test/collectcells/unidentified/OUTCAR +3541 -0
  60. data/test/collectcells/unidentified/minexpconfiguration.yaml +2 -0
  61. data/test/fitmodelstructure/.gitignore +1 -0
  62. data/test/fitmodelstructure/AgI/CONTCAR +17 -0
  63. data/test/fitmodelstructure/AgI/fitmodelstructure.log +1161 -0
  64. data/test/fitmodelstructure/AgI/model.yaml +45 -0
  65. data/test/fitmodelstructure/normal/CONTCAR +17 -0
  66. data/test/fitmodelstructure/normal/fitmodelstructure.log +5063 -0
  67. data/test/fitmodelstructure/normal/model.yaml +122 -0
  68. data/test/fitmodelstructure/unidentified/CONTCAR +44 -0
  69. data/test/fitmodelstructure/unidentified/fitmodelstructure.log +8833 -0
  70. data/test/fitmodelstructure/unidentified/model.yaml +154 -0
  71. data/test/helper.rb +17 -0
  72. data/test/identifypolyhedralsites/.gitignore +1 -0
  73. data/test/identifypolyhedralsites/identifyatomsites.log +333 -0
  74. data/test/identifypolyhedralsites/normal/fitmodelstructure.yaml +60 -0
  75. data/test/identifypolyhedralsites/normal/model.yaml +122 -0
  76. data/test/identifypolyhedralsites/unidentified/fitmodelstructure.yaml +2 -0
  77. data/test/identifypolyhedralsites/unidentified/model.yaml +154 -0
  78. data/test/identifypolyhedralsites/volumemismatch/fitmodelstructure.yaml +101 -0
  79. data/test/identifypolyhedralsites/volumemismatch/model.yaml +154 -0
  80. data/test/identifyscattersites/CONTCAR +17 -0
  81. data/test/identifyscattersites/POSCAR +12 -0
  82. data/test/identifyscattersites/fitmodelstructure.log +1 -0
  83. data/test/identifyscattersites/fitmodelstructure.yaml +0 -0
  84. data/test/identifyscattersites/identifyscattersites.yaml +5 -0
  85. data/test/identifyscattersites/model.yaml +45 -0
  86. data/test/minexpconfiguration/.gitignore +1 -0
  87. data/test/minexpconfiguration/collective/AgI/.gitignore +2 -0
  88. data/test/minexpconfiguration/collective/AgI/siteoperations.yaml +51265 -0
  89. data/test/minexpconfiguration/collective/AgI/sitesingle.yaml +15 -0
  90. data/test/minexpconfiguration/collective/AgI/test.sh +2 -0
  91. data/test/minexpconfiguration/normal/identifysites.yaml +22 -0
  92. data/test/minexpconfiguration/normal/minexpconfiguration.log +0 -0
  93. data/test/minexpconfiguration/normal/siteoperations.yaml +1793 -0
  94. data/test/minexpconfiguration/unidentified/identifysites.yaml +2 -0
  95. data/test/minexpconfiguration/unidentified/siteoperations.yaml +1793 -0
  96. data/test/sitecombination/initsites.yaml +7 -0
  97. data/test/sitecombination/initsites_test2.yaml +8 -0
  98. data/test/sitecombination/sitecombination.yaml +29 -0
  99. data/test/siteconfiguration/elements-sitenames.yaml +2 -0
  100. data/test/siteconfiguration/latticeaxes.yaml +3 -0
  101. data/test/siteconfiguration/sitenames-coordinates.yaml +4 -0
  102. data/test/sitemigrationsdistance/model.yaml +45 -0
  103. data/test/siteoperations/.gitignore +2 -0
  104. data/test/siteoperations/model.yaml +43 -0
  105. data/test/siteoperations/symmetryoperations.yaml +1441 -0
  106. data/test/sitesingle/.gitignore +1 -0
  107. data/test/sitesingle/sitecombination.yaml +29 -0
  108. data/test/siteuniq/minexpconfiguration.yaml +15 -0
  109. data/test/siteuniq/siteuniq.yaml +8 -0
  110. data/test/test_atom.rb +206 -0
  111. data/test/test_cell.rb +604 -0
  112. data/test/test_commands.rb +340 -0
  113. data/test/test_crystana.rb +7 -0
  114. data/test/test_frameatom.rb +22 -0
  115. data/test/test_frameinterstitialcell.rb +939 -0
  116. data/test/test_interstitialatom.rb +22 -0
  117. data/test/test_modelstructure.rb +807 -0
  118. data/test/test_optionmanager.rb +172 -0
  119. data/test/test_site.rb +40 -0
  120. data/test/test_siteconfiguration.rb +29 -0
  121. data/test/test_sitenamelabeledcell.rb +528 -0
  122. data/test/test_siteoperation.rb +79 -0
  123. data/test/test_sitewithposition.rb +20 -0
  124. data/test/test_transitionfinder.rb +432 -0
  125. data/test/transitcell/.gitignore +2 -0
  126. data/test/transitcell/collectcells.yaml +51 -0
  127. data/test/transitcell/sitemigrations.yaml +8 -0
  128. data/test/transitcell/siteoperations.yaml +17 -0
  129. data/test/transitcell/transitcell.log +1342 -0
  130. data/test/transitionfinder/collectcells.yaml +81 -0
  131. data/test/transitionfinder/sitemigrations.yaml +33 -0
  132. data/test/transitionfinder/siteoperations.yaml +16 -0
  133. data/test/transitionfinder/test_cell.rb +287 -0
  134. data/test/transitionfinder/test_cellmanager.rb +185 -0
  135. data/test/transitionfinder/test_edge.rb +49 -0
  136. data/test/uniquesitesgenerator/elements-sitenames.yaml +1 -0
  137. data/test/uniquesitesgenerator/siteoperations.yaml +9 -0
  138. metadata +406 -0
data/lib/crysna.rb ADDED
@@ -0,0 +1,26 @@
1
+ require "rubygems"
2
+ require "mageo"
3
+ require "crystalcell"
4
+ require "vasputils"
5
+ require "progressbar"
6
+
7
+ module Crysna; end
8
+
9
+ require "crysna/frameatom"
10
+ require "crysna/frameinterstitialcell"
11
+ require "crysna/interstitialatom"
12
+ require "crysna/site"
13
+ require "crysna/atom"
14
+ require "crysna/sitewithposition"
15
+ require "crysna/siteconfiguration"
16
+ require "crysna/modelstructure"
17
+ require "crysna/cell"
18
+ require "crysna/optionmanager"
19
+ require "crysna/sitenamelabeledcell"
20
+ require "crysna/siteoperation"
21
+ require "crysna/transitionfinder"
22
+ require "crysna/transitionfinder/cell"
23
+ require "crysna/transitionfinder/cellmanager"
24
+ require "crysna/transitionfinder/edge"
25
+ #require "crysna/transitionfinder/edgemanager"
26
+ #require "crysna/uniquesitesgenerator"
@@ -0,0 +1,97 @@
1
+ #! /usr/bin/env ruby
2
+ # coding: utf-8
3
+
4
+ #Site with element info.
5
+ #This doesn't have coordinates.
6
+ #
7
+ class Crysna::Atom
8
+ attr_reader :element
9
+ attr_reader :site
10
+
11
+ #
12
+ def initialize(element, sitename, global_vector)
13
+ @element = element
14
+ @site = Crysna::Site.new(sitename, global_vector)
15
+ end
16
+
17
+ def ==(other)
18
+ return false unless self.element == other.element
19
+ return false unless self.site == other.site
20
+ return true
21
+ end
22
+
23
+ def migrate!(site_name, global_vector)
24
+ new_gvec = @site.global_vector + global_vector.to_v3di
25
+ @site = Crysna::Site.new(site_name, new_gvec)
26
+ end
27
+
28
+ def migrate(site_name, global_vector)
29
+ result = Marshal.load(Marshal.dump(self))
30
+ result.migrate!(site_name, global_vector)
31
+ result
32
+ end
33
+
34
+ # Return center-migrate atom.
35
+ # Therefore, global_vector becomes [0,0,0]
36
+ def centering
37
+ result = Marshal.load(Marshal.dump(self))
38
+ result.centering!
39
+ result
40
+ end
41
+
42
+ # Destructive migrate to center cell.
43
+ # Therefore, global_vector becomes [0,0,0]
44
+ def centering!
45
+ self.migrate!(@site.name, @site.global_vector * (-1))
46
+ end
47
+
48
+
49
+ #Mainly for sort
50
+ def <=>(other)
51
+ flag = @element <=> other.element
52
+ return flag unless flag == 0
53
+
54
+ flag = @site.name <=> other.site.name
55
+ return flag unless flag == 0
56
+
57
+ flag = @site.global_vector[0] <=> other.site.global_vector[0]
58
+ return flag unless flag == 0
59
+
60
+ flag = @site.global_vector[1] <=> other.site.global_vector[1]
61
+ return flag unless flag == 0
62
+
63
+ flag = @site.global_vector[2] <=> other.site.global_vector[2]
64
+ return flag
65
+ end
66
+
67
+ ##Not-destructive method for site migration.
68
+ #def migrate(name, g_vector)
69
+ # result = Marshal.load(Marshal.dump(self))
70
+ # result.migrate!(name, g_vector)
71
+ # return result
72
+ #end
73
+
74
+ ##Destructive method for site migration.
75
+ #def migrate!(name, g_vector)
76
+ # @name = name
77
+ # @global_vector.size.times do |i|
78
+ # @global_vector[i] += g_vector[i]
79
+ # end
80
+ #end
81
+
82
+ #Return site name. E.g., "B"
83
+ def sitename
84
+ @site.name
85
+ end
86
+
87
+ #Return site name with suffix as global vector with the manner of cif.
88
+ #E.g., "B555"
89
+ def full_sitename
90
+ result = sitename
91
+ @site.global_vector.each do |i|
92
+ result += (i+5).to_i.to_s
93
+ end
94
+ result
95
+ end
96
+ end
97
+
@@ -0,0 +1,314 @@
1
+ #! /usr/bin/env ruby
2
+ # coding: utf-8
3
+
4
+ #require "yaml"
5
+ #require "crystal/cell2.rb"
6
+ #require "crystal/atom2.rb"
7
+
8
+ #
9
+ # 常にソートされたものを返す。
10
+ #
11
+ class Crysna::Cell
12
+ include Comparable
13
+
14
+ #attr_reader :energy
15
+ #attr_reader :atoms
16
+ #alias to_hash sites
17
+
18
+ class DuplicateSiteError < Exception; end
19
+ class TypeError < Exception; end
20
+ class NoEntryError < Exception; end
21
+
22
+ # sites は element を鍵、サイト名リストを値としたハッシュ。
23
+ # e.g., sites = { 0 => ["S00", "S01"], 1 => ["S02", "S03"], }
24
+ #def initialize(sites, energy = nil)
25
+ def initialize(sites)
26
+ @atoms = []
27
+ sites.each do |elem, names|
28
+ names.each do |name|
29
+ @atoms << Crysna::Atom.new(elem, name, [0,0,0])
30
+ end
31
+ end
32
+ end
33
+
34
+ def self.load_file(file)
35
+ self.new(YAML.load_file(file))
36
+ end
37
+
38
+ # Generate new instance by POCAR style indication.
39
+ # elems is like {'Ag'=>2, 'I'=>2}$
40
+ # sitenames is like ['2A', '2B', 'IA', 'IA']
41
+ def self.new_elems_sitenames(elems, sitenames)
42
+ sites = {}
43
+ elems.each do |elem, num|
44
+ site_elem = []
45
+ num.times { site_elem << sitenames.shift}
46
+ sites[elem] = site_elem
47
+ end
48
+ sites
49
+ self.new(sites)
50
+ end
51
+
52
+ #Return sorted @atoms
53
+ def atoms
54
+ @atoms.sort!
55
+ @atoms
56
+ end
57
+
58
+ #Return internal data with format at initialize
59
+ # e.g., { 0 => ["S00", "S01"], 1 => ["S02", "S03"]}
60
+ def sites
61
+ results = {}
62
+ @atoms.each do |atom|
63
+ elem = atom.element
64
+ sitename = atom.site.name
65
+ results[elem] = [] unless results.has_key? elem
66
+ results[elem] << sitename
67
+ end
68
+ results
69
+ end
70
+
71
+
72
+ # element が占有するサイト site_name を追加する。
73
+ # dup_check を true にすると、
74
+ # サイト名が重複したときに例外 Crysna::Cell::DuplicateSiteError
75
+ # を生じる。
76
+ # dup_check を false にすると、このチェックが行われない。
77
+ def add_atom(element, site_name, global_vector, dup_check = false)
78
+ if dup_check
79
+ @atoms.each do |atom|
80
+ if atom.site.name == site_name
81
+ raise DuplicateSiteError,
82
+ "#{site_name} is already occupied in #{@sites.inspect}"
83
+ end
84
+ end
85
+ end
86
+
87
+ @atoms << Crysna::Atom.new(element, site_name, global_vector)
88
+ @atoms.sort!
89
+ end
90
+
91
+
92
+ # Execute symmetry operation.
93
+ # site_operation is a hash;
94
+ # the key is old name,
95
+ # and the value is an array of
96
+ # [new_name, global_vector, rotation]
97
+ # matrix indicates operation to global vector.
98
+ def operate(site_operation)
99
+ #pp site_operation
100
+ @atoms.each do |atom|
101
+ #pp site_operation;exit
102
+ unless site_operation.keys.include?(atom.site.name)
103
+ raise NoEntryError, "#{atom.site.name} is not in #{site_operation.inspect}"
104
+ end
105
+ end
106
+
107
+ #result = Crysna::Cell.new({})
108
+ result = self.class.new({})
109
+ atoms.each do |atom|
110
+ op = site_operation[atom.site.name]
111
+ new_name, shift_vector, rotation = *op
112
+ pos =
113
+ Matrix[* rotation] * atom.site.global_vector +
114
+ Mageo::Vector3DInternal[* shift_vector]
115
+ new_vector = Mageo::Vector3DInternal[* pos]
116
+
117
+ result.add_atom(atom.element, new_name, new_vector)
118
+ end
119
+
120
+ return result
121
+ end
122
+
123
+ def ==(other)
124
+ return false unless atoms.sort == other.atoms.sort
125
+ return true
126
+ end
127
+
128
+ # self に対して1つ原子を追加したときにありうる
129
+ # 全ての Crysna::Cell を配列にして返す。
130
+ # site_candidates は元素名を鍵、サイトリストを値としたハッシュ。
131
+ #
132
+ # dup_check は重複サイトチェック。
133
+ # 重複サイトに複数の原子が入る場合を判定する。
134
+ # dup_check が true だと返される結果に該当項目が含まれない。
135
+ # dup_check が false だと返される結果に該当項目が含まれる。
136
+ #
137
+ # site_candidates に含まれていないサイトが self に含まれていても
138
+ # エラーにはせず含まれたまま処理する。
139
+ def added_sites(site_candidates, dup_check = false)
140
+ results = []
141
+ site_candidates.each do |element, added_sites|
142
+ added_sites.each do |added_site|
143
+ site_config = Marshal.load(Marshal.dump(self))
144
+ begin
145
+ site_config.add_atom(element, added_site, [0, 0, 0], dup_check)
146
+ rescue DuplicateSiteError
147
+ next
148
+ end
149
+ results << site_config
150
+ end
151
+ end
152
+ return results
153
+ end
154
+
155
+ ## Return element list, which is unique and sorted.
156
+ def elements
157
+ @atoms.map{|atom| atom.element}.sort.uniq
158
+ end
159
+
160
+ def atoms_of_element(element)
161
+ results = []
162
+ atoms.each do |atom|
163
+ results << atom if atom.element == element
164
+ end
165
+ results.sort
166
+ end
167
+
168
+ # Destructive migrate all atoms to center cell.
169
+ # Therefore, global_vector becomes [0,0,0]
170
+ def centering!
171
+ @atoms.map! do |atom|
172
+ atom.centering
173
+ end
174
+ return self
175
+ end
176
+
177
+ # Return center-migrateed cell with all atoms.
178
+ # Therefore, global_vector becomes [0,0,0]
179
+ def centering
180
+ result = Marshal.load(Marshal.dump(self))
181
+ result.centering!
182
+ result
183
+ end
184
+
185
+
186
+ # compare
187
+ # configuration_string で比較する。
188
+ ### old
189
+ ### 元素名ソートで若いものから優先して比較する。
190
+ ### Enumerable の min もしくは max メソッドで一意のものが導き出さ
191
+ ### れさえすれば良いので、大小の物理的な意味はあまり深く考えない。
192
+ ### 当面の基準は、以下:
193
+ ### - 含まれる元素リストをソートした配列で比較し、
194
+ ### 違えばこれを返す。
195
+ ### このチェックを通過したら含まれる元素は
196
+ ### 同じということになる。
197
+ ### - 元素名でソートして番号の若いものから優先的に
198
+ ### サイト名の配列で比較。
199
+ ### 違えばこれを返す。
200
+ ### 全ての元素について行う。
201
+ ### - これらのチェックを通過すれば等しい。
202
+ def <=>(other)
203
+ self.configuration_string <=> other.configuration_string
204
+
205
+ ###self_tmp = self.centering
206
+ ###other_tmp = other.centering
207
+ ###raise TypeError unless other_tmp.is_a? Crysna::Cell
208
+ ###
209
+ ####pp self_tmp.configuration_string_full
210
+ ####pp other_tmp.configuration_string_full
211
+ ###
212
+ ###elems = (self_tmp.elements + other_tmp.elements).sort.uniq
213
+ ###
214
+ ###elems.each do |element|
215
+ ### self_tmp_atoms = atoms_of_element(element)
216
+ ### other_tmp_atoms = other_tmp.atoms_of_element(element)
217
+ ###
218
+ ### flag = self_tmp_atoms.size <=> other_tmp_atoms.size
219
+ ### #pp self_tmp_atoms.size
220
+ ### #pp other_tmp_atoms.size
221
+ ### return flag unless flag == 0
222
+ ###
223
+ ### flag = self_tmp_atoms <=> other_tmp_atoms
224
+ ###
225
+ ### return flag unless flag == 0
226
+ ### self_tmp_atoms.size.times do |i|
227
+ ### #pp self_tmp_atoms[i]
228
+ ### #pp other_tmp_atoms[i]
229
+ ### flag = self_tmp_atoms[i] <=> other_tmp_atoms[i]
230
+ ### return flag unless flag == 0
231
+ ### end
232
+ ###end
233
+ ###
234
+ ###return 0
235
+ end
236
+
237
+ #Return the cell which is the first in sort.
238
+ def minimize(operations, io = File.open(File::NULL, "w"))
239
+ min = self
240
+ io.puts "in Cell::minimize()"
241
+ operations.each do |ope|
242
+ id = ope['operation_id']
243
+ operation = ope['operation']
244
+
245
+ io.puts "operation_id: " + id.to_s
246
+ new = self.operate(operation)
247
+ new.atoms.each do |atom|
248
+ io.puts "#{atom.site.name}#{atom.site.global_vector.to_a}"
249
+ end
250
+ if new < min
251
+ min = new
252
+ io.puts "min is updated"
253
+ end
254
+
255
+ io.puts
256
+ end
257
+ return min
258
+ end
259
+
260
+ #Output yaml format.
261
+ #Note that global_vector is discarded.
262
+ def to_yaml
263
+ results = {}
264
+ atoms.each do |atom|
265
+ results[atom.element] ||= []
266
+ results[atom.element] << atom.site.name
267
+ end
268
+ YAML.dump(results)
269
+ end
270
+
271
+ # CrystalCell::Cell クラスインスタンスを返す。
272
+ # 引数 axes は格子ベクトルを絶対座標で表したもの。
273
+ # 引数 sites_coordinates はサイト名を鍵、内部座標を値とするハッシュ。
274
+ def to_cell(axes, sites_coordinates)
275
+ la = CrystalCell::LatticeAxes.new(axes)
276
+ cc_atoms = []
277
+ atoms.each do |atom|
278
+ cc_atoms << CrystalCell::Atom.new(atom.element, sites_coordinates[atom.site.name])
279
+ end
280
+ CrystalCell::Cell.new(la, cc_atoms)
281
+ end
282
+
283
+ def [](index)
284
+ atoms[index]
285
+ end
286
+
287
+ #Return string to which sitenames of atoms are joined.
288
+ #Ignoreing their elements.
289
+ #For example, "ABCD"
290
+ def configuration_string
291
+ #atoms.map do |atom|
292
+ # atom.sitename
293
+ #end . join("")
294
+ result = elements.map do |elem|
295
+ "#{elem}:" +
296
+ atoms_of_element(elem).map {|atom| atom.sitename}.join("-")
297
+ end .join(",")
298
+ result
299
+ end
300
+
301
+ #Return string to which configuration_string_full of atoms are joined.
302
+ #Ignoreing their elements.
303
+ #For example, "A555-B455-C556-D555"
304
+ #Note: suffix of arabic number is the same manner of CIF indices.
305
+ def configuration_string_full
306
+ result = elements.map do |elem|
307
+ "#{elem}:" +
308
+ atoms_of_element(elem).map {|atom| atom.full_sitename}.join("-")
309
+ end .join(",")
310
+ result
311
+ end
312
+
313
+ end
314
+
@@ -0,0 +1,13 @@
1
+ #! /usr/bin/env ruby
2
+ # coding: utf-8
3
+
4
+ #require "crystal/atom2.rb"
5
+
6
+ #
7
+ # Class for frame atom.
8
+ # This class is the same as CrystalCell::Atom, except for the class name.
9
+ # This class is assumed to be used in FrameInterstitialCell.
10
+ #
11
+ class FrameAtom < CrystalCell::Atom
12
+ end
13
+