58 integer,
private :: dim
59 real(real64),
allocatable :: vectors(:, :)
60 real(real64),
allocatable :: change_of_basis_matrix(:, :)
65 generic ::
assignment(=) => copy
67 generic :: from_cartesian => from_cartesian1, from_cartesian2
68 generic :: to_cartesian => to_cartesian1, to_cartesian2
83 type(basis_vectors_t) function basis_vectors_constructor(namespace, dim, vectors) result(basis)
84 type(namespace_t),
intent(in) :: namespace
85 integer,
intent(in) :: dim
86 real(real64),
intent(in) :: vectors(dim, dim)
88 integer :: idir1, idir2
90 push_sub(basis_vectors_constructor)
94 safe_allocate(basis%vectors(1:dim, 1:dim))
95 safe_allocate(basis%change_of_basis_matrix(1:dim, 1:dim))
97 basis%vectors(:, :) = vectors(:, :)
99 basis%orthogonal = .
true.
101 do idir2 = idir1 + 1, dim
102 if (abs(dot_product(basis%vectors(:, idir1), basis%vectors(:, idir2))) >
m_epsilon)
then
103 basis%orthogonal = .false.
110 message(1) =
"Basis vectors are not linearly independent and therefore the change-of-basis matrix cannot be calculated."
115 pop_sub(basis_vectors_constructor)
120 class(basis_vectors_t),
intent(out) :: this
121 class(basis_vectors_t),
intent(in) :: source
125 this%dim = source%dim
126 safe_allocate_source_a(this%vectors, source%vectors)
127 safe_allocate_source_a(this%change_of_basis_matrix, source%change_of_basis_matrix)
128 this%orthogonal = source%orthogonal
135 type(basis_vectors_t),
intent(inout) :: this
139 safe_deallocate_a(this%vectors)
140 safe_deallocate_a(this%change_of_basis_matrix)
147 class(basis_vectors_t),
intent(inout) :: this
148 real(real64),
intent(in) :: factor(1:this%dim)
155 do idir = 1, this%dim
156 this%vectors(:, idir) = this%vectors(:, idir)*factor(idir)
168 real(real64),
intent(in) :: xx_cart(1:this%dim)
169 real(real64) :: xx(1:this%dim)
173 xx = matmul(this%change_of_basis_matrix, xx_cart)
180 real(real64),
intent(in) :: xx(1:this%dim)
181 real(real64) :: xx_cart(1:this%dim)
185 xx_cart = matmul(this%vectors, xx)
192 integer,
intent(in) :: np
193 real(real64),
contiguous,
intent(in) :: xx_cart(:, :)
194 real(real64) :: xx(np, this%dim)
198 call lalg_gemm_nc(np, this%dim, this%dim, m_one, xx_cart, this%change_of_basis_matrix, m_zero, xx)
205 integer,
intent(in) :: np
206 real(real64),
contiguous,
intent(in) :: xx(:, :)
207 real(real64) :: xx_cart(np, this%dim)
210 call lalg_gemm_nc(np, this%dim, this%dim, m_one, xx, this%vectors, m_zero, xx_cart)
216 integer,
intent(in) :: dim
217 real(real64),
intent(in) :: vectors(1:dim, 1:dim)
218 real(real64),
intent(out) :: matrix(1:dim, 1:dim)
220 real(real64) :: volume, cross(1:3)
226 cross(1:3) = dcross_product(vectors(1:3, 2), vectors(1:3, 3))
227 volume = dot_product(vectors(1:3, 1), cross(1:3))
229 matrix(1, 1:3) = dcross_product(vectors(:, 2), vectors(:, 3))/volume
230 matrix(2, 1:3) = dcross_product(vectors(:, 3), vectors(:, 1))/volume
231 matrix(3, 1:3) = dcross_product(vectors(:, 1), vectors(:, 2))/volume
233 volume = vectors(1, 1)*vectors(2, 2) - vectors(2, 1)*vectors(1, 2)
234 matrix(1, 1) = vectors(2, 2)/volume
235 matrix(1, 2) = -vectors(1, 2)/volume
236 matrix(2, 1) = -vectors(2, 1)/volume
237 matrix(2, 2) = vectors(1, 1)/volume
239 volume = vectors(1, 1)
240 matrix(1, 1) = m_one / vectors(1, 1)
243 call lalg_inverse(dim, matrix,
'dir')
Note that lalg_determinant and lalg_inverse are just wrappers over the same routine.
subroutine basis_vectors_copy(this, source)
real(real64) function, dimension(np, this%dim) basis_vectors_to_cartesian2(this, np, xx)
real(real64) function, dimension(np, this%dim) basis_vectors_from_cartesian2(this, np, xx_cart)
subroutine calculate_change_of_basis_matrix(dim, vectors, matrix)
pure real(real64) function, dimension(1:this%dim) basis_vectors_from_cartesian1(this, xx_cart)
subroutine basis_vectors_scale(this, factor)
subroutine basis_vectors_finalize(this)
pure real(real64) function, dimension(1:this%dim) basis_vectors_to_cartesian1(this, xx)
type(basis_vectors_t) function basis_vectors_constructor(namespace, dim, vectors)
real(real64), parameter, public m_epsilon
This module is intended to contain "only mathematical" functions and procedures.
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Vectors defining a basis in a vector space. This class provides methods to convert vector coordinates...