Octopus
symmetrizer.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
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
22 use debug_oct_m
23 use global_oct_m
24 use index_oct_m
26 use math_oct_m
28 use mesh_oct_m
29 use mpi_oct_m
32 use space_oct_m
35
36 implicit none
37
38 private
39 public :: &
52
53 type symmetrizer_t
54 private
55 type(symmetries_t), pointer :: symm
56 integer(int64), allocatable :: map(:,:)
57 integer(int64), allocatable :: map_inv(:,:)
58 contains
59 procedure symmetrize_lattice_vectors
60 end type symmetrizer_t
61
62contains
63
64 ! ---------------------------------------------------------
65 subroutine symmetrizer_init(this, mesh, symm)
66 type(symmetrizer_t), intent(out) :: this
67 class(mesh_t), intent(in) :: mesh
68 type(symmetries_t), target, intent(in) :: symm
69
70 integer :: nops, ip, iop, idir, idx(3)
71 real(real64) :: destpoint(3), srcpoint(3), srcpoint_inv(3), lsize(3), offset(3)
72
73 push_sub(symmetrizer_init)
74
75 assert(mesh%box%dim <= 3)
76
77 this%symm => symm
78
79 !For each operation, we create a mapping between the grid point and the symmetric point
80 nops = symmetries_number(symm)
81
82 safe_allocate(this%map(1:mesh%np, 1:nops))
83 safe_allocate(this%map_inv(1:mesh%np, 1:nops))
84
85 call profiling_in("SYMMETRIZER_INIT")
86
87 lsize = real(mesh%idx%ll, real64)
88 offset = real(mesh%idx%nr(1, :) + mesh%idx%enlarge, real64)
89
90 do ip = 1, mesh%np
91 call mesh_local_index_to_coords(mesh, ip, idx)
92 destpoint = real(idx, real64) - offset
93 ! offset moves corner of cell to origin, in integer mesh coordinates
94
95 assert(all(nint(destpoint) >= 0))
96 assert(all(nint(destpoint) < lsize))
97
98 ! move to center of cell in real coordinates
99 destpoint = destpoint + offset
100
101 !convert to proper reduced coordinates
102 destpoint = destpoint/lsize
103
104 ! iterate over all points that go to this point by a symmetry operation
105 do iop = 1, nops
106 srcpoint = symm_op_apply_red(symm%ops(iop), destpoint)
107 srcpoint_inv = symm_op_apply_inv_red(symm%ops(iop), destpoint)
108
109 !We now come back to what should be an integer, if the symmetric point beloings to the grid
110 !At this point, this is already checked
111 srcpoint = srcpoint*lsize
112 srcpoint_inv = srcpoint_inv*lsize
113
114 ! move back to reference to origin at corner of cell
115 srcpoint = srcpoint - offset
116 srcpoint_inv = srcpoint_inv - offset
117 ! apply periodic boundary conditions in periodic directions
118 do idir = 1, symm%periodic_dim
119 if (nint(srcpoint(idir)) < 0 .or. nint(srcpoint(idir)) >= mesh%idx%ll(idir)) then
120 srcpoint(idir) = real(modulo(nint(srcpoint(idir)), mesh%idx%ll(idir)), real64)
121 end if
122 if (nint(srcpoint_inv(idir)) < 0 .or. nint(srcpoint_inv(idir)) >= mesh%idx%ll(idir)) then
123 srcpoint_inv(idir) = real(modulo(nint(srcpoint_inv(idir)), mesh%idx%ll(idir)), real64)
124 end if
125 end do
126 assert(all(nint(srcpoint) >= 0))
127 assert(all(nint(srcpoint) < mesh%idx%ll))
128 srcpoint = srcpoint + offset
129
130 assert(all(nint(srcpoint_inv) >= 0))
131 assert(all(nint(srcpoint_inv) < mesh%idx%ll))
132 srcpoint_inv = srcpoint_inv + offset
133
134 this%map(ip, iop) = mesh_global_index_from_coords(mesh, nint(srcpoint))
135 assert(this%map(ip, iop) <= mesh%np_global)
136 this%map_inv(ip, iop) = mesh_global_index_from_coords(mesh, nint(srcpoint_inv))
137 assert(this%map_inv(ip, iop) <= mesh%np_global)
138 end do
139 end do
140
141 call profiling_out("SYMMETRIZER_INIT")
142
143 pop_sub(symmetrizer_init)
144 end subroutine symmetrizer_init
145
146 ! ---------------------------------------------------------
147
148 subroutine symmetrizer_end(this)
149 type(symmetrizer_t), intent(inout) :: this
152 nullify(this%symm)
153
154 safe_deallocate_a(this%map)
155 safe_deallocate_a(this%map_inv)
156
157 pop_sub(symmetrizer_end)
158 end subroutine symmetrizer_end
159
160 ! ---------------------------------------------------------
161
162 ! ---------------------------------------------------------
168 subroutine symmetrize_lattice_vectors(this, size, initial_rlattice, rlattice, symmetrize)
169 class(symmetrizer_t), intent(in) :: this
170 integer, intent(in) :: size
171 real(real64), intent(in) :: initial_rlattice(size,size)
172 real(real64), intent(inout) :: rlattice(size,size)
173 logical, intent(in) :: symmetrize
174
175 real(real64) :: strain(size,size), inv_initial_rlattice(size,size)
176 real(real64), parameter :: tol_small = 1.0e-14_real64
177
179
180 ! Remove too small elements
181 call dzero_small_elements_matrix(rlattice, tol_small)
182
183 inv_initial_rlattice = initial_rlattice
184 call lalg_inverse(size, inv_initial_rlattice, 'dir')
185
186 ! Compute strain as rlattice * initial_rlattice^{-1}
187 strain = matmul(rlattice, inv_initial_rlattice)
188
189 if (symmetrize) then
190 ! Symmetrize the strain tensor
191 call dsymmetrize_tensor_cart(this%symm, strain, use_non_symmorphic=.true.)
192 else ! The tensor should be at least symmetric, as we forbid rotations
193 strain = m_half * (strain + transpose(strain))
194 end if
195
196 ! Remove too small elements
197 call dzero_small_elements_matrix(strain, tol_small)
198
199 ! Get the symmetrized lattice vectors
200 rlattice = matmul(strain, initial_rlattice)
201
202 ! Remove too small elements
203 call dzero_small_elements_matrix(rlattice, tol_small)
204
206 end subroutine symmetrize_lattice_vectors
207
208
209#include "undef.F90"
210#include "real.F90"
211#include "symmetrizer_inc.F90"
212
213#include "undef.F90"
214#include "complex.F90"
215#include "symmetrizer_inc.F90"
216
217end module symmetrizer_oct_m
218
219!! Local Variables:
220!! mode: f90
221!! coding: utf-8
222!! End:
real(real64), parameter, public m_half
Definition: global.F90:206
This module implements the index, used for the mesh points.
Definition: index.F90:124
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
subroutine, public dzero_small_elements_matrix(aa, tol)
Definition: math.F90:1442
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
integer(int64) function, public mesh_global_index_from_coords(mesh, ix)
This function returns the true global index of the point for a given vector of integer coordinates.
Definition: mesh.F90:919
subroutine, public mesh_local_index_to_coords(mesh, ip, ix)
Given a local point index, this function returns the set of integer coordinates of the point.
Definition: mesh.F90:950
Some general things and nomenclature:
Definition: par_vec.F90:173
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:631
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:554
integer pure function, public symmetries_number(this)
Definition: symmetries.F90:553
subroutine, public dsymmetrizer_apply(this, mesh, field, field_vector, symmfield, symmfield_vector, suppress_warning, reduced_quantity)
supply field and symmfield, and/or field_vector and symmfield_vector
subroutine, public dsymmetrize_magneto_optics_cart(symm, tensor)
subroutine, public symmetrizer_end(this)
subroutine, public zsymmetrizer_apply_single(this, mesh, iop, field, symmfield)
subroutine, public zsymmetrizer_apply(this, mesh, field, field_vector, symmfield, symmfield_vector, suppress_warning, reduced_quantity)
supply field and symmfield, and/or field_vector and symmfield_vector
subroutine, public dsymmetrizer_apply_single(this, mesh, iop, field, symmfield)
subroutine, public symmetrize_lattice_vectors(this, size, initial_rlattice, rlattice, symmetrize)
Given a symmetric lattice vector, symmetrize another one.
subroutine, public dsymmetrize_tensor_cart(symm, tensor, use_non_symmorphic)
Symmetric a rank-2 tensor defined in Cartesian space.
subroutine, public zsymmetrize_tensor_cart(symm, tensor, use_non_symmorphic)
Symmetric a rank-2 tensor defined in Cartesian space.
subroutine, public zsymmetrize_magneto_optics_cart(symm, tensor)
subroutine, public symmetrizer_init(this, mesh, symm)
int true(void)