Octopus
symm_op.F90
Go to the documentation of this file.
1!! Copyright (C) 2009 X. Andrade
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
21module symm_op_oct_m
22 use debug_oct_m
23 use global_oct_m
24 use, intrinsic :: iso_fortran_env
27
28 implicit none
29
30 private
31
32 public :: &
33 symm_op_t, &
50
51 type symm_op_t
52 private
53 integer :: dim
54 integer :: rot_red(1:3, 1:3)
55 integer :: rot_red_inv(1:3, 1:3)
56 real(real64), public :: rot_cart(1:3, 1:3)
57 real(real64) :: trans_red(1:3)
58 real(real64) :: trans_cart(1:3)
59 end type symm_op_t
60
61 interface symm_op_apply_red
63 end interface symm_op_apply_red
64
65 interface symm_op_apply_cart
67 end interface symm_op_apply_cart
68
69 interface symm_op_apply_inv_red
71 end interface symm_op_apply_inv_red
72
75 end interface symm_op_apply_transpose_red
76
79 end interface symm_op_apply_inv_cart
80
83 end interface symm_op_invariant_cart
84
85 interface symm_op_invariant_red
87 end interface symm_op_invariant_red
88
89
90 real(real64), public, parameter :: tol_translation = 1e-7_real64
91 real(real64), parameter :: tol_identity = 5.0e-6_real64
92
93contains
94
95 ! -------------------------------------------------------------------------------
96 subroutine symm_op_init(this, rot, latt, dim, trans)
97 type(symm_op_t), intent(out) :: this
98 integer, intent(in) :: rot(:, :)
99 type(lattice_vectors_t), intent(in) :: latt
100 integer, intent(in) :: dim
101 real(real64), optional, intent(in) :: trans(:)
102
103 integer :: idim
104
105 push_sub(symm_op_init)
106
107 assert(dim <= 3)
108
109 this%dim = dim
110
111 !What comes out of spglib is the rotation matrix in fractional coordinates
112 !This is not a rotation matrix!
113 this%rot_red = 0
114 this%rot_red(1:dim, 1:dim) = rot(1:dim, 1:dim)
115 do idim = dim+1,3
116 this%rot_red(idim,idim) = 1
117 end do
118
119 ! The inverse operation is only given by its inverse, not the transpose
120 ! By construction the reduced matrix also has a determinant of +1
121 ! Calculate the inverse of the matrix
122 this%rot_red_inv(1,1) = +(this%rot_red(2,2)*this%rot_red(3,3) - this%rot_red(2,3)*this%rot_red(3,2))
123 this%rot_red_inv(2,1) = -(this%rot_red(2,1)*this%rot_red(3,3) - this%rot_red(2,3)*this%rot_red(3,1))
124 this%rot_red_inv(3,1) = +(this%rot_red(2,1)*this%rot_red(3,2) - this%rot_red(2,2)*this%rot_red(3,1))
125 this%rot_red_inv(1,2) = -(this%rot_red(1,2)*this%rot_red(3,3) - this%rot_red(1,3)*this%rot_red(3,2))
126 this%rot_red_inv(2,2) = +(this%rot_red(1,1)*this%rot_red(3,3) - this%rot_red(1,3)*this%rot_red(3,1))
127 this%rot_red_inv(3,2) = -(this%rot_red(1,1)*this%rot_red(3,2) - this%rot_red(1,2)*this%rot_red(3,1))
128 this%rot_red_inv(1,3) = +(this%rot_red(1,2)*this%rot_red(2,3) - this%rot_red(1,3)*this%rot_red(2,2))
129 this%rot_red_inv(2,3) = -(this%rot_red(1,1)*this%rot_red(2,3) - this%rot_red(1,3)*this%rot_red(2,1))
130 this%rot_red_inv(3,3) = +(this%rot_red(1,1)*this%rot_red(2,2) - this%rot_red(1,2)*this%rot_red(2,1))
131
132 this%trans_red(1:3) = m_zero
133 if (present(trans)) then
134 this%trans_red(1:dim) = trans(1:dim)
135 end if
136
137 call symm_op_build_cartesian(this, latt, dim)
138
139 pop_sub(symm_op_init)
140 end subroutine symm_op_init
141
142
143 ! -------------------------------------------------------------------------------
145 subroutine symm_op_build_cartesian(this, latt, dim)
146 type(symm_op_t), intent(inout) :: this
147 type(lattice_vectors_t), intent(in) :: latt
148 integer, intent(in) :: dim
150 integer :: idim
153
154 !This is a proper rotation matrix
155 !R_{cart} = A*R_{red}*A^{-1}
156 !Where A is the matrix containing the lattice vectors as column
157 this%rot_cart = m_zero
158 this%rot_cart(1:dim, 1:dim) = matmul(latt%rlattice(1:dim, 1:dim), &
159 matmul(this%rot_red(1:dim, 1:dim),transpose(latt%klattice(1:dim, 1:dim))/ (m_two * m_pi)))
160 do idim = dim+1,3
161 this%rot_cart(idim,idim) = m_one
162 end do
163
164 this%trans_cart(1:3) = m_zero
165 if (symm_op_has_translation(this, tol_translation)) then
166 this%trans_cart(1:dim) = latt%red_to_cart(this%trans_red(1:dim))
167 end if
168
169 !We check that the rotation matrix in Cartesian space is indeed a rotation matrix
170 if (any(abs(matmul(this%rot_cart,transpose(this%rot_cart)) &
171 -reshape((/1, 0, 0, 0, 1, 0, 0, 0, 1/), (/3, 3/)))>tol_identity)) then
172 message(1) = "Internal error: This matrix is not a rotation matrix"
173 write(message(2),'(3(3f19.13,2x))') this%rot_cart
174 message(3) = "Lattice vector is "
175 write(message(4),'(3(3f19.13,2x))') latt%rlattice
176 call messages_fatal(4)
177 end if
179 end subroutine symm_op_build_cartesian
180
181 ! -------------------------------------------------------------------------------
182 subroutine symm_op_copy(inp, outp)
183 type(symm_op_t), intent(in) :: inp
184 type(symm_op_t), intent(out) :: outp
185
186 push_sub(symm_op_copy)
187
188 outp%dim = inp%dim
189 outp%rot_red(1:3, 1:3) = inp%rot_red(1:3, 1:3)
190 outp%rot_red_inv(1:3, 1:3) = inp%rot_red_inv(1:3, 1:3)
191 outp%trans_red(1:3) = inp%trans_red(1:3)
192 outp%rot_cart(1:3, 1:3) = inp%rot_cart(1:3, 1:3)
193 outp%trans_cart(1:3) = inp%trans_cart(1:3)
194
195 pop_sub(symm_op_copy)
196 end subroutine symm_op_copy
197
198 ! -------------------------------------------------------------------------------
199 logical pure function symm_op_has_translation(this, prec) result(has)
200 type(symm_op_t), intent(in) :: this
201 real(real64), intent(in) :: prec
202
203 has = any(abs(this%trans_red(1:this%dim)) >= prec)
204
205 end function symm_op_has_translation
206
207 ! -------------------------------------------------------------------------------
208
209 function symm_op_rotation_matrix_red(this) result(matrix)
210 type(symm_op_t), intent(in) :: this
211 integer :: matrix(1:this%dim, 1:this%dim)
212
213 matrix(1:this%dim, 1:this%dim) = this%rot_red(1:this%dim, 1:this%dim)
214
215 end function symm_op_rotation_matrix_red
216
217 ! -------------------------------------------------------------------------------
218
219 function symm_op_rotation_matrix_cart(this) result(matrix)
220 type(symm_op_t), intent(in) :: this
221 real(real64) :: matrix(1:this%dim, 1:this%dim)
222
223 matrix(1:this%dim, 1:this%dim) = this%rot_cart(1:this%dim, 1:this%dim)
224
226
227
228 ! -------------------------------------------------------------------------------
229
230 function symm_op_translation_vector_red(this) result(vector)
231 type(symm_op_t), intent(in) :: this
232 real(real64) :: vector(1:this%dim)
233
234 vector(1:this%dim) = this%trans_red(1:this%dim)
235
237
238 ! -------------------------------------------------------------------------------
239
240 function symm_op_translation_vector_cart(this) result(vector)
241 type(symm_op_t), intent(in) :: this
242 real(real64) :: vector(1:this%dim)
243
244 vector(1:this%dim) = this%trans_cart(1:this%dim)
245
247
248 ! -------------------------------------------------------------------------------
249
250 logical pure function symm_op_is_identity(this) result(is_identity)
251 type(symm_op_t), intent(in) :: this
252
253 is_identity = .true.
254 is_identity = is_identity .and. all(abs(this%trans_red) < tol_translation)
255 is_identity = is_identity .and. all(abs(this%rot_red(:, 1) - (/ m_one, m_zero, m_zero/)) < tol_identity)
256 is_identity = is_identity .and. all(abs(this%rot_red(:, 2) - (/ m_zero, m_one, m_zero/)) < tol_identity)
257 is_identity = is_identity .and. all(abs(this%rot_red(:, 3) - (/ m_zero, m_zero, m_one/)) < tol_identity)
258
259 end function symm_op_is_identity
260
261 ! -------------------------------------------------------------------------------
262
263 pure function isymm_op_apply_red(this, aa) result(bb)
264 type(symm_op_t), intent(in) :: this
265 integer, intent(in) :: aa(:)
266 integer :: bb(1:this%dim)
267
268 bb(1:this%dim) = nint(dsymm_op_apply_red(this, real(aa, real64) ))
269
270 end function isymm_op_apply_red
271
272 ! -------------------------------------------------------------------------------
273
274 function isymm_op_apply_inv_red(this, aa) result(bb)
275 type(symm_op_t), intent(in) :: this
276 integer, intent(in) :: aa(:)
277 integer :: bb(1:this%dim)
278
279 bb(1:this%dim) = nint(dsymm_op_apply_inv_red(this, real(aa, real64) ))
280
281 end function isymm_op_apply_inv_red
282
283#include "undef.F90"
284#include "real.F90"
285#include "symm_op_inc.F90"
286
287#include "undef.F90"
288#include "complex.F90"
289#include "symm_op_inc.F90"
290
291end module symm_op_oct_m
293!! Local Variables:
294!! mode: f90
295!! coding: utf-8
296!! End:
real(real64), parameter, public m_two
Definition: global.F90:189
real(real64), parameter, public m_zero
Definition: global.F90:187
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:185
real(real64), parameter, public m_one
Definition: global.F90:188
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
logical pure function zsymm_op_invariant_cart(this, aa, prec)
Definition: symm_op.F90:666
pure real(real64) function, dimension(1:this%dim) dsymm_op_apply_red(this, aa)
Definition: symm_op.F90:445
subroutine, public symm_op_copy(inp, outp)
Definition: symm_op.F90:276
pure real(real64) function, dimension(1:this%dim) dsymm_op_apply_inv_red(this, aa)
Definition: symm_op.F90:456
pure real(real64) function, dimension(1:this%dim) dsymm_op_apply_transpose_red(this, aa)
Definition: symm_op.F90:468
pure complex(real64) function, dimension(1:this%dim) zsymm_op_apply_cart(this, aa)
Definition: symm_op.F90:639
real(real64) function, dimension(1:this%dim), public symm_op_translation_vector_red(this)
Definition: symm_op.F90:324
logical pure function, public symm_op_has_translation(this, prec)
Definition: symm_op.F90:293
logical pure function dsymm_op_invariant_red(this, aa, prec)
Definition: symm_op.F90:519
real(real64) function, dimension(1:this%dim, 1:this%dim), public symm_op_rotation_matrix_cart(this)
Definition: symm_op.F90:313
pure complex(real64) function, dimension(1:this%dim) zsymm_op_apply_transpose_red(this, aa)
Definition: symm_op.F90:628
pure real(real64) function, dimension(1:this%dim) dsymm_op_apply_cart(this, aa)
Definition: symm_op.F90:479
integer function, dimension(1:this%dim, 1:this%dim), public symm_op_rotation_matrix_red(this)
Definition: symm_op.F90:303
logical pure function, public symm_op_is_identity(this)
Definition: symm_op.F90:344
pure complex(real64) function, dimension(1:this%dim) zsymm_op_apply_red(this, aa)
Definition: symm_op.F90:605
pure complex(real64) function, dimension(1:this%dim) zsymm_op_apply_inv_red(this, aa)
Definition: symm_op.F90:616
pure complex(real64) function, dimension(1:this%dim) zsymm_op_apply_inv_cart(this, aa, rotation_only)
Definition: symm_op.F90:650
integer function, dimension(1:this%dim) isymm_op_apply_inv_red(this, aa)
Definition: symm_op.F90:368
real(real64), parameter tol_identity
Definition: symm_op.F90:184
real(real64), parameter, public tol_translation
Definition: symm_op.F90:183
pure real(real64) function, dimension(1:this%dim) dsymm_op_apply_inv_cart(this, aa, rotation_only)
Definition: symm_op.F90:490
real(real64) function, dimension(1:this%dim), public symm_op_translation_vector_cart(this)
Definition: symm_op.F90:334
subroutine, public symm_op_build_cartesian(this, latt, dim)
Computes the Cartesian rotation matrix and translation vectors from the reduced ones.
Definition: symm_op.F90:239
logical pure function dsymm_op_invariant_cart(this, aa, prec)
Definition: symm_op.F90:506
pure integer function, dimension(1:this%dim) isymm_op_apply_red(this, aa)
Definition: symm_op.F90:357
subroutine, public symm_op_init(this, rot, latt, dim, trans)
Definition: symm_op.F90:190
logical pure function zsymm_op_invariant_red(this, aa, prec)
Definition: symm_op.F90:679
int true(void)