Class: CrystalCell::Atom

Inherits:
Object
  • Object
show all
Includes:
Mageo
Defined in:
lib/crystalcell/atom.rb

Overview

Class for an atom in a cell. This class doesn’t have lattice information. Forbid changes in internal information. When you want to change, you can make a new instance. This class is not assumeed in a periodic condition.

Defined Under Namespace

Classes: TypeError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(element, position, name = nil, movable_flags = nil) ⇒ Atom

Arguments:

elements:
    Identifier of a element.
    This may be String like "Li", Integer like 0, or other class instances.
    Why doesn't this class have concrete name of elements?
    The reason is below:
        - This class is assumed to be used in Cell class instances.
            When we treat symmetry of the cell, the elements of atoms are not necessary information.
            This specification enable highly abstract level of treatment of cells.
        - POSCAR file of VASP (before ver.4 series) don't have element information.
            This specification enable to use POSCAR directly without POTCAR or element indication.
position:
    Coordinates of an atom.
    This argument 'position' is mainly assumed as a internal coordinate.
name:
    Identifier of an atom, e.g., "Li1" or "O23".
movable_flags: 
    Movable flags of an atom in each of three directions as a Array of three items.

Raises:



36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/crystalcell/atom.rb', line 36

def initialize(element, position, name = nil, movable_flags = nil)
  raise TypeError, "Position doesn't have []: (#{position.inspect})" unless position.methods.include?(:[])
  raise TypeError, "Number of items in position is not 3: (#{position})" if position.size != 3
  raise TypeError, "Coordinate is not a Float: (#{position})" if position[0].class != Float
  raise TypeError, "Coordinate is not a Float: (#{position})" if position[1].class != Float
  raise TypeError, "Coordinate is not a Float: (#{position})" if position[2].class != Float

  @element = element
  set_position(position)
  @name = name
  @movable_flags = movable_flags
end

Instance Attribute Details

#elementObject

Returns the value of attribute element.



16
17
18
# File 'lib/crystalcell/atom.rb', line 16

def element
  @element
end

#movable_flagsObject (readonly)

Do not change :position to attr_accessor. This must be Vector3DInternal instance.



15
16
17
# File 'lib/crystalcell/atom.rb', line 15

def movable_flags
  @movable_flags
end

#nameObject

Returns the value of attribute name.



16
17
18
# File 'lib/crystalcell/atom.rb', line 16

def name
  @name
end

#positionObject

Returns the value of attribute position.



16
17
18
# File 'lib/crystalcell/atom.rb', line 16

def position
  @position
end

Class Method Details

.equal_in_delta?(atom0, atom1, tol = 0.0) ⇒ Boolean

Equivalence checking (class method version). Return true when all the condition below are satisfied:

- same element identifier.
- difference of coordinates is within tolerance.

Note that distance cannot be used since this class doesn’t have a lattice axes. Imagine the shape of tolerant zone is a hexahedron.

Returns:

  • (Boolean)


57
58
59
60
61
62
63
# File 'lib/crystalcell/atom.rb', line 57

def self.equal_in_delta?(atom0, atom1, tol = 0.0)
  return false if atom0.element != atom1.element
  3.times do |i|
    return false if ((atom0.position[i] - atom1.position[i]).abs > tol)
  end
  return true
end

Instance Method Details

#==(other) ⇒ Object

Restricted equivalence checking. Return true when all the condition below are satisfied:

- same element identifier.
- difference of coordinates is the same.

This method should be used after well-consideration. Arbitrary coordinates are not generally the same like Float instances. It is a good idea to use in test scripts.



74
75
76
77
78
# File 'lib/crystalcell/atom.rb', line 74

def ==(other)
  #pp self
  #pp other
  self.class.equal_in_delta?(self, other, 0.0)
end

#equal_in_delta?(other, tol = 0.0) ⇒ Boolean

Equivalence checking (instance method version) . Return true when all the condition below are satisfied:

- same element identifier.
- difference of coordinates is within tolerance.

Returns:

  • (Boolean)


84
85
86
# File 'lib/crystalcell/atom.rb', line 84

def equal_in_delta?(other, tol = 0.0)
  self.class.equal_in_delta?(self, other, tol)
end

#internal_coordinatesObject

Return Vector3DInternal instance consist of coordinates between 0 and 1.



89
90
91
92
# File 'lib/crystalcell/atom.rb', line 89

def internal_coordinates
  result = @position.map{ |coord| coord - coord.floor }
  return Vector3DInternal[ *result ]
end

#set_position(position) ⇒ Object

Overwrite position.

Raises:



102
103
104
105
106
107
# File 'lib/crystalcell/atom.rb', line 102

def set_position(position)
  #pp position
  #pp position.class
  raise TypeError, "#{position.class}" if position.class == Vector3D
  @position = position.to_v3di
end

#translate(vec) ⇒ Object

Translate atom position (nondestructive). Argument ‘vec’ should be given as internal vector, which is an Array or Vector3DInternal instance but Vector3D instance.



121
122
123
124
125
# File 'lib/crystalcell/atom.rb', line 121

def translate(vec)
  tmp = Marshal.load(Marshal.dump(self))
  tmp.translate!(vec)
  return tmp
end

#translate!(vec) ⇒ Object

Translate atom position (destructive). Argument ‘vec’ should be given as internal vector, which is an Array or Vector3DInternal instance but Vector3D instance.

Raises:



112
113
114
115
116
# File 'lib/crystalcell/atom.rb', line 112

def translate!(vec)
  raise TypeError if vec.class == Vector3D
  raise TypeError if vec.size != 3
  self.set_position(@position + Vector3DInternal[ *vec ])
end

#translation_symmetry_operationObject

Return Vector3DInternal instance consist of integers, by which self.internal_coordinates translate to self.position.



96
97
98
99
# File 'lib/crystalcell/atom.rb', line 96

def translation_symmetry_operation
  result = @position.map{ |coord| coord.floor }
  return Vector3DInternal[ *result ]
end