Octopus
grid.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!! Copyright (C) 2021 S. Ohlmann
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
23
24module grid_oct_m
25 use accel_oct_m
27 use box_oct_m
32 use cube_oct_m
37 use global_oct_m
39 use mesh_oct_m
42 use mpi_oct_m
46 use parser_oct_m
48 use space_oct_m
53 use unit_oct_m
56
57 implicit none
58
59 private
60 public :: &
61 grid_t, &
65 grid_end, &
74
76 type, extends(mesh_t) :: grid_t
77 ! Components are public by default
78 type(derivatives_t) :: der
79 type(stencil_t) :: stencil
80 type(symmetries_t) :: symm
81 type(symmetrizer_t) :: symmetrizer
82 end type grid_t
83
84 integer, parameter :: &
85 CURV_AFFINE = 1, &
86 curv_gygi = 2, &
87 curv_briggs = 3, &
88 curv_modine = 4
89
90contains
91
92 !-------------------------------------------------------------------
101 subroutine grid_init_stage_1(gr, namespace, space, symm, latt, n_sites, site_position)
102 type(grid_t), intent(inout) :: gr
103 type(namespace_t), intent(in) :: namespace
104 class(space_t), intent(in) :: space
105 type(symmetries_t), optional, intent(in) :: symm
106 type(lattice_vectors_t), optional, intent(in) :: latt
107 integer, optional, intent(in) :: n_sites
108 real(real64), optional, intent(in) :: site_position(:,:)
109
110 type(stencil_t) :: cube
111 integer :: enlarge(space%dim)
112 type(block_t) :: blk
113 integer :: idir
114 real(real64) :: grid_spacing(space%dim)
115
116 push_sub(grid_init_stage_1)
118 gr%box => box_factory_create(namespace, space, latt=latt, n_sites=n_sites, site_position=site_position)
119
120 if (present(symm)) then
121 gr%symm = symm
122 end if
123
124 !%Variable Spacing
125 !%Type float
126 !%Section Mesh
127 !%Description
128 !% The spacing between the points in the mesh. This controls the
129 !% quality of the discretization: smaller spacing gives more
130 !% precise results but increased computational cost.
131 !%
132 !% When using curvilinear coordinates, this is a canonical spacing
133 !% that will be changed locally by the transformation. In periodic
134 !% directions, your spacing may be slightly different than what
135 !% you request here, since the box size must be an integer
136 !% multiple of the spacing.
137 !%
138 !% The default value is defined by the image resolution if <tt>BoxShape =
139 !% box_image</tt>. Othewise here is no default otherwise.
140 !%
141 !% It is possible to have a different spacing in each one of the Cartesian directions
142 !% if we define <tt>Spacing</tt> as block of the form
143 !%
144 !% <tt>%Spacing
145 !% <br>&nbsp;&nbsp;spacing_x | spacing_y | spacing_z
146 !% <br>%</tt>
147 !%End
148
149 if(parse_block(namespace, 'Spacing', blk) == 0) then
150 if(parse_block_cols(blk,0) < space%dim) call messages_input_error(namespace, 'Spacing')
151 do idir = 1, space%dim
152 call parse_block_float(blk, 0, idir - 1, grid_spacing(idir), units_inp%length)
153 end do
154 call parse_block_end(blk)
155 else
156 call parse_variable(namespace, 'Spacing', -m_one, grid_spacing(1), units_inp%length)
157 grid_spacing = grid_spacing(1)
158 end if
159
160 if (associated(gr%box)) then
161 select type (box => gr%box)
162 type is (box_image_t)
163 do idir = 1, space%dim
164 ! default grid_spacing is determined from the pixel size such that one grid point = one pixel.
165 if (grid_spacing(idir) < m_zero) then
166 grid_spacing(idir) = box%pixel_size(idir)
167 end if
168 end do
169 end select
170 end if
172 if (any(grid_spacing(1:space%dim) < m_epsilon)) then
173 message(1) = " Your input for 'Spacing' is negative or zero."
174 call messages_fatal(1, namespace=namespace)
175 end if
176
177 !%Variable PeriodicBoundaryMask
178 !%Type block
179 !%Section Mesh
180 !%Description
181 !% (Experimental) Defines a mask for which periodic boundaries are replaced by zero boundary conditions.
182 !%End
183 if (parse_block(namespace, 'PeriodicBoundaryMask', blk) < 0) then
184 gr%masked_periodic_boundaries = .false.
185 else
186 gr%masked_periodic_boundaries = .true.
187 call parse_block_string(blk, 0, 0, gr%periodic_boundary_mask)
188 call messages_experimental('PeriodicBoundaryMask')
189 call parse_block_end(blk)
190 end if
191
192 ! Initialize coordinate system
193 call initialize_coordinate_system(gr, namespace, space, grid_spacing, latt, n_sites, site_position)
195 ! initialize derivatives
196 call derivatives_init(gr%der, namespace, space, gr%coord_system)
197 ! the stencil used to generate the grid is a union of a cube (for
198 ! multigrid) and the Laplacian
199 call stencil_cube_get_lapl(cube, space%dim, order = 2)
200 call stencil_union(cube, gr%der%lapl%stencil, gr%stencil)
201 call stencil_end(cube)
202
203 enlarge = 2
204 enlarge = max(enlarge, gr%der%n_ghost)
205
206 call mesh_init_stage_1(gr, namespace, space, gr%box, gr%coord_system, grid_spacing, enlarge)
207 call mesh_init_stage_2(gr, namespace, space, gr%box, gr%stencil)
208
209 pop_sub(grid_init_stage_1)
210 end subroutine grid_init_stage_1
211
212 !--------------------------------------------------------------------
214 subroutine grid_init_from_grid_stage_1(gr, original_gr, namespace, space, box, spacing_prefactor, latt, n_sites, site_position)
215 type(grid_t), intent(inout) :: gr
216 type(grid_t), intent(in) :: original_gr
217 type(namespace_t), intent(in) :: namespace
218 class(space_t), intent(in) :: space
219 class(box_t), target, optional, intent(in) :: box
220 real(real64), optional, intent(in) :: spacing_prefactor(:)
221 type(lattice_vectors_t), optional, intent(in) :: latt
222 integer, optional, intent(in) :: n_sites
223 real(real64), optional, intent(in) :: site_position(:,:)
224
225 type(stencil_t) :: cube
226 integer :: enlarge(space%dim)
227
229
230 ! First of all, create and associate the box that contains the grid
231 if (.not. present(box)) then
232 gr%box => box_factory_create(namespace, space)
233 else
234 gr%box => box
235 end if
236
237 !!! Copy all data !!!
238 ! Symmetries
239 gr%symm = original_gr%symm
240 ! Spacing
241 if (present(spacing_prefactor)) then
242 gr%spacing = spacing_prefactor * original_gr%spacing
243 if (any(abs(gr%spacing - m_one) > m_epsilon)) then
244 write(message(1), '(a)') "The two grids have different spacings, it will not be possible to establish a map between them"
245 call messages_warning(1)
246 end if
247 else
248 gr%spacing = original_gr%spacing
249 end if
250 ! Periodic boundaries
251 gr%masked_periodic_boundaries = original_gr%masked_periodic_boundaries
252 if (gr%masked_periodic_boundaries) gr%periodic_boundary_mask = original_gr%periodic_boundary_mask
253 ! Coordinate System
254 call initialize_coordinate_system(gr, namespace, space, gr%spacing, latt, n_sites, site_position)
255
256 ! initialize derivatives
257 call derivatives_init(gr%der, namespace, space, gr%coord_system)
258 ! the stencil used to generate the grid is a union of a cube (for
259 ! multigrid) and the Laplacian
260 call stencil_cube_get_lapl(cube, space%dim, order = 2)
261 call stencil_union(cube, gr%der%lapl%stencil, gr%stencil)
262 call stencil_end(cube)
263
264 enlarge = 2
265 enlarge = max(enlarge, gr%der%n_ghost)
266
267 call mesh_init_stage_1(gr, namespace, space, gr%box, gr%coord_system, gr%spacing, enlarge)
268 call mesh_init_stage_2(gr, namespace, space, gr%box, gr%stencil)
269
271 end subroutine grid_init_from_grid_stage_1
272
273
274 !--------------------------------------------------------------------
278 subroutine initialize_coordinate_system(gr, namespace, space, grid_spacing, latt, n_sites, site_position)
279 type(grid_t), intent(inout) :: gr
280 type(namespace_t), intent(in) :: namespace
281 class(space_t), intent(in) :: space
282 real(real64), intent(in) :: grid_spacing(:)
283 type(lattice_vectors_t), optional, intent(in) :: latt
284 integer, optional, intent(in) :: n_sites
285 real(real64), optional, intent(in) :: site_position(:,:)
286
287 integer :: cv_method
288
290
291 !%Variable CurvMethod
292 !%Type integer
293 !%Default curv_uniform
294 !%Section Mesh::Curvilinear
295 !%Description
296 !% The relevant functions in octopus are represented on a mesh in real space.
297 !% This mesh may be an evenly spaced regular rectangular grid (standard mode),
298 !% or else an adaptive or curvilinear grid. We have implemented
299 !% three kinds of adaptive meshes, although only one is currently working,
300 !% the one invented by F. Gygi (<tt>curv_gygi</tt>). The code will stop if any of
301 !% the other two is invoked. All are experimental with domain parallelization.
302 !%Option curv_affine 1
303 !% Regular, uniform rectangular grid.
304 !%Option curv_gygi 2
305 !% The deformation of the grid is done according to the scheme described by
306 !% F. Gygi [F. Gygi and G. Galli, <i>Phys. Rev. B</i> <b>52</b>, R2229 (1995)].
307 !%Option curv_briggs 3
308 !% The deformation of the grid is done according to the scheme described by
309 !% Briggs [E.L. Briggs, D.J. Sullivan, and J. Bernholc, <i>Phys. Rev. B</i> <b>54</b> 14362 (1996)]
310 !% (NOT WORKING).
311 !%Option curv_modine 4
312 !% The deformation of the grid is done according to the scheme described by
313 !% Modine [N.A. Modine, G. Zumbach and E. Kaxiras, <i>Phys. Rev. B</i> <b>55</b>, 10289 (1997)]
314 !% (NOT WORKING).
315 !%End
316 call parse_variable(namespace, 'CurvMethod', curv_affine, cv_method)
317 if (.not. varinfo_valid_option('CurvMethod', cv_method)) call messages_input_error(namespace, 'CurvMethod')
318 if (cv_method /= curv_affine .and. accel_is_enabled()) then
319 call messages_write('Curvilinear coordinates on GPUs is not implemented')
320 call messages_fatal(namespace=namespace)
321 end if
322 if (present(latt)) then
323 if (cv_method /= curv_affine .and. latt%nonorthogonal) then
324 call messages_input_error(namespace, 'CurvMethod', 'Curvilinear coordinates with non-orthogonal cells are not implemented')
325 end if
326 end if
327 call messages_print_var_option("CurvMethod", cv_method, namespace=namespace)
328
329 ! FIXME: The other two methods are apparently not working
330 if (cv_method > curv_gygi) then
331 call messages_experimental('Selected curvilinear coordinates method')
332 end if
333
334 select case (cv_method)
335 case (curv_briggs)
336 gr%coord_system => curv_briggs_t(namespace, space%dim, &
337 gr%box%bounding_box_l(1:space%dim), grid_spacing(1:space%dim))
338 case (curv_gygi)
339 if (present(site_position) .and. present(n_sites)) then
340 gr%coord_system => curv_gygi_t(namespace, space%dim, n_sites, site_position)
341 else
342 message(1) = "Option CurvMethod = curv_gygi is not currently implemented without ions present."
343 call messages_fatal(1, namespace=namespace)
344 end if
345 case (curv_modine)
346 if (present(site_position) .and. present(n_sites)) then
347 gr%coord_system => curv_modine_t(namespace, space%dim, n_sites, site_position, &
348 gr%box%bounding_box_l(1:space%dim), grid_spacing(1:space%dim))
349 else
350 message(1) = "Option CurvMethod = curv_modine is not currently implemented without ions present."
351 call messages_fatal(1, namespace=namespace)
352 end if
353 case (curv_affine)
354 if (present(latt)) then
355 if (latt%nonorthogonal) then
356 gr%coord_system => affine_coordinates_t(namespace, space%dim, latt%rlattice_primitive)
357 else
358 gr%coord_system => cartesian_t(namespace, space%dim)
359 end if
360 else
361 gr%coord_system => cartesian_t(namespace, space%dim)
362 end if
363 end select
364
366 end subroutine initialize_coordinate_system
367
368
369 !-------------------------------------------------------------------
377 subroutine grid_init_stage_2(gr, namespace, space, mc, qvector)
378 type(grid_t), target, intent(inout) :: gr
379 type(namespace_t), intent(in) :: namespace
380 class(space_t), intent(in) :: space
381 type(multicomm_t), intent(in) :: mc
382 real(real64), optional, intent(in) :: qvector(:)
383
384 push_sub(grid_init_stage_2)
385
386 call mesh_init_stage_3(gr, namespace, space, gr%stencil, mc)
387
388 call nl_operator_global_init(namespace)
389 call derivatives_build(gr%der, namespace, space, gr, qvector)
390
391 ! print info concerning the grid
392 call grid_write_info(gr, namespace=namespace)
393
394 if(space%dim == 3) then
395 call symmetrizer_init(gr%symmetrizer, gr, gr%symm)
396 end if
397
398 pop_sub(grid_init_stage_2)
399 end subroutine grid_init_stage_2
400
401
402 !-------------------------------------------------------------------
405 subroutine grid_end(gr)
406 type(grid_t), intent(inout) :: gr
407
408 class(coordinate_system_t), pointer :: coord_system
409 class(box_t), pointer :: box
410
411 push_sub(grid_end)
412
414
415 call derivatives_end(gr%der)
416
417 ! We need to take a pointer here, otherwise we run into a gfortran bug.
418 coord_system => gr%coord_system
419 safe_deallocate_p(coord_system)
420 box => gr%box
421 safe_deallocate_p(box)
422
423 call mesh_end(gr)
424
425 call stencil_end(gr%stencil)
426
427 call symmetrizer_end(gr%symmetrizer)
428
429 pop_sub(grid_end)
430 end subroutine grid_end
431
432
433 !-------------------------------------------------------------------
434 subroutine grid_write_info(gr, iunit, namespace)
435 type(grid_t), intent(in) :: gr
436 integer, optional, intent(in) :: iunit
437 type(namespace_t), optional, intent(in) :: namespace
438
439 push_sub(grid_write_info)
440
441 call messages_print_with_emphasis(msg="Grid", iunit=iunit, namespace=namespace)
442
443 message(1) = 'Simulation Box:'
444 call messages_info(1, iunit=iunit, namespace=namespace)
445 call gr%box%write_info(iunit, namespace)
446
447 message(1) = "Main mesh:"
448 call messages_info(1, iunit=iunit, namespace=namespace)
449 call mesh_write_info(gr, iunit, namespace)
450
451 if (gr%use_curvilinear) then
452 call gr%coord_system%write_info(iunit, namespace)
453 end if
454
455 call messages_print_with_emphasis(iunit=iunit, namespace=namespace)
456
457 pop_sub(grid_write_info)
458 end subroutine grid_write_info
459
460 !-------------------------------------------------------------------
464 subroutine grid_lattice_vectors_update(gr, space, namespace, mc, new_latt)
465 type(grid_t), intent(inout) :: gr
466 type(space_t), intent(in) :: space
467 type(namespace_t), intent(in) :: namespace
468 type(multicomm_t), intent(in) :: mc
469 type(lattice_vectors_t), intent(in) :: new_latt
471 real(real64) :: new_box_bounds(2, space%dim)
472
474
475 call new_latt%write_info(namespace)
476
477 ! Regenerate the coordinate system
478 select type (coord_system=>gr%coord_system)
479 type is (affine_coordinates_t)
480 if (new_latt%nonorthogonal) then
481 deallocate(gr%coord_system)
482 gr%coord_system => affine_coordinates_t(namespace, space%dim, new_latt%rlattice_primitive)
483 end if
484 end select
485
486 ! Regenerate the grid keeping the same number of points
487 select type (coord_system=>gr%coord_system)
488 class is (affine_coordinates_t)
489 new_box_bounds = gr%box%bounds(coord_system%basis)
490 gr%spacing = (new_box_bounds(2,:)-new_box_bounds(1,:))/gr%idx%ll(:)
491 write(message(1), '(a)') trim(gr%box%short_info(unit_angstrom))
492 call messages_info(1, namespace=namespace)
493 call messages_new_line()
494 end select
495
496 safe_deallocate_a(gr%x)
497 safe_deallocate_a(gr%chi)
498 safe_deallocate_a(gr%vol_pp)
499 safe_deallocate_a(gr%jacobian_inverse)
500 call mesh_init_stage_3(gr, namespace, space, gr%stencil, mc, regenerate=.true.)
501
502 call derivatives_build(gr%der, namespace, space, gr, regenerate=.true., verbose=.false.)
503
505 end subroutine grid_lattice_vectors_update
506
507#include "undef.F90"
508#include "real.F90"
509#include "grid_inc.F90"
510
511#include "undef.F90"
512#include "complex.F90"
513#include "grid_inc.F90"
514
515end module grid_oct_m
516
517!! Local Variables:
518!! mode: f90
519!! coding: utf-8
520!! End:
pure logical function, public accel_is_enabled()
Definition: accel.F90:427
Module, implementing a factory for boxes.
class(box_t) function, pointer, public box_factory_create(namespace, space, latt, n_sites, site_position)
initialize a box of any type
This module implements the curvilinear coordinates given in E.L. Briggs, D.J. Sullivan,...
This module implements the curvilinear coordinates given in F. Gygi and G. Galli, PRB 52 R2229 (1996)...
Definition: curv_gygi.F90:118
This module implements the curvilinear coordinates given in N. A. Modine, G. Zumbach,...
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public derivatives_build(der, namespace, space, mesh, qvector, regenerate, verbose)
build the derivatives object:
subroutine, public derivatives_init(der, namespace, space, coord_system, order)
subroutine, public derivatives_end(der)
real(real64), parameter, public m_zero
Definition: global.F90:188
real(real64), parameter, public m_epsilon
Definition: global.F90:204
real(real64), parameter, public m_one
Definition: global.F90:189
This module implements the underlying real-space grid.
Definition: grid.F90:117
subroutine, public grid_init_stage_1(gr, namespace, space, symm, latt, n_sites, site_position)
First stage of the grid initialization.
Definition: grid.F90:195
subroutine initialize_coordinate_system(gr, namespace, space, grid_spacing, latt, n_sites, site_position)
this subroutine initializes the coordinate system
Definition: grid.F90:372
integer, parameter curv_gygi
Definition: grid.F90:177
integer, parameter curv_briggs
Definition: grid.F90:177
subroutine, public zgrid_symmetrize_scalar_field(gr, field, suppress_warning)
Definition: grid.F90:813
subroutine, public grid_init_from_grid_stage_1(gr, original_gr, namespace, space, box, spacing_prefactor, latt, n_sites, site_position)
this subroutine allows to create a grid from an existing grid
Definition: grid.F90:308
subroutine, public zgrid_symmetrize_vector_field(gr, field, suppress_warning)
Definition: grid.F90:839
subroutine, public grid_init_stage_2(gr, namespace, space, mc, qvector)
Second stage of the grid initialization.
Definition: grid.F90:471
subroutine, public dgrid_symmetrize_vector_field(gr, field, suppress_warning)
Definition: grid.F90:695
subroutine, public grid_write_info(gr, iunit, namespace)
Definition: grid.F90:528
subroutine, public dgrid_symmetrize_single(gr, iop, field, symm_field, suppress_warning)
Definition: grid.F90:723
subroutine, public grid_lattice_vectors_update(gr, space, namespace, mc, new_latt)
Regenerate the grid information after update of the lattice vectors.
Definition: grid.F90:558
subroutine, public zgrid_symmetrize_single(gr, iop, field, symm_field, suppress_warning)
Definition: grid.F90:867
subroutine, public grid_end(gr)
finalize a grid object
Definition: grid.F90:499
subroutine, public dgrid_symmetrize_scalar_field(gr, field, suppress_warning)
Definition: grid.F90:669
integer, parameter curv_modine
Definition: grid.F90:177
This module contains subroutines, related to the initialization of the mesh.
Definition: mesh_init.F90:117
subroutine, public mesh_init_stage_3(mesh, namespace, space, stencil, mc, parent, regenerate)
When running parallel in domains, stencil and np_stencil are needed to compute the ghost points....
Definition: mesh_init.F90:538
subroutine, public mesh_init_stage_1(mesh, namespace, space, box, coord_system, spacing, enlarge)
First stage mesh initialization.
Definition: mesh_init.F90:170
subroutine, public mesh_init_stage_2(mesh, namespace, space, box, stencil, regenerate)
This subroutine creates the global array of spatial indices and the inverse mapping.
Definition: mesh_init.F90:290
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
subroutine, public mesh_write_info(this, iunit, namespace)
Definition: mesh.F90:306
recursive subroutine, public mesh_end(this)
Definition: mesh.F90:682
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:920
character(len=512), private msg
Definition: messages.F90:165
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:537
subroutine, public messages_new_line()
Definition: messages.F90:1134
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:414
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:713
subroutine, public messages_experimental(name, namespace)
Definition: messages.F90:1085
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:616
This module handles the communicators for the various parallelization strategies.
Definition: multicomm.F90:145
This module defines non-local operators.
subroutine, public nl_operator_global_init(namespace)
initialize global settings for non-local operators
subroutine, public nl_operator_global_end()
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:618
This module defines routines, generating operators for a cubic stencil.
subroutine, public stencil_cube_get_lapl(this, dim, order)
This module defines stencils used in Octopus.
Definition: stencil.F90:135
subroutine, public stencil_end(this)
Definition: stencil.F90:214
subroutine, public stencil_union(st1, st2, stu)
Definition: stencil.F90:226
subroutine, public symmetrizer_end(this)
subroutine, public symmetrizer_init(this, mesh, symm)
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:132
This module defines the unit system, used for input and output.
type(unit_t), public unit_angstrom
For XYZ files.
type(unit_system_t), public units_inp
the units systems for reading and writing
Class implementing a box generated from a 2D image.
Definition: box_image.F90:133
class to tell whether a point is inside or outside
Definition: box.F90:141
abstract class to describe coordinate systems
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:169
Describes mesh distribution to nodes.
Definition: mesh.F90:186
Stores all communicators and groups.
Definition: multicomm.F90:206
The class representing the stencil, which is used for non-local mesh operations.
Definition: stencil.F90:163
int true(void)