quaternion.f90 Source File

This File Depends On

sourcefile~~quaternion.f90~~EfferentGraph sourcefile~quaternion.f90 quaternion.f90 sourcefile~tensor.f90 tensor.f90 sourcefile~tensor.f90->sourcefile~quaternion.f90 sourcefile~kinds.f90 kinds.f90 sourcefile~kinds.f90->sourcefile~quaternion.f90 sourcefile~kinds.f90->sourcefile~tensor.f90
Help

Files Dependent On This One

sourcefile~~quaternion.f90~~AfferentGraph sourcefile~quaternion.f90 quaternion.f90 sourcefile~testquaternion.f90 testQuaternion.f90 sourcefile~quaternion.f90->sourcefile~testquaternion.f90
Help

Source Code


Source Code

module quaternion_mod
	!! Module for working with quaternions
	!! @todo
	!! Add documentation
	use kinds_mod
	use tensor_mod
	implicit none
	private
	
	!=========!
	!= Types =!
	!=========!
	
	type::quat_t
		!! Hamilton's quaternion extension to complex numbers
		real(wp)::s = 0.0_wp
			!! Scalar part
		real(wp),dimension(3)::v = 0.0_wp
			!! Vector part
	contains
		procedure::getRotationMatrix
	end type
	
	!==============!
	!= Interfaces =!
	!==============!
	
	interface quat_t
		module procedure newQuat
	end interface
	
	interface norm2
		module procedure norm2_q
	end interface
	
	interface conjg
		module procedure conjg_q
	end interface
	
	interface exp
		module procedure exp_q
	end interface
	
	interface log
		module procedure log_q
	end interface
	
	interface log10
		module procedure log10_q
	end interface
	
	interface operator(+)
		module procedure add_rq
		module procedure add_qr
		module procedure add_vq
		module procedure add_qv
		module procedure add_qq
	end interface
	
	interface operator(-)
		module procedure sub_rq
		module procedure sub_qr
		module procedure sub_vq
		module procedure sub_qv
		module procedure sub_qq
	end interface
	
	interface operator(*)
		module procedure mul_rq
		module procedure mul_qr
		module procedure mul_vq
		module procedure mul_qv
		module procedure mul_qq
	end interface
	
	interface operator(/)
		module procedure div_qr
	end interface
	
	!===========!
	!= Exports =!
	!===========!
	
	public::quat_t
	
	public::scaler
	public::vector
	
	public::norm2
	public::conjg
	public::inv
	
	public::exp
	public::log
	public::log10
	
	public::operator(+)
	public::operator(-)
	public::operator(*)
	public::operator(/)
	
