!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch !! !! This program is free software; you can redistribute it and/or modify !! it under the terms of the GNU General Public License as published by !! the Free Software Foundation; either version 2, or (at your option) !! any later version. !! !! This program is distributed in the hope that it will be useful, !! but WITHOUT ANY WARRANTY; without even the implied warranty of !! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !! GNU General Public License for more details. !! !! You should have received a copy of the GNU General Public License !! along with this program; if not, write to the Free Software !! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA !! 02110-1301, USA. !! #include "global.h" module grid_oct_m use cube_oct_m use curvilinear_oct_m use derivatives_oct_m use double_grid_oct_m use geometry_oct_m use global_oct_m use mesh_oct_m use mesh_init_oct_m use messages_oct_m use mpi_oct_m use multicomm_oct_m use multigrid_oct_m use namespace_oct_m use nl_operator_oct_m use parser_oct_m use profiling_oct_m use space_oct_m use simul_box_oct_m use stencil_oct_m use stencil_cube_oct_m use unit_oct_m use unit_system_oct_m implicit none private public :: & grid_t, & grid_init_stage_0, & grid_init_stage_1, & grid_init_stage_2, & grid_end, & grid_write_info, & grid_create_multigrid type grid_t ! Components are public by default type(simul_box_t) :: sb type(mesh_t) :: mesh type(multigrid_level_t) :: fine type(derivatives_t) :: der type(curvilinear_t) :: cv type(multigrid_t), pointer :: mgrid type(double_grid_t) :: dgrid logical :: have_fine_mesh type(stencil_t) :: stencil end type grid_t contains !------------------------------------------------------------------- !> !! "Zero-th" stage of grid initialization. It initializes the simulation box. subroutine grid_init_stage_0(gr, namespace, geo, space) type(grid_t), intent(inout) :: gr type(namespace_t), intent(in) :: namespace type(geometry_t), intent(inout) :: geo type(space_t), intent(in) :: space PUSH_SUB(grid_init_stage_0) call simul_box_init(gr%sb, namespace, geo, space) POP_SUB(grid_init_stage_0) end subroutine grid_init_stage_0 !------------------------------------------------------------------- subroutine grid_init_stage_1(gr, namespace, geo) type(grid_t), intent(inout) :: gr type(namespace_t), intent(in) :: namespace type(geometry_t), intent(in) :: geo type(stencil_t) :: cube integer :: enlarge(1:MAX_DIM) type(block_t) :: blk integer :: idir FLOAT :: def_h, def_rsize FLOAT :: grid_spacing(1:MAX_DIM) PUSH_SUB(grid_init_stage_1) !%Variable UseFineMesh !%Type logical !%Default no !%Section Mesh !%Description !% If enabled, Octopus will use a finer mesh for the calculation !% of the forces or other sensitive quantities. !% Experimental, and incompatible with domain-parallelization. !%End if (gr%sb%dim == 3) then call parse_variable(namespace, 'UseFineMesh', .false., gr%have_fine_mesh) else gr%have_fine_mesh = .false. end if if(gr%have_fine_mesh) call messages_experimental("UseFineMesh") call geometry_grid_defaults(geo, def_h, def_rsize) ! initialize to -1 grid_spacing = -M_ONE !%Variable Spacing !%Type float !%Section Mesh !%Description !% The spacing between the points in the mesh. This controls the !% quality of the discretization: smaller spacing gives more !% precise results but increased computational cost. !% !% When using curvilinear coordinates, this is a canonical spacing !% that will be changed locally by the transformation. In periodic !% directions, your spacing may be slightly different than what !% you request here, since the box size must be an integer !% multiple of the spacing. !% !% The default value is defined by the species if only default pseudopotentials are used !% or by the image resolution if BoxShape = box_image. Otherwise, there is !% no default. !% !% It is possible to have a different spacing in each one of the Cartesian directions !% if we define Spacing as block of the form !% !% %Spacing !%
  spacing_x | spacing_y | spacing_z !%
