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