module vector_class !! Vector class module. Defines a vector type (x, y, z) and associated operations on vectors and other types. use constants, only : wp implicit none !> Vector class type :: vector !> vector components real(kind=wp) :: x, y, z contains !> Returns the magnitude of the vector procedure :: magnitude => magnitude !> Returns the length of the vector procedure :: length => length !> .dot. operator. Dot product generic :: operator(.dot.) => vec_dot_vec, vec_dot_mat !> .cross. operator. Cross product generic :: operator(.cross.) => vec_cross_vec !> Overloads the Division operator for vec3 generic :: operator(/) => vec_div_scal_r4, vec_div_scal_r8, vec_div_scal_int !> Overloads the Multiplication operator for vec3 generic :: operator(*) => vec_mult_vec, vec_mult_scal, scal_mult_vec !> Overloads the exponential operator for vec3 generic :: operator(**) => vec_mult_exp_scal_int, vec_mult_exp_scal_r4, vec_mult_exp_scal_r8 !> Overloads the Addition operator for vec3 generic :: operator(+) => vec_add_vec, vec_add_scal, scal_add_vec !> Overloads the Subtraction operator for vec3 generic :: operator(-) => vec_minus_vec, vec_minus_scal, scal_minus_vec !> Overloads the equal operator for vec3 generic :: operator(==) => vec_equal_vec procedure, pass(a), private :: vec_dot_vec procedure, pass(a), private :: vec_dot_mat procedure, pass(a), private :: vec_cross_vec procedure, pass(a), private :: vec_div_scal_r4 procedure, pass(a), private :: vec_div_scal_r8 procedure, pass(a), private :: vec_div_scal_int procedure, pass(a), private :: vec_mult_vec procedure, pass(a), private :: vec_mult_scal procedure, pass(b), private :: scal_mult_vec procedure, pass(a), private :: vec_mult_exp_scal_int procedure, pass(a), private :: vec_mult_exp_scal_r4 procedure, pass(a), private :: vec_mult_exp_scal_r8 procedure, pass(a), private :: vec_add_vec procedure, pass(a), private :: vec_add_scal procedure, pass(b), private :: scal_add_vec procedure, pass(a), private :: vec_minus_vec procedure, pass(a), private :: vec_minus_scal procedure, pass(b), private :: scal_minus_vec procedure, pass(a), private :: vec_equal_vec end type vector private public :: magnitude, vector, abs, length, max, nint, min interface nint !! Overload of the nint intrinsic for a vec3 module procedure nint_vec end interface nint interface abs !! Overload of the abs intrinsic for a vec3 module procedure abs_vec end interface abs interface max !! Overload of the max intrinsic for a vec3 module procedure max_vec module procedure maxval_vec end interface max interface min !! Overload of the min intrinsic for a vec3 module procedure min_vec module procedure minval_vec end interface min contains type(vector) pure elemental function vec_mult_exp_scal_int(a, b) !! vec3**scalar for integer scalar !> Input Vector class(vector), intent(in) :: a !> Input scalar integer, intent(in) :: b vec_mult_exp_scal_int = vector(a%x**b, a%y**b, a%z**b) end function vec_mult_exp_scal_int type(vector) pure elemental function vec_mult_exp_scal_r4(a, b) !! vec3**scalar for 32-bit float scalar use constants, only : sp !> Input Vector class(vector), intent(in) :: a !> Input scalar real(kind=sp), intent(in) :: b vec_mult_exp_scal_r4 = vector(a%x**b, a%y**b, a%z**b) end function vec_mult_exp_scal_r4 type(vector) pure elemental function vec_mult_exp_scal_r8(a, b) !! vec3**scalar for 64-bit float scalar use constants, only : dp !> Input Vector class(vector), intent(in) :: a !> Input scalar real(kind=dp), intent(in) :: b vec_mult_exp_scal_r8 = vector(a%x**b, a%y**b, a%z**b) end function vec_mult_exp_scal_r8 logical pure elemental function vec_equal_vec(a, b) !! vec3 == vec3 !> Input vec3s class(vector), intent(in) :: a, b vec_equal_vec = .false. if(a%x == b%x)then if(a%y == b%y)then if(a%z == b%z)then vec_equal_vec = .true. end if end if end if end function vec_equal_vec type(vector) pure elemental function nint_vec(this) !! Overload the nint intrinsic for a vec3 elementwise !> Input vector type(vector), intent(IN) :: this nint_vec = vector(real(nint(this%x), kind=wp), real(nint(this%y), kind=wp), real(nint(this%z), kind=wp)) end function nint_vec type(vector) pure elemental function abs_vec(this) !! Calculate the absoulte of a vector elementwise !> Input vector type(vector), intent(IN) :: this abs_vec = vector(abs(this%x), abs(this%y), abs(this%z)) end function abs_vec type(vector) pure elemental function max_vec(this, val) !! Get the max value elementwise between a vec3 and a scalar !> Input vector type(vector), intent(IN) :: this !> Input max value real(kind=wp), intent(IN) :: val max_vec = vector(max(this%x, val), max(this%y, val), max(this%z, val)) end function max_vec type(vector) pure elemental function min_vec(this, val) !! Get the min value elementwise between a vec3 and a scalar !> Input vector type(vector), intent(IN) :: this !> Input minimum value real(kind=wp), intent(IN) :: val min_vec = vector(min(this%x, val), min(this%y, val), min(this%z, val)) end function min_vec real(kind=wp) pure elemental function maxval_vec(this) !! Get the max value in a vec3 !> Input vector type(vector), intent(IN) :: this maxval_vec = max(this%x, this%y, this%z) end function maxval_vec real(kind=wp) pure elemental function minval_vec(this) !! Get the min value in a vec3 !> Input vector type(vector), intent(IN) :: this minval_vec = min(this%x, this%y, this%z) end function minval_vec type(vector) pure elemental function vec_minus_vec(a, b) !! vec3 - vec3 !> Input vector class(vector), intent(IN) :: a !> vec3 to subtract type(vector), intent(IN) :: b vec_minus_vec = vector(a%x - b%x, a%y - b%y, a%z - b%z) end function vec_minus_vec type(vector) pure elemental function vec_add_scal(a, b) !! vec3 + scalar !> Input vector class(vector), intent(IN) :: a !> Scalar to add real(kind=wp), intent(IN) :: b vec_add_scal = vector(a%x + b, a%y + b, a%z + b) end function vec_add_scal type(vector) pure elemental function scal_add_vec(a, b) !! vec3 + scalar !> Input vector class(vector), intent(IN) :: b !> Scalar to add real(kind=wp), intent(IN) :: a scal_add_vec = vector(b%x + a, b%y + a, b%z + a) end function scal_add_vec type(vector) pure elemental function vec_minus_scal(a, b) !! vec3 - scalar !> Input vector class(vector), intent(IN) :: a !> Scalar to subtract real(kind=wp), intent(IN) :: b vec_minus_scal = vector(a%x - b, a%y - b, a%z - b) end function vec_minus_scal type(vector) pure elemental function scal_minus_vec(a, b) !! scalar - vec3 !> Input vector class(vector), intent(IN) :: b !> Scalar to subtract from real(kind=wp), intent(IN) :: a scal_minus_vec = vector(a - b%x, a - b%y, a - b%z) end function scal_minus_vec type(vector) pure elemental function vec_add_vec(a, b) !! vec3 + vec3 !> Input vector class(vector), intent(IN) :: a !> Vec3 to add type(vector), intent(IN) :: b vec_add_vec = vector(a%x + b%x, a%y + b%y, a%z + b%z) end function vec_add_vec pure elemental function vec_dot_vec(a, b) result (dot) !! vec3 . vec3 !> Input vec3 class(vector), intent(IN) :: a !> vec3 to dot type(vector), intent(IN) :: b real(kind=wp) :: dot dot = (a%x * b%x) + (a%y * b%y) + (a%z * b%z) end function vec_dot_vec pure function vec_dot_mat(a, b) result (dot) !! vec3 . matrix !> Input vec3 class(vector), intent(IN) :: a !> Matrix to dot with real(kind=wp), intent(IN) :: b(4, 4) type(vector) :: dot dot%x = b(1, 1)*a%x + b(2, 1)*a%y + b(3, 1)*a%z + b(4, 1)*1. dot%y = b(1, 2)*a%x + b(2, 2)*a%y + b(3, 2)*a%z + b(4, 2)*1. dot%z = b(1, 3)*a%x + b(2, 3)*a%y + b(3, 3)*a%z + b(4, 3)*1. end function vec_dot_mat pure elemental function vec_cross_vec(a, b) result(cross) !! vec3 x vec3 !> Input vector class(vector), intent(in) :: a !> vec3 to cross with type(vector), intent(in) :: b type(vector) :: cross cross%x = a%y*b%z - a%z*b%y cross%y = -a%x*b%z + a%z*b%x cross%z = a%x*b%y - a%y*b%x end function vec_cross_vec type(vector) pure elemental function vec_mult_vec(a, b) !! vec3 * vec3 elementwise !> input vec3 class(vector), intent(IN) :: a !> vec3 to multiply by type(vector), intent(IN) :: b vec_mult_vec = vector(a%x * b%x, a%y * b%y, a%z * b%z) end function vec_mult_vec type(vector) pure elemental function vec_mult_scal(a, b) !! vec3 * scalar elementwise !> input vec3 class(vector), intent(IN) :: a !> Scalar to multiply by real(kind=wp), intent(IN) :: b vec_mult_scal = vector(a%x * b, a%y * b, a%z * b) end function vec_mult_scal type(vector) pure elemental function scal_mult_vec(a, b) !! Scalar * vec3 elementwise !> input vec3 class(vector), intent(IN) :: b !> Scalar to multiply by real(kind=wp), intent(IN) :: a scal_mult_vec = vector(a * b%x, a * b%y, a * b%z) end function scal_mult_vec type(vector) pure elemental function vec_div_scal_r4(a, b) !! vec3 / scalar elementwise. Scalar is a 32-bit float use constants, only : sp !> input vec3 class(vector), intent(IN) :: a !> Scalar to divide by real(kind=sp), intent(IN) :: b vec_div_scal_r4 = vector(a%x / b, a%y / b, a%z / b) end function vec_div_scal_r4 type(vector) pure elemental function vec_div_scal_r8(a, b) !! vec3 / scalar elementwise. Scalar is a 64-bit float use constants, only : dp !> input vec3 class(vector), intent(IN) :: a !> Scalar to divide by real(kind=dp), intent(IN) :: b vec_div_scal_r8 = vector(a%x / b, a%y / b, a%z / b) end function vec_div_scal_r8 type(vector) pure elemental function vec_div_scal_int(a, b) !! vec3 / scalar elementwise. Scalar is an integer !> input vec3 class(vector), intent(IN) :: a !> Scalar to divide by integer, intent(IN) :: b vec_div_scal_int = vector(a%x / real(b, kind=wp), a%y / real(b, kind=wp), a%z / real(b, kind=wp)) end function vec_div_scal_int type(vector) pure elemental function magnitude(this) !! Returns the magnitude of a vec3 class(vector), intent(in) :: this real(kind=wp) :: tmp tmp = this%length() magnitude = this / tmp end function magnitude real(kind=wp) pure elemental function length(this) !! Returns the length of a vec3 class(vector), intent(in) :: this length = sqrt(this%x**2 + this%y**2 + this%z**2) end function length end Module vector_class