crysna 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+