contains

	!==================!
	!= Basic Routines =!
	!==================!

	function newQuat(r,v) result(self)
		real(wp),intent(in)::r
		real(wp),dimension(3),intent(in)::v
		type(quat_t)::self
		
		self%s = r
		self%v = v
	end function newQuat

	elemental function scaler(q) result(o)
		!! Return the scalar part of the quaternion
		type(quat_t),intent(in)::q
			!! The quaternion of interest
		real(wp)::o
		
		o = q%s
	end function scaler

	function vector(q) result(o)
		!! Return the vector part of the quaternion
		type(quat_t),intent(in)::q
			!! The quaternion of interest
		real(wp),dimension(3)::o
		
		o = q%v
	end function vector

	elemental function norm2_q(q) result(o)
		!! Return the magnitude of the quaternion
		type(quat_t),intent(in)::q
			!! The quaternion of interest
		real(wp)::o
		
		o = sqrt(q%s**2+sum(q%v**2))
	end function norm2_q

	elemental function conjg_q(q) result(o)
		!! Return the conjugate of the quaternion
		type(quat_t),intent(in)::q
			!! The quaternion of interest
		type(quat_t)::o
		
		o%s =  q%s
		o%v = -q%v
	end function conjg_q

	elemental function inv(q) result(o)
		!! Return the inverse of the quaternion
		type(quat_t),intent(in)::q
			!! The quaternion of interest
		type(quat_t)::o
		
		o = conjg(q)/norm2(q)**2
	end function inv

	!==============================!
	!= Standard Function Routines =!
	!==============================!

	elemental function exp_q(q) result(o)
		!! Take the exponent of a quaternion
		type(quat_t),intent(in)::q
			!! The quaternion of interest
		type(quat_t)::o
		
		real(wp)::vm
		
		vm = norm2(q%v)
		
		o%s = exp(q%s)*( cos(vm) )
		o%v = exp(q%s)*( q%v/vm*sin(vm) )
	end function exp_q

	elemental function log_q(q) result(o)
		!! Take the natural log of a quaternion
		type(quat_t),intent(in)::q
			!! The quaternion of interest
		type(quat_t)::o
		
		real(wp)::vm,qm
		
		vm = norm2(q%v)
		qm = norm2(q)
		
		o%s = log(qm)
		o%v = q%v/vm*acos(q%s/qm)
	end function log_q

	elemental function log10_q(q) result(o)
		!! Take the log10 of a quaternion
		type(quat_t),intent(in)::q
			!! The quaternion of interest
		type(quat_t)::o
		
		o = log(q)/log(10.0_wp)
	end function log10_q

	!================!
	!= Add Routines =!
	!================!

	elemental function add_rq(r,q) result(o)
		real(wp),intent(in)::r
		type(quat_t),intent(in)::q
		type(quat_t)::o
		
		o%s = r+q%s
		o%v = q%v
	end function add_rq

	elemental function add_qr(q,r) result(o)
		type(quat_t),intent(in)::q
		real(wp),intent(in)::r
		type(quat_t)::o
		
		o%s = q%s+r
		o%v = q%v
	end function add_qr

	pure function add_vq(v,q) result(o)
		real(wp),dimension(3),intent(in)::v
		type(quat_t),intent(in)::q
		type(quat_t)::o
		
		o%s = q%s
		o%v = v+q%v
	end function add_vq

	pure function add_qv(q,v) result(o)
		type(quat_t),intent(in)::q
		real(wp),dimension(3),intent(in)::v
		type(quat_t)::o
		
		o%s = q%s
		o%v = q%v+v
	end function add_qv

	elemental function add_qq(u,v) result(o)
		type(quat_t),intent(in)::u
		type(quat_t),intent(in)::v
		type(quat_t)::o
		
		o%s = u%s+v%s
		o%v = u%v+v%v
	end function add_qq

	!=====================!
	!= Subtract Routines =!
	!=====================!

	elemental function sub_rq(r,q) result(o)
		real(wp),intent(in)::r
		type(quat_t),intent(in)::q
		type(quat_t)::o
		
		o%s = r-q%s
		o%v = -q%v
	end function sub_rq

	elemental function sub_qr(q,r) result(o)
		type(quat_t),intent(in)::q
		real(wp),intent(in)::r
		type(quat_t)::o
		
		o%s = q%s-r
		o%v = q%v
	end function sub_qr

	pure function sub_vq(v,q) result(o)
		real(wp),dimension(3),intent(in)::v
		type(quat_t),intent(in)::q
		type(quat_t)::o
		
		o%s = -q%s
		o%v = v-q%v
	end function sub_vq

	pure function sub_qv(q,v) result(o)
		type(quat_t),intent(in)::q
		real(wp),dimension(3),intent(in)::v
		type(quat_t)::o
		
		o%s = q%s
		o%v = q%v-v
	end function sub_qv

	elemental function sub_qq(u,v) result(o)
		type(quat_t),intent(in)::u
		type(quat_t),intent(in)::v
		type(quat_t)::o
		
		o%s = u%s-v%s
		o%v = u%v-v%v
	end function sub_qq

	!===========================!
	!= Multiplication Routines =!
	!===========================!

	elemental function mul_rq(u,v) result(o)
		real(wp),intent(in)::u
		type(quat_t),intent(in)::v
		type(quat_t)::o
		
		o%s = u*v%s
		o%v = u*v%v
	end function mul_rq

	elemental function mul_qr(u,v) result(o)
		type(quat_t),intent(in)::u
		real(wp),intent(in)::v
		type(quat_t)::o
		
		o%s = u%s*v
		o%v = u%v*v
	end function mul_qr

	pure function mul_vq(u,v) result(o)
		real(wp),dimension(3),intent(in)::u
		type(quat_t),intent(in)::v
		type(quat_t)::o
		
		o%s = -(u.o.v%v)
		o%v = u*v%s+(u.x.v%v)
	end function mul_vq

	pure function mul_qv(u,v) result(o)
		type(quat_t),intent(in)::u
		real(wp),dimension(3),intent(in)::v
		type(quat_t)::o
		
		o%s = -(u%v.o.v)
		o%v = u%s*v+(u%v.x.v)
	end function mul_qv

	elemental function mul_qq(u,v) result(o)
		type(quat_t),intent(in)::u
		type(quat_t),intent(in)::v
		type(quat_t)::o
		
		o%s = u%s*v%s-(u%v.o.v%v)
		o%v = u%s*v%v+u%v*v%s+(u%v.x.v%v)
	end function mul_qq

	!=====================!
	!= Division Routines =!
	!=====================!

	elemental function div_qr(q,r) result(o)
		type(quat_t),intent(in)::q
		real(wp),intent(in)::r
		type(quat_t)::o
		
		o%s = q%s/r
		o%v = q%v/r
	end function div_qr

	!=======================!
	!= Quaternion Routines =!
	!=======================!

	function getRotationMatrix(self) result(o)
		class(quat_t),intent(in)::self
		real(wp),dimension(3,3)::o
		
		type(quat_t)::q
		real(wp)::a,b,c,d
		
		q = self/norm2(self)
		
		a = q%s
		b = q%v(1)
		c = q%v(2)
		d = q%v(3)
		
		o(1,1) = a**2 + b**2 - c**2 - d**2
		o(2,2) = a**2 - b**2 + c**2 - d**2
		o(3,3) = a**2 - b**2 - c**2 + d**2
		
		o(2,1) = 2.0_wp*b*c + 2.0_wp*a*d
		o(1,2) = 2.0_wp*b*c - 2.0_wp*a*d
		
		o(3,1) = 2.0_wp*b*d - 2.0_wp*a*c
		o(1,3) = 2.0_wp*b*d + 2.0_wp*a*c
		
		o(3,2) = 2.0_wp*c*d + 2.0_wp*a*b
		o(2,3) = 2.0_wp*c*d - 2.0_wp*a*b
	end function getRotationMatrix

end module quaternion_mod