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
89contains
90
91 ! -------------------------------------------------------------------------------
92 subroutine symm_op_init(this, rot, latt, dim, trans)
93 type(symm_op_t), intent(out) :: this
94 integer, intent(in) :: rot(:, :)
95 type(lattice_vectors_t), intent(in) :: latt
96 integer, intent(in) :: dim
97 real(real64), optional, intent(in) :: trans(:)
98
99 integer :: idim
100
101 push_sub(symm_op_init)
102
103 assert(dim <= 3)
104
105 this%dim = dim
106
107 !What comes out of spglib is the rotation matrix in fractional coordinates
108 !This is not a rotation matrix!
109 this%rot_red = 0
110 this%rot_red(1:dim, 1:dim) = rot(1:dim, 1:dim)
111 do idim = dim+1,3
112 this%rot_red(idim,idim) = 1
113 end do
115 !The inverse operation is only given by its inverse, not the transpose
116 !By Contrustion the reduced matrix also has a determinant of +1
117 ! Calculate the inverse of the matrix
118 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))
119 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))
120 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))
121 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))
122 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))
123 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))
124 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))
125 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))
126 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))
127
128 this%trans_red(1:3) = m_zero
129 if (present(trans)) then
130 this%trans_red(1:dim) = trans(1:dim)
131 end if
132
133 call symm_op_build_cartesian(this, latt, dim)
134
135 pop_sub(symm_op_init)
136 end subroutine symm_op_init
137
138
139 ! -------------------------------------------------------------------------------
141 subroutine symm_op_build_cartesian(this, latt, dim)
142 type(symm_op_t), intent(inout) :: this
143 type(lattice_vectors_t), intent(in) :: latt
144 integer, intent(in) :: dim
145
146 integer :: idim
150 !This is a proper rotation matrix
151 !R_{cart} = A*R_{red}*A^{-1}
152 !Where A is the matrix containing the lattice vectors as column
153 this%rot_cart = m_zero
154 this%rot_cart(1:dim, 1:dim) = matmul(latt%rlattice(1:dim, 1:dim), &
155 matmul(this%rot_red(1:dim, 1:dim),transpose(latt%klattice(1:dim, 1:dim))/ (m_two * m_pi)))
156 do idim = dim+1,3
157 this%rot_cart(idim,idim) = m_one
158 end do
159
160 this%trans_cart(1:3) = m_zero
161 if (symm_op_has_translation(this, 1e-6_real64)) then
162 this%trans_cart(1:dim) = latt%red_to_cart(this%trans_red(1:dim))
163 end if
164
165 !We check that the rotation matrix in Cartesian space is indeed a rotation matrix
166 if (any(abs(matmul(this%rot_cart,transpose(this%rot_cart)) &
167 -reshape((/1, 0, 0, 0, 1, 0, 0, 0, 1/), (/3, 3/)))>5.0e-6_real64)) then
168 message(1) = "Internal error: This matrix is not a rotation matrix"
169 write(message(2),'(3(3f19.13,2x))') this%rot_cart
170 message(3) = "Lattice vector is "
171 write(message(4),'(3(3f19.13,2x))') latt%rlattice
172 call messages_fatal(4)
173 end if
175 end subroutine symm_op_build_cartesian
176
177 ! -------------------------------------------------------------------------------
178 subroutine symm_op_copy(inp, outp)
179 type(symm_op_t), intent(in) :: inp
180 type(symm_op_t), intent(out) :: outp
181
182 push_sub(symm_op_copy)
183
184 outp%dim = inp%dim
185 outp%rot_red(1:3, 1:3) = inp%rot_red(1:3, 1:3)
186 outp%rot_red_inv(1:3, 1:3) = inp%rot_red_inv(1:3, 1:3)
187 outp%trans_red(1:3) = inp%trans_red(1:3)
188 outp%rot_cart(1:3, 1:3) = inp%rot_cart(1:3, 1:3)
189 outp%trans_cart(1:3) = inp%trans_cart(1:3)
190
191 pop_sub(symm_op_copy)
192 end subroutine symm_op_copy
193
194 ! -------------------------------------------------------------------------------
195 logical pure function symm_op_has_translation(this, prec) result(has)
196 type(symm_op_t), intent(in) :: this
197 real(real64), intent(in) :: prec
198
199 has = any(abs(this%trans_red(1:this%dim)) >= prec)
200
201 end function symm_op_has_translation
202
203 ! -------------------------------------------------------------------------------
204
205 function symm_op_rotation_matrix_red(this) result(matrix)
206 type(symm_op_t), intent(in) :: this
207 integer :: matrix(1:this%dim, 1:this%dim)
208
209 matrix(1:this%dim, 1:this%dim) = this%rot_red(1:this%dim, 1:this%dim)
210
211 end function symm_op_rotation_matrix_red
212
213 ! -------------------------------------------------------------------------------
214
215 function symm_op_rotation_matrix_cart(this) result(matrix)
216 type(symm_op_t), intent(in) :: this
217 real(real64) :: matrix(1:this%dim, 1:this%dim)
218
219 matrix(1:this%dim, 1:this%dim) = this%rot_cart(1:this%dim, 1:this%dim)
220
222
223
224 ! -------------------------------------------------------------------------------
225
226 function symm_op_translation_vector_red(this) result(vector)
227 type(symm_op_t), intent(in) :: this
228 real(real64) :: vector(1:this%dim)
229
230 vector(1:this%dim) = this%trans_red(1:this%dim)
231
233
234 ! -------------------------------------------------------------------------------
235
236 function symm_op_translation_vector_cart(this) result(vector)
237 type(symm_op_t), intent(in) :: this
238 real(real64) :: vector(1:this%dim)
239
240 vector(1:this%dim) = this%trans_cart(1:this%dim)
241
243
244 ! -------------------------------------------------------------------------------
245
246 logical pure function symm_op_is_identity(this) result(is_identity)
247 type(symm_op_t), intent(in) :: this
248
249 is_identity = .true.
250 is_identity = is_identity .and. all(abs(this%trans_red) < 1.0e-5_real64)
251 is_identity = is_identity .and. all(abs(this%rot_red(:, 1) - (/ m_one, m_zero, m_zero/)) < 1.0e-5_real64)
252 is_identity = is_identity .and. all(abs(this%rot_red(:, 2) - (/ m_zero, m_one, m_zero/)) < 1.0e-5_real64)
253 is_identity = is_identity .and. all(abs(this%rot_red(:, 3) - (/ m_zero, m_zero, m_one/)) < 1.0e-5_real64)
254
255 end function symm_op_is_identity
256
257 ! -------------------------------------------------------------------------------
258
259 pure function isymm_op_apply_red(this, aa) result(bb)
260 type(symm_op_t), intent(in) :: this
261 integer, intent(in) :: aa(:)
262 integer :: bb(1:this%dim)
263
264 bb(1:this%dim) = nint(dsymm_op_apply_red(this, real(aa, real64) ))
265
266 end function isymm_op_apply_red
267
268 ! -------------------------------------------------------------------------------
269
270 function isymm_op_apply_inv_red(this, aa) result(bb)
271 type(symm_op_t), intent(in) :: this
272 integer, intent(in) :: aa(:)
273 integer :: bb(1:this%dim)
274
275 bb(1:this%dim) = nint(dsymm_op_apply_inv_red(this, real(aa, real64) ))
276
277 end function isymm_op_apply_inv_red
278
279#include "undef.F90"
280#include "real.F90"
281#include "symm_op_inc.F90"
282
283#include "undef.F90"
284#include "complex.F90"
285#include "symm_op_inc.F90"
286
287end module symm_op_oct_m
289!! Local Variables:
290!! mode: f90
291!! coding: utf-8
292!! 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
pure complex(real64) function, dimension(1:this%dim) zsymm_op_apply_inv_cart(this, aa)
Definition: symm_op.F90:641
logical pure function zsymm_op_invariant_cart(this, aa, prec)
Definition: symm_op.F90:652
pure real(real64) function, dimension(1:this%dim) dsymm_op_apply_red(this, aa)
Definition: symm_op.F90:441
subroutine, public symm_op_copy(inp, outp)
Definition: symm_op.F90:272
pure real(real64) function, dimension(1:this%dim) dsymm_op_apply_inv_red(this, aa)
Definition: symm_op.F90:452
pure real(real64) function, dimension(1:this%dim) dsymm_op_apply_transpose_red(this, aa)
Definition: symm_op.F90:464
pure complex(real64) function, dimension(1:this%dim) zsymm_op_apply_cart(this, aa)
Definition: symm_op.F90:630
real(real64) function, dimension(1:this%dim), public symm_op_translation_vector_red(this)
Definition: symm_op.F90:320
logical pure function, public symm_op_has_translation(this, prec)
Definition: symm_op.F90:289
logical pure function dsymm_op_invariant_red(this, aa, prec)
Definition: symm_op.F90:510
real(real64) function, dimension(1:this%dim, 1:this%dim), public symm_op_rotation_matrix_cart(this)
Definition: symm_op.F90:309
pure complex(real64) function, dimension(1:this%dim) zsymm_op_apply_transpose_red(this, aa)
Definition: symm_op.F90:619
pure real(real64) function, dimension(1:this%dim) dsymm_op_apply_cart(this, aa)
Definition: symm_op.F90:475
pure real(real64) function, dimension(1:this%dim) dsymm_op_apply_inv_cart(this, aa)
Definition: symm_op.F90:486
integer function, dimension(1:this%dim, 1:this%dim), public symm_op_rotation_matrix_red(this)
Definition: symm_op.F90:299
logical pure function, public symm_op_is_identity(this)
Definition: symm_op.F90:340
pure complex(real64) function, dimension(1:this%dim) zsymm_op_apply_red(this, aa)
Definition: symm_op.F90:596
pure complex(real64) function, dimension(1:this%dim) zsymm_op_apply_inv_red(this, aa)
Definition: symm_op.F90:607
integer function, dimension(1:this%dim) isymm_op_apply_inv_red(this, aa)
Definition: symm_op.F90:364
real(real64) function, dimension(1:this%dim), public symm_op_translation_vector_cart(this)
Definition: symm_op.F90:330
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:235
logical pure function dsymm_op_invariant_cart(this, aa, prec)
Definition: symm_op.F90:497
pure integer function, dimension(1:this%dim) isymm_op_apply_red(this, aa)
Definition: symm_op.F90:353
subroutine, public symm_op_init(this, rot, latt, dim, trans)
Definition: symm_op.F90:186
logical pure function zsymm_op_invariant_red(this, aa, prec)
Definition: symm_op.F90:665
int true(void)