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 :: &
61
62 type symmetrizer_t
63 private
64 type(symmetries_t), pointer :: symm
65 integer(int64), allocatable :: map(:,:)
66 integer(int64), allocatable :: map_inv(:,:)
67 type(accel_mem_t) :: map_buff
68 contains
69 procedure symmetrize_lattice_vectors
70 end type symmetrizer_t
71
72contains
73
74 ! ---------------------------------------------------------
75 subroutine symmetrizer_init(this, mesh, symm)
76 type(symmetrizer_t), intent(out) :: this
77 class(mesh_t), intent(in) :: mesh
78 type(symmetries_t), target, intent(in) :: symm
79
80 integer :: nops, ip, iop, idir, idx(3)
81 real(real64) :: destpoint(3), srcpoint(3), srcpoint_inv(3), lsize(3), offset(3)
82
83 push_sub(symmetrizer_init)
84
85 assert(mesh%box%dim <= 3)
86
87 this%symm => symm
88
89 !For each operation, we create a mapping between the grid point and the symmetric point
90 nops = symmetries_number(symm)
91
92 safe_allocate(this%map(1:mesh%np, 1:nops))
93 safe_allocate(this%map_inv(1:mesh%np, 1:nops))
94
95 call profiling_in("SYMMETRIZER_INIT")
96
97 lsize = real(mesh%idx%ll, real64)
98 offset = real(mesh%idx%nr(1, :) + mesh%idx%enlarge, real64)
99
100 do ip = 1, mesh%np
101 call mesh_local_index_to_coords(mesh, ip, idx)
102 destpoint = real(idx, real64) - offset
103 ! offset moves corner of cell to origin, in integer mesh coordinates
104
105 assert(all(nint(destpoint) >= 0))
106 assert(all(nint(destpoint) < lsize))
107
108 ! move to center of cell in real coordinates
109 destpoint = destpoint + offset
110
111 !convert to proper reduced coordinates
112 destpoint = destpoint/lsize
113
114 ! iterate over all points that go to this point by a symmetry operation
115 do iop = 1, nops
116 srcpoint = symm_op_apply_red(symm%ops(iop), destpoint)
117 srcpoint_inv = symm_op_apply_inv_red(symm%ops(iop), destpoint)
118
119 !We now come back to what should be an integer, if the symmetric point beloings to the grid
120 !At this point, this is already checked
121 srcpoint = srcpoint*lsize
122 srcpoint_inv = srcpoint_inv*lsize
123
124 ! move back to reference to origin at corner of cell
125 srcpoint = srcpoint - offset
126 srcpoint_inv = srcpoint_inv - offset
127 ! apply periodic boundary conditions in periodic directions
128 do idir = 1, symm%periodic_dim
129 if (nint(srcpoint(idir)) < 0 .or. nint(srcpoint(idir)) >= mesh%idx%ll(idir)) then
130 srcpoint(idir) = real(modulo(nint(srcpoint(idir)), mesh%idx%ll(idir)), real64)
131 end if
132 if (nint(srcpoint_inv(idir)) < 0 .or. nint(srcpoint_inv(idir)) >= mesh%idx%ll(idir)) then
133 srcpoint_inv(idir) = real(modulo(nint(srcpoint_inv(idir)), mesh%idx%ll(idir)), real64)
134 end if
135 end do
136 assert(all(nint(srcpoint) >= 0))
137 assert(all(nint(srcpoint) < mesh%idx%ll))
138 srcpoint = srcpoint + offset
139
140 assert(all(nint(srcpoint_inv) >= 0))
141 assert(all(nint(srcpoint_inv) < mesh%idx%ll))
142 srcpoint_inv = srcpoint_inv + offset
143
144 this%map(ip, iop) = mesh_global_index_from_coords(mesh, nint(srcpoint))
145 assert(this%map(ip, iop) <= mesh%np_global)
146 this%map_inv(ip, iop) = mesh_global_index_from_coords(mesh, nint(srcpoint_inv))
147 assert(this%map_inv(ip, iop) <= mesh%np_global)
148 end do
149 end do
150
151 call symmetrizer_build_map_buffer(this, mesh)
152
153 call profiling_out("SYMMETRIZER_INIT")
154
155 pop_sub(symmetrizer_init)
156 end subroutine symmetrizer_init
158 ! ---------------------------------------------------------
161 subroutine symmetrizer_build_map_buffer(this, mesh)
162 type(symmetrizer_t), intent(inout) :: this
163 class(mesh_t), intent(in) :: mesh
165 integer :: nops, ip, iop
166 integer, allocatable :: map_tmp(:,:)
167
169
170 if (accel_is_enabled() .and. .not. mesh%parallel_in_domains .and. .not. this%map_buff%allocated) then
171 assert(allocated(this%map))
172 nops = symmetries_number(this%symm)
173 safe_allocate(map_tmp(1:mesh%np, 1:nops))
174 ! Shift the map to C 0-based indexing here on the host, so the device kernel in
175 ! symmetrize_batch.cu can index the field buffer directly
176 do iop = 1, nops
177 do ip = 1, mesh%np
178 map_tmp(ip, iop) = int(this%map(ip, iop) - 1, int32)
179 end do
180 end do
181 call accel_create_buffer(this%map_buff, accel_mem_read_only, type_integer, int(mesh%np, int64)*nops)
182 call accel_write_buffer(this%map_buff, mesh%np, nops, map_tmp)
183 safe_deallocate_a(map_tmp)
184 end if
185
187 end subroutine symmetrizer_build_map_buffer
188
189 ! ---------------------------------------------------------
190
191 subroutine symmetrizer_end(this)
192 type(symmetrizer_t), intent(inout) :: this
193
194 push_sub(symmetrizer_end)
195 nullify(this%symm)
196
197 safe_deallocate_a(this%map)
198 safe_deallocate_a(this%map_inv)
199
200 if (this%map_buff%allocated) call accel_free_buffer(this%map_buff)
201
202 pop_sub(symmetrizer_end)
203 end subroutine symmetrizer_end
204
205 ! ---------------------------------------------------------
206
207 ! ---------------------------------------------------------
213 subroutine symmetrize_lattice_vectors(this, size, initial_rlattice, rlattice, symmetrize)
214 class(symmetrizer_t), intent(in) :: this
215 integer, intent(in) :: size
216 real(real64), intent(in) :: initial_rlattice(size,size)
217 real(real64), intent(inout) :: rlattice(size,size)
218 logical, intent(in) :: symmetrize
219
220 real(real64) :: strain(3,3), inv_initial_rlattice(size,size)
221 integer :: idir
222 real(real64), parameter :: tol_small = 1.0e-14_real64
223
225
226 ! Remove too small elements
227 call dzero_small_elements_matrix(rlattice, tol_small)
228
229 inv_initial_rlattice = initial_rlattice
230 call lalg_inverse(size, inv_initial_rlattice, 'dir')
231
232 ! Compute strain as rlattice * initial_rlattice^{-1}
233
234 ! This is required because the symmetry operations are 3x3 Cartesian matrices.
235 strain = m_zero
236 do idir = 1, 3
237 strain(idir, idir) = m_one
238 end do
239 ! Compute strain as rlattice * initial_rlattice^{-1} on the periodic block
240 strain(1:size,1:size) = matmul(rlattice, inv_initial_rlattice)
241
242 if (symmetrize) then
243 ! Symmetrize the strain tensor
244 call dsymmetrize_tensor_cart(this%symm, strain, use_non_symmorphic=.true.)
245 else ! The tensor should be at least symmetric, as we forbid rotations
246 strain = m_half * (strain + transpose(strain))
247 end if
248
249 ! Remove too small elements
250 call dzero_small_elements_matrix(strain, tol_small)
251
252 ! Get the symmetrized lattice vectors
253 rlattice = matmul(strain(1:size,1:size), initial_rlattice)
254
255 ! Remove too small elements
256 call dzero_small_elements_matrix(rlattice, tol_small)
257
259 end subroutine symmetrize_lattice_vectors
260
261
262#include "undef.F90"
263#include "real.F90"
264#include "symmetrizer_inc.F90"
265
266#include "undef.F90"
267#include "complex.F90"
268#include "symmetrizer_inc.F90"
269
270! symmetrizer_apply_single + symmetrizer_apply_batch, instantiated for all
271! precisions (d, z, s, c)
272#include "undef.F90"
273#include "real.F90"
274#include "symmetrizer_batch_inc.F90"
275
276#include "undef.F90"
277#include "complex.F90"
278#include "symmetrizer_batch_inc.F90"
279
280#include "undef.F90"
281#include "real32.F90"
282#include "symmetrizer_batch_inc.F90"
283
284#include "undef.F90"
285#include "complex32.F90"
286#include "symmetrizer_batch_inc.F90"
287
288end module symmetrizer_oct_m
289
290!! Local Variables:
291!! mode: f90
292!! coding: utf-8
293!! End:
subroutine, public accel_free_buffer(this, async)
Definition: accel.F90:990
pure logical function, public accel_is_enabled()
Definition: accel.F90:414
integer, parameter, public accel_mem_read_only
Definition: accel.F90:185
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_zero
Definition: global.F90:200
real(real64), parameter, public m_half
Definition: global.F90:206
real(real64), parameter, public m_one
Definition: global.F90:201
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)
The same as for symmetrizer_apply, but a single symmetry operation.
subroutine, public ssymmetrizer_apply_batch(this, mesh, iop, src, dst)
Symmetrize a whole batch, returning another batch with the same layout.
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)
The same as for symmetrizer_apply, but a single symmetry operation.
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 csymmetrizer_apply_batch(this, mesh, iop, src, dst)
Symmetrize a whole batch, returning another batch with the same layout.
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:138
Describes mesh distribution to nodes.
Definition: mesh.F90:187
int true(void)