class CrystalCell::LatticeAxes

Class to deal with lattice axes in three dimensional space, related to cell parameter and crystal axes. Lattice information cannot be changed after initialized.

When lattice axes of three vectors are given, lattice axes are automatically converted as below.

- c axes in internal axis is along to z axis in cartesian axis.
- b axes in internal axis is on the b-c plane.
- a axes in internal axis is set to be a right-hand system.
E.g., 
    [ [0.5, 0.5, 0.0], [0.5, 0.0, 0.5], [0.0, 0.5, 0.5] ]
    will be converted to 
    [ [0.57735, 0.20412, 0.35355],
        [0.00000, 0.61237, 0.35355],
        [0.00000, 0.00000, 0.70710]]

Attributes

axes[R]

Public Class Methods

axes_to_lc(axes) click to toggle source

Convert three axes to six lattice constants.

# File lib/crystalcell/latticeaxes.rb, line 83
def self.axes_to_lc(axes)
  axes.collect!{|i| Vector3D[*i] }
  a = axes[0].r
  b = axes[1].r
  c = axes[2].r
  alpha = axes[1].angle_degree(axes[2])
  beta    = axes[2].angle_degree(axes[0])
  gamma = axes[0].angle_degree(axes[1])
  return [ a, b, c, alpha, beta, gamma ]
end
lc_to_axes(lc, righthand = true) click to toggle source

Convert six lattice constants to three axes. Set true to the argument of 'righthand' if a assumed lattice has righthand axis system.

# File lib/crystalcell/latticeaxes.rb, line 62
def self.lc_to_axes(lc, righthand = true)
  raise ArgumentError if (lc.size != 6)

  a = lc[0]
  b = lc[1]
  c = lc[2]
  alpha = (2.0*PI) * lc[3] / 360.0 # radian
  beta    = (2.0*PI) * lc[4] / 360.0 # radian
  gamma = (2.0*PI) * lc[5] / 360.0 # radian

  v_c = Vector3D[0.0, 0.0, c]
  v_b = Vector3D[0.0, b * Math::sin(alpha), b * Math::cos(alpha)]
  v_a_z = a * Math::cos(beta)
  v_a_y = (a * (Math::cos(gamma) - Math::cos(alpha) * Math::cos(beta)))/ Math::sin(alpha)
  v_a_x = Math::sqrt(a**2 - v_a_y**2 - v_a_z**2)
  v_a_x *= -1.0 if righthand == false
  v_a = Vector3D[v_a_x, v_a_y, v_a_z]
  return [v_a, v_b, v_c]
end
lefthand?(axes) click to toggle source

Return true if the relation of vector order is lefthand system.

# File lib/crystalcell/latticeaxes.rb, line 102
def self.lefthand?(axes)
  axes.map! { |i| Vector3D[*i] }
  return true if Vector3D.scalar_triple_product(*axes) < 0.0
  return false
end
new(vectors) click to toggle source

Argument 'vectors' is three vectors with the order of a, b, c. If you want to make LatticeAxes instances from lattice constants, you should convert to axes with LatticeAxes.lc_to_axes 任意の向きのベクトルを渡しても、必ず triangulate する。

Calls superclass method
# File lib/crystalcell/latticeaxes.rb, line 35
def initialize(vectors)
  raise InitializeError, "#{vectors.inspect}" unless vectors.size == 3

  if vectors.class == CrystalCell::LatticeAxes
    @axes = vectors
  else
    begin
      vectors = self.class.triangulate(vectors)
    rescue Vector3D::RangeError
      raise InitializeError, "#{vectors.inspect}"
    end

    super(vectors)
  end
end
new_lc(lc) click to toggle source

Generate new instance from lattice constants.

# File lib/crystalcell/latticeaxes.rb, line 55
def self.new_lc(lc)
  vec = CrystalCell::LatticeAxes.lc_to_axes(lc)
  CrystalCell::LatticeAxes.new(vec)
end
righthand?(axes) click to toggle source

Return true if the relation of vector order is righthand system.

# File lib/crystalcell/latticeaxes.rb, line 95
def self.righthand?(axes)
  axes.map! { |i| Vector3D[*i] }
  return true if Vector3D.scalar_triple_product(*axes) > 0.0
  return false
end
triangulate(vectors) click to toggle source

Convert three axes to three axes with rules below:

c axis is along z axis in cartesian system.
b axis is on y-z plane in cartesian system.

Return an array of three Vector3D instances. This class does not convert righthand to lefthand system. The name of this method 'triangulate' originates from the matrix indicating the vectors being triangular matrix.

クラスメソッドは廃止の方向で。 vectors の数をチェックするのは initialize でやるべきことだろうし、 LatticeAxes クラスインスタンス以外で triangulate を使う場面が想像できない。

# File lib/crystalcell/latticeaxes.rb, line 120
def self.triangulate(vectors)
  vectors.map! { |i| Vector3D[*i] }
  raise InitializeError if self.dependent?(vectors)
  lc = self.axes_to_lc(vectors)
  righthand = self.righthand?(vectors)
  return self.lc_to_axes(lc, righthand)
end

Public Instance Methods

*(val) click to toggle source

Multiply all vectors. Not destructive.

# File lib/crystalcell/latticeaxes.rb, line 186
def *(val)
  #result = Marshal.load(Marshal.dump(self))

  self.class.new(@axes.map{|vec| vec * val})
end
==(other) click to toggle source
# File lib/crystalcell/latticeaxes.rb, line 176
def ==(other)
  3.times do |i|
    3.times do |j|
      return false if self[i][j] != other[i][j]
    end
  end
  return true
end
equal_in_delta?(other, length_ratio, angle_tolerance) click to toggle source

Compare <other> CrystalCell::LatticeAxes instance. <length_ratio> is tolerance of ratio in length of axes. <angle_tolerance> is tolerance of value in angle between axes.

# File lib/crystalcell/latticeaxes.rb, line 161
def equal_in_delta?(other, length_ratio, angle_tolerance)
  length_a = self .get_lattice_constants[0..2]
  length_b = other.get_lattice_constants[0..2]
  3.times do |i|
    return false unless ((length_a[i] - length_b[i]).abs <= length_ratio)
  end

  angle_a  = self .get_lattice_constants[3..5]
  angle_b  = other.get_lattice_constants[3..5]
  3.times do |i|
    return false unless ((angle_a[i] - angle_b[i]).abs <=    angle_tolerance)
  end
  return true
end
get_lattice_constants() click to toggle source

Get lattice constants in six values.

# File lib/crystalcell/latticeaxes.rb, line 131
def get_lattice_constants
  return CrystalCell::LatticeAxes.axes_to_lc(@axes)
end
lefthand?() click to toggle source
# File lib/crystalcell/latticeaxes.rb, line 139
def lefthand?
  self.class.lefthand?(@axes)
end
righthand?() click to toggle source
# File lib/crystalcell/latticeaxes.rb, line 135
def righthand?
  self.class.righthand?(@axes)
end
to_a() click to toggle source
# File lib/crystalcell/latticeaxes.rb, line 192
def to_a
  @axes.map{|v| v.to_a}
end

Private Instance Methods

triangulate() click to toggle source
# File lib/crystalcell/latticeaxes.rb, line 198
def triangulate
  #self.class.triangulate(@axes)
# rotate(2, 2, 1)
# rotate(2, 0, 2)
# rotate(1, 2, 1)
end