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
48
49
# File 'lib/crystalcell/atom.rb', line 36

def initialize(element, position, name = nil, movable_flags = nil)
    #p position
    #p position.methods.sort
    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)


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

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.



76
77
78
79
80
# File 'lib/crystalcell/atom.rb', line 76

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)


86
87
88
# File 'lib/crystalcell/atom.rb', line 86

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.



91
92
93
94
# File 'lib/crystalcell/atom.rb', line 91

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

#set_position(position) ⇒ Object

Overwrite position.

Raises:



104
105
106
107
108
109
# File 'lib/crystalcell/atom.rb', line 104

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.



123
124
125
126
127
# File 'lib/crystalcell/atom.rb', line 123

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:



114
115
116
117
118
# File 'lib/crystalcell/atom.rb', line 114

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.



98
99
100
101
# File 'lib/crystalcell/atom.rb', line 98

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