%
!%End if(parse_block(namespace, 'Spacing', blk) == 0) then if(parse_block_cols(blk,0) < gr%sb%dim) call messages_input_error(namespace, 'Spacing') do idir = 1, gr%sb%dim call parse_block_float(blk, 0, idir - 1, grid_spacing(idir), units_inp%length) if(def_h > M_ZERO) call messages_check_def(grid_spacing(idir), .true., def_h, 'Spacing', units_out%length) end do call parse_block_end(blk) else call parse_variable(namespace, 'Spacing', -M_ONE, grid_spacing(1), units_inp%length) grid_spacing(1:gr%sb%dim) = grid_spacing(1) if(def_h > M_ZERO) call messages_check_def(grid_spacing(1), .true., def_h, 'Spacing', units_out%length) end if #if defined(HAVE_GDLIB) if(gr%sb%box_shape == BOX_IMAGE) then do idir = 1, gr%sb%dim ! default grid_spacing is determined from lsize and the size of the image if(grid_spacing(idir) < M_ZERO) then grid_spacing(idir) = M_TWO*gr%sb%lsize(idir)/TOFLOAT(gr%sb%image_size(idir)) end if end do end if #endif if (any(grid_spacing(1:gr%sb%dim) < M_EPSILON)) then if (def_h > M_ZERO .and. def_h < huge(def_h)) then call geometry_grid_defaults_info(geo) do idir = 1, gr%sb%dim grid_spacing(idir) = def_h write(message(1), '(a,i1,3a,f6.3)') "Info: Using default spacing(", idir, & ") [", trim(units_abbrev(units_out%length)), "] = ", & units_from_atomic(units_out%length, grid_spacing(idir)) call messages_info(1) end do ! Note: the default automatically matches the 'recommended' value compared by messages_check_def above. else message(1) = 'Either:' message(2) = " *) variable 'Spacing' is not defined and" message(3) = " I can't find a suitable default" message(4) = " *) your input for 'Spacing' is negative or zero" call messages_fatal(4) end if end if !%Variable PeriodicBoundaryMask !%Type block !%Section Mesh !%Description !% (Experimental) Defines a mask for which periodic boundaries are replaced by zero boundary conditions. !%End if(parse_block(namespace, 'PeriodicBoundaryMask', blk) < 0) then gr%mesh%masked_periodic_boundaries = .false. else gr%mesh%masked_periodic_boundaries = .true. call parse_block_string(blk, 0, 0, gr%mesh%periodic_boundary_mask) call messages_experimental('PeriodicBoundaryMask') end if ! initialize curvilinear coordinates call curvilinear_init(gr%cv, namespace, gr%sb, geo, grid_spacing) ! initialize derivatives call derivatives_nullify(gr%der) call derivatives_init(gr%der, namespace, gr%sb, gr%cv%method /= CURV_METHOD_UNIFORM) call double_grid_init(gr%dgrid, namespace, gr%sb) enlarge = 0 enlarge(1:gr%sb%dim) = 2 enlarge = max(enlarge, double_grid_enlarge(gr%dgrid)) enlarge = max(enlarge, gr%der%n_ghost) ! now we generate the mesh and the derivatives call mesh_init_stage_1(gr%mesh, gr%sb, gr%cv, grid_spacing, enlarge) ! the stencil used to generate the grid is a union of a cube (for ! multigrid) and the Laplacian. call stencil_cube_get_lapl(cube, gr%sb%dim, order = 2) call stencil_union(gr%sb%dim, cube, gr%der%lapl%stencil, gr%stencil) call stencil_end(cube) call mesh_init_stage_2(gr%mesh, gr%sb, geo, gr%cv, gr%stencil, namespace) POP_SUB(grid_init_stage_1) end subroutine grid_init_stage_1 !------------------------------------------------------------------- subroutine grid_init_stage_2(gr, namespace, mc, geo) type(grid_t), target, intent(inout) :: gr type(namespace_t), intent(in) :: namespace type(multicomm_t), intent(in) :: mc type(geometry_t), intent(in) :: geo PUSH_SUB(grid_init_stage_2) call mesh_init_stage_3(gr%mesh, namespace, gr%stencil, mc) call nl_operator_global_init(namespace) if(gr%have_fine_mesh) then message(1) = "Info: coarse mesh" call messages_info(1) end if call derivatives_build(gr%der, namespace, gr%mesh) ! initialize a finer mesh to hold the density, for this we use the ! multigrid routines if(gr%have_fine_mesh) then if(gr%mesh%parallel_in_domains) then message(1) = 'UseFineMesh does not work with domain parallelization.' call messages_fatal(1) end if SAFE_ALLOCATE(gr%fine%mesh) SAFE_ALLOCATE(gr%fine%der) call multigrid_mesh_double(geo, gr%cv, gr%mesh, gr%fine%mesh, gr%stencil, namespace) call derivatives_nullify(gr%fine%der) call derivatives_init(gr%fine%der, namespace, gr%mesh%sb, gr%cv%method /= CURV_METHOD_UNIFORM) call mesh_init_stage_3(gr%fine%mesh, namespace, gr%stencil, mc) call multigrid_get_transfer_tables(gr%fine%tt, gr%fine%mesh, gr%mesh) message(1) = "Info: fine mesh" call messages_info(1) call derivatives_build(gr%fine%der, namespace, gr%fine%mesh) gr%fine%der%coarser => gr%der gr%der%finer => gr%fine%der gr%fine%der%to_coarser => gr%fine%tt gr%der%to_finer => gr%fine%tt else gr%fine%mesh => gr%mesh gr%fine%der => gr%der end if ! multigrids are not initialized by default nullify(gr%mgrid) ! print info concerning the grid call grid_write_info(gr, geo, stdout) POP_SUB(grid_init_stage_2) end subroutine grid_init_stage_2 !------------------------------------------------------------------- subroutine grid_end(gr) type(grid_t), intent(inout) :: gr PUSH_SUB(grid_end) call nl_operator_global_end() if(gr%have_fine_mesh) then call derivatives_end(gr%fine%der) call mesh_end(gr%fine%mesh) SAFE_DEALLOCATE_P(gr%fine%mesh) SAFE_DEALLOCATE_P(gr%fine%der) SAFE_DEALLOCATE_P(gr%fine%tt%to_coarse) SAFE_DEALLOCATE_P(gr%fine%tt%to_fine1) SAFE_DEALLOCATE_P(gr%fine%tt%to_fine2) SAFE_DEALLOCATE_P(gr%fine%tt%to_fine4) SAFE_DEALLOCATE_P(gr%fine%tt%to_fine8) SAFE_DEALLOCATE_P(gr%fine%tt%fine_i) end if call double_grid_end(gr%dgrid) call derivatives_end(gr%der) call curvilinear_end(gr%cv) call mesh_end(gr%mesh) if(associated(gr%mgrid)) then call multigrid_end(gr%mgrid) SAFE_DEALLOCATE_P(gr%mgrid) end if call stencil_end(gr%stencil) POP_SUB(grid_end) end subroutine grid_end !------------------------------------------------------------------- subroutine grid_write_info(gr, geo, iunit) type(grid_t), intent(in) :: gr type(geometry_t), intent(in) :: geo integer, intent(in) :: iunit PUSH_SUB(grid_write_info) if(.not.mpi_grp_is_root(mpi_world)) then if(debug%info) call messages_debug_newlines(6) POP_SUB(grid_write_info) return end if call messages_print_stress(iunit, "Grid") call simul_box_write_info(gr%sb, geo, iunit) if(gr%have_fine_mesh) then message(1) = "Wave-functions mesh:" call messages_info(1, iunit) call mesh_write_info(gr%mesh, iunit) message(1) = "Density mesh:" else message(1) = "Main mesh:" end if call messages_info(1, iunit) call mesh_write_info(gr%fine%mesh, iunit) if (gr%mesh%use_curvilinear) then call curvilinear_write_info(gr%cv, iunit) end if call messages_print_stress(iunit) POP_SUB(grid_write_info) end subroutine grid_write_info !------------------------------------------------------------------- subroutine grid_create_multigrid(gr, namespace, geo, mc) type(grid_t), intent(inout) :: gr type(namespace_t), intent(in) :: namespace type(geometry_t), intent(in) :: geo type(multicomm_t), intent(in) :: mc PUSH_SUB(grid_create_multigrid) SAFE_ALLOCATE(gr%mgrid) call multigrid_init(gr%mgrid, namespace, geo, gr%cv, gr%mesh, gr%der, gr%stencil, mc) POP_SUB(grid_create_multigrid) end subroutine grid_create_multigrid end module grid_oct_m !! Local Variables: !! mode: f90 !! coding: utf-8 !! End: