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 accel_oct_m
23 use batch_oct_m
25 use debug_oct_m
26 use global_oct_m
27 use index_oct_m
29 use math_oct_m
31 use mesh_oct_m
32 use mpi_oct_m
35 use space_oct_m
38 use types_oct_m
39
40 implicit none
41
42 private
43 public :: &
59
60 type symmetrizer_t
61 private
62 type(symmetries_t), pointer :: symm
63 integer(int64), allocatable :: map(:,:)
64 integer(int64), allocatable :: map_inv(:,:)
65 type(accel_mem_t) :: map_buff
66 contains
67 procedure symmetrize_lattice_vectors
68 end type symmetrizer_t
69
70contains
71
72 ! ---------------------------------------------------------
73 subroutine symmetrizer_init(this, mesh, symm)
74 type(symmetrizer_t), intent(out) :: this
75 class(mesh_t), intent(in) :: mesh
76 type(symmetries_t), target, intent(in) :: symm
77
78 integer :: nops, ip, iop, idir, idx(3)
79 real(real64) :: destpoint(3), srcpoint(3), srcpoint_inv(3), lsize(3), offset(3)
80
81 push_sub(symmetrizer_init)
82
83 assert(mesh%box%dim <= 3)
84
85 this%symm => symm
86
87 !For each operation, we create a mapping between the grid point and the symmetric point
88 nops = symmetries_number(symm)
89
90 safe_allocate(this%map(1:mesh%np, 1:nops))
91 safe_allocate(this%map_inv(1:mesh%np, 1:nops))
92
93 call profiling_in("SYMMETRIZER_INIT")
94
95 lsize = real(mesh%idx%ll, real64)
96 offset = real(mesh%idx%nr(1, :) + mesh%idx%enlarge, real64)
97
98 do ip = 1, mesh%np
99 call mesh_local_index_to_coords(mesh, ip, idx)
100 destpoint = real(idx, real64) - offset
101 ! offset moves corner of cell to origin, in integer mesh coordinates
102
103 assert(all(nint(destpoint) >= 0))
104 assert(all(nint(destpoint) < lsize))
105
106 ! move to center of cell in real coordinates
107 destpoint = destpoint + offset
108
109 !convert to proper reduced coordinates
110 destpoint = destpoint/lsize
111
112 ! iterate over all points that go to this point by a symmetry operation
113 do iop = 1, nops
114 srcpoint = symm_op_apply_red(symm%ops(iop), destpoint)
115 srcpoint_inv = symm_op_apply_inv_red(symm%ops(iop), destpoint)
117 !We now come back to what should be an integer, if the symmetric point beloings to the grid
118 !At this point, this is already checked
119 srcpoint = srcpoint*lsize
120 srcpoint_inv = srcpoint_inv*lsize
121
122 ! move back to reference to origin at corner of cell
123 srcpoint = srcpoint - offset
124 srcpoint_inv = srcpoint_inv - offset
125 ! apply periodic boundary conditions in periodic directions
126 do idir = 1, symm%periodic_dim
127 if (nint(srcpoint(idir)) < 0 .or. nint(srcpoint(idir)) >= mesh%idx%ll(idir)) then
128 srcpoint(idir) = real(modulo(nint(srcpoint(idir)), mesh%idx%ll(idir)), real64)
129 end if
130 if (nint(srcpoint_inv(idir)) < 0 .or. nint(srcpoint_inv(idir)) >= mesh%idx%ll(idir)) then
131 srcpoint_inv(idir) = real(modulo(nint(srcpoint_inv(idir)), mesh%idx%ll(idir)), real64)
132 end if
133 end do
134 assert(all(nint(srcpoint) >= 0))
135 assert(all(nint(srcpoint) < mesh%idx%ll))
136 srcpoint = srcpoint + offset
137
138 assert(all(nint(srcpoint_inv) >= 0))
139 assert(all(nint(srcpoint_inv) < mesh%idx%ll))
140 srcpoint_inv = srcpoint_inv + offset
141
142 this%map(ip, iop) = mesh_global_index_from_coords(mesh, nint(srcpoint))
143 assert(this%map(ip, iop) <= mesh%np_global)
144 this%map_inv(ip, iop) = mesh_global_index_from_coords(mesh, nint(srcpoint_inv))
145 assert(this%map_inv(ip, iop) <= mesh%np_global)
146 end do
147 end do
148
149 call symmetrizer_build_map_buffer(this, mesh)
150
151 call profiling_out("SYMMETRIZER_INIT")
152
153 pop_sub(symmetrizer_init)
154 end subroutine symmetrizer_init
156 ! ---------------------------------------------------------
159 subroutine symmetrizer_build_map_buffer(this, mesh)
160 type(symmetrizer_t), intent(inout) :: this
161 class(mesh_t), intent(in) :: mesh
163 integer :: nops, ip, iop
164 integer, allocatable :: map_tmp(:,:)
165
167
168 if (accel_is_enabled() .and. .not. mesh%parallel_in_domains .and. .not. this%map_buff%allocated) then
169 assert(allocated(this%map))
170 nops = symmetries_number(this%symm)
171 safe_allocate(map_tmp(1:mesh%np, 1:nops))
172 ! Shift the map to C 0-based indexing here on the host, so the device kernel in
173 ! symmetrize_batch.cu can index the field buffer directly
174 do iop = 1, nops
175 do ip = 1, mesh%np
176 map_tmp(ip, iop) = int(this%map(ip, iop) - 1, int32)
177 end do
178 end do
179 call accel_create_buffer(this%map_buff, accel_mem_read_only, type_integer, int(mesh%np, int64)*nops)
180 call accel_write_buffer(this%map_buff, mesh%np, nops, map_tmp)
181 safe_deallocate_a(map_tmp)
182 end if
183
185 end subroutine symmetrizer_build_map_buffer
186
187 ! ---------------------------------------------------------
188
189 subroutine symmetrizer_end(this)
190 type(symmetrizer_t), intent(inout) :: this
191
192 push_sub(symmetrizer_end)
193 nullify(this%symm)
194
195 safe_deallocate_a(this%map)
196 safe_deallocate_a(this%map_inv)
197
198 if (this%map_buff%allocated) call accel_free_buffer(this%map_buff)
199
200 pop_sub(symmetrizer_end)
201 end subroutine symmetrizer_end
202
203 ! ---------------------------------------------------------
204
205 ! ---------------------------------------------------------
211 subroutine symmetrize_lattice_vectors(this, size, initial_rlattice, rlattice, symmetrize)
212 class(symmetrizer_t), intent(in) :: this
213 integer, intent(in) :: size
214 real(real64), intent(in) :: initial_rlattice(size,size)
215 real(real64), intent(inout) :: rlattice(size,size)
216 logical, intent(in) :: symmetrize
217
218 real(real64) :: strain(size,size), inv_initial_rlattice(size,size)
219 real(real64), parameter :: tol_small = 1.0e-14_real64
220
222
223 ! Remove too small elements
224 call dzero_small_elements_matrix(rlattice, tol_small)
225
226 inv_initial_rlattice = initial_rlattice
227 call lalg_inverse(size, inv_initial_rlattice, 'dir')
228
229 ! Compute strain as rlattice * initial_rlattice^{-1}
230 strain = matmul(rlattice, inv_initial_rlattice)
231
232 if (symmetrize) then
233 ! Symmetrize the strain tensor
234 call dsymmetrize_tensor_cart(this%symm, strain, use_non_symmorphic=.true.)
235 else ! The tensor should be at least symmetric, as we forbid rotations
236 strain = m_half * (strain + transpose(strain))
237 end if
238
239 ! Remove too small elements
240 call dzero_small_elements_matrix(strain, tol_small)
241
242 ! Get the symmetrized lattice vectors
243 rlattice = matmul(strain, initial_rlattice)
244
245 ! Remove too small elements
246 call dzero_small_elements_matrix(rlattice, tol_small)
247
249 end subroutine symmetrize_lattice_vectors
250
251
252#include "undef.F90"
253#include "real.F90"
254#include "symmetrizer_inc.F90"
255
256#include "undef.F90"
257#include "complex.F90"
258#include "symmetrizer_inc.F90"
259
260end module symmetrizer_oct_m
261
262!! Local Variables:
263!! mode: f90
264!! coding: utf-8
265!! End:
subroutine, public accel_free_buffer(this, async)
Definition: accel.F90:1006
pure logical function, public accel_is_enabled()
Definition: accel.F90:403
integer, parameter, public accel_mem_read_only
Definition: accel.F90:186
This module implements batches of mesh functions.
Definition: batch.F90:135
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:118
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:1450
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:920
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:951
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:569
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 dsymmetrizer_apply_batch(this, mesh, iop, src, dst)
Symmetrize a whole batch, returning another batch with the same layout.
subroutine, public dsymmetrize_magneto_optics_cart(symm, tensor)
subroutine, public symmetrizer_end(this)
subroutine, public zsymmetrizer_apply_batch(this, mesh, iop, src, dst)
Symmetrize a whole batch, returning another batch with the same layout.
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)
subroutine, public symmetrizer_build_map_buffer(this, mesh)
Build the symmetrization map on GPU.
type(type_t), parameter, public type_integer
Definition: types.F90:137
Describes mesh distribution to nodes.
Definition: mesh.F90:187
int true(void)