mesh_cart_m.f90 Source File


Source Code

module mesh_cart_m
    !! Module implementing the 2d mesh
    use netcdf
    use precision_m, only: FP, FP_LARGEST
    use comm_handling_m, only: is_master
    use equilibrium_m,    only: equilibrium_t
    use slab_equilibrium_m, only: slab_t
    use descriptors_m, only: DISTRICT_CORE, DISTRICT_CLOSED, DISTRICT_SOL, &
                             DISTRICT_WALL, DISTRICT_PRIVFLUX, DISTRICT_DOME, &
                             DISTRICT_OUT
    use error_handling_m, only: handle_error, error_info_t
    use status_codes_m, only: PARALLAX_ERR_MESH, PARALLAX_WRN_MESH
    use status_codes_m, only: PARALLAX_ERR_MESH
    use, intrinsic :: iso_c_binding, only: c_int32_t, c_bool, c_ptr, c_loc, &
                                           c_null_ptr
    implicit none

    integer, parameter, private :: PINFO_INNER      = 1
    !! Descriptor (internal) for inner grid point
    integer, parameter, private :: PINFO_BOUNDARY   = 2
    !! Descriptor (internal) for boundary point
    integer, parameter, private :: PINFO_GHOST      = 3
    !! Descriptor (internal) for ghost point

    type, public, bind(C) :: mesh_cart_data_t
        !! Data type used to expose `mesh_cart_t` data to C/C++
        !! Please see `mesh_cart_t` for descriptions of individual
        !! properties/members.
        !! Values are copied directly.
        !! Arrays are exposed with pointers.
        logical(c_bool)    :: extend_beyond_wall
        integer(c_int32_t) :: lvl
        integer(c_int32_t) :: lvst
        real(FP)           :: spacing_f
        real(FP)           :: spacing_c
        integer(c_int32_t) :: n_points

        real(FP)           :: phi
        real(FP)           :: xmin
        real(FP)           :: ymin
        integer(c_int32_t) :: nx_f
        integer(c_int32_t) :: ny_f
        type(c_ptr)        :: cart_i
        type(c_ptr)        :: cart_j

        integer(c_int32_t) :: size_neighbor
        type(c_ptr)        :: index_neighbor
        integer(c_int32_t) :: size_ghost_layer

        integer(c_int32_t) :: n_points_inner
        type(c_ptr)        :: inner_indices
        integer(c_int32_t) :: n_points_boundary
        type(c_ptr)        :: boundary_indices
        integer(c_int32_t) :: n_points_ghost
        type(c_ptr)        :: ghost_indices
        type(c_ptr)        :: pinfo

        type(c_ptr)        :: district

        integer(c_int32_t) :: n_points_red
        integer(c_int32_t) :: n_points_black
        type(c_ptr)        :: redblack_indices
    end type mesh_cart_data_t

    type, public :: mesh_cart_t
        !! Datatype for a mesh_2d
        logical, private :: extend_beyond_wall
        !! If true, mesh is extended beyond the wall
        integer, private :: lvl
        !! Level of coarseness of grid, required for multigrid solver lvl=1 is finest level.
        !! lvl=2,3,4.. correspond to a increased coarseness by a factor of 2,4,8,... respectively.
        integer, private :: lvst
        !! Discrete grid distance
        real(FP), private :: spacing_f
        !! Grid spacing on the finest level
        real(FP), public :: spacing_c
        !! Grid spacing on the actual level (coarse)
        !! NOTE: This variable is set public only temporarily and must not be
        !!  changed from outside of this module.
        !!  In normal circumstances use the routine get_spacing_c.
        !!  (It needs to be accessed directly in helmholtz_operators,
        !!  to circumvent the known issue of OMP scaling with intel compiler)
        integer, public :: n_points
        !! Number of total mesh points
        !! NOTE: This variable is set public only temporarily and must not be
        !!  changed from outside of this module.
        !!  In normal circumstances use the routine get_n_points.
        !!  (It needs to be accessed directly in helmholtz_operators,
        !!  to circumvent the known issue of OMP scaling with intel compiler)
        real(FP), private :: phi
        !! Toroidal angle of mesh, normalized to range [0, 2pi)
        real(FP), private :: xmin
        !! Reference point to compute x-coordinate
        real(FP), private :: ymin
        !! Reference point to compute y-coordinate
        integer, private :: nx_f
        !! x-dimension of rectangular Cartesian unmasked grid (finest level)
        integer, private :: ny_f
        !! y-dimension of rectangular Cartesian unmasked grid (finest level)
        integer, private, allocatable, dimension(:) :: cart_i
        !! Indices in Cartesian logical space in x direction (x_i, y_j)
        integer, private, allocatable, dimension(:) :: cart_j
        !! Indices in Cartesian logical space in y direction (x_i, y_j)
        integer, private, allocatable, dimension(:,:) :: cart_shaped_l
        !! A 2d array where the (i, j)^th element gives the index l
        !! such that cart_i(l) == i and cart_j(l) == j
        integer, private :: min_i, max_i, min_j, max_j
        !! Limits of the cart_i and cart_j arrays

        integer, private :: size_neighbor
        !! Number of neighbor points in each direction (left, right, bottom, top)
        integer, public, allocatable, dimension(:,:,:) :: index_neighbor
        !! Index of neighbor points
        integer, private :: size_ghost_layer
        !! Depth of ghost layer

        integer, private :: n_points_inner
        !! Number of inner points
        integer, public, allocatable, dimension(:) :: inner_indices
        !! Indices of inner points
        integer, private :: n_points_boundary
        !! Number of boundary points
        integer, public, allocatable, dimension(:) :: boundary_indices
        !! Indices of boundary points
        integer, private :: n_points_ghost
        !! Number of ghost points
        integer, public, allocatable, dimension(:) :: ghost_indices
        !! Indices of ghost points
        integer, private, allocatable, dimension(:) :: pinfo
        !! Stores information for mesh point

        integer, private, allocatable, dimension(:) :: district
        !! Stores information on logical location of grid point

        logical, private :: yperiodic
        !! Only relevant for SLAB equilibrium, indicates periodicity in y-direction

        integer, private :: n_points_red
        !! Number of red points (chequerboard)
        integer, private :: n_points_black
        !! Number of black points (chequerboard)
        integer, public, allocatable, dimension(:) :: redblack_indices
        !! Index list of redblack points, eventually needed for red-black gauss seidel smoother
        !! First nred entries are indices of red points
        !! Following nblack entries are indices of black points
        !! Final nboundary+nghost entries are indices of boundary and ghost points

    contains
        ! Getter routines
        procedure, public :: get_phi
        procedure, public :: set_phi
        procedure, public :: get_lvl
        procedure, public :: get_lvst
        procedure, public :: get_n_points
        procedure, public :: get_spacing_f
        procedure, public :: get_spacing_c
        procedure, public :: get_size_neighbor
        procedure, public :: get_cart_i
        procedure, public :: get_cart_j
        procedure, public :: get_x
        procedure, public :: get_y
        procedure, public :: get_n_points_inner
        procedure, public :: get_n_points_boundary
        procedure, public :: get_n_points_ghost
        procedure, public :: get_xmin
        procedure, public :: get_ymin
        procedure, public :: get_n_points_red
        procedure, public :: get_n_points_black

        procedure, public :: is_inner_point
        procedure, public :: is_boundary_point
        procedure, public :: is_ghost_point
        procedure, public :: get_district

        procedure, public :: cart_to_mesh_index
        procedure, public :: build_shaped_cart_arrays
        procedure, public :: deallocate_shaped_cart_arrays
        procedure, public :: get_index_neighbor

        procedure, public :: determine_interpolation_stencil
        procedure, public :: get_surrounding_indices

        procedure, public :: normal_to_boundary

        ! I/O rotines
        procedure, public :: display => display_mesh_cart
        procedure, public :: write_netcdf => write_netcdf_mesh_cart
        procedure, public :: read_netcdf => read_netcdf_mesh_cart

        ! Build routines
        procedure, public :: init => init_mesh_cart
        procedure, private :: build_cart
        procedure, private :: build_cart_slab
        procedure, private :: build_connectivity
        procedure, private :: build_boundary
        procedure, private :: build_ghost_layer
        procedure, private :: build_pinfo
        procedure, private :: build_district
        procedure, private :: build_patch
        procedure, private :: build_redblack
        procedure, private :: point_inside
        procedure, public :: reorder

        ! Routines for MPI comminication of mesh
        procedure, public :: exchange_mesh_mpi

        ! C interoperability routines
        procedure, public :: expose_data
    end type

    interface

        pure real(FP) module function get_phi(self)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
        end function

        module subroutine set_phi(self, new_phi)
            !! Sets phi value of mesh to a new value
            class(mesh_cart_t), intent(inout) :: self
            !! Instance of the type
            real(FP), intent(in) :: new_phi
            !! New phi value
        end subroutine

        pure integer module function get_lvl(self)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
        end function

        pure integer module function get_lvst(self)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
        end function

        pure integer module function get_n_points(self)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
        end function

        pure real(FP) module function get_spacing_f(self)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
        end function

        pure real(FP) module function get_spacing_c(self)
            !! Returns mesh distance of level, spacing_c = spacing_f*lvst
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
        end function

        pure integer module function get_size_neighbor(self)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
        end function

        pure integer module function get_cart_i(self, ind)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
            integer, intent(in) :: ind
            !! Mesh index
        end function

        pure integer module function get_cart_j(self, ind)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
            integer, intent(in) :: ind
            !! Mesh index
        end function

        pure real(FP) module function get_x(self, ind)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
            integer, intent(in) :: ind
            !! Mesh index
        end function

        pure real(FP) module function get_y(self, ind)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
            integer, intent(in) :: ind
            !! Mesh index
        end function

        pure integer module function get_n_points_inner(self)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
        end function

        pure integer module function get_n_points_boundary(self)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
        end function

        pure integer module function get_n_points_ghost(self)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
        end function

        pure real(FP) module function get_xmin(self)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
        end function

        pure real(FP) module function get_ymin(self)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
        end function

        pure integer module function get_n_points_red(self)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
        end function

        pure integer module function get_n_points_black(self)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
        end function

        pure integer module function get_index_neighbor(self, ishift, jshift, ind)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
            integer, intent(in) :: ishift
            !! Shift in horizontal direction w.r.t. point ind
            integer, intent(in) :: jshift
            !! Shift in vertical direction w.r.t. point ind
            integer, intent(in) :: ind
            !! Mesh index
        end function

        integer module function cart_to_mesh_index(self, i, j)
            !! Given Cartesian indizes (i,j) returns mesh index
            !! if no point could be found 0 is returned
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
            integer, intent(in) :: i
            !! Horizontal Cartesian index
            integer, intent(in) :: j
            !! Vertical Cartesian index
        end function

        module subroutine build_shaped_cart_arrays(self)
            !! Builds a 2D array where shaped_cart_l(i,j) = l gives the index
            !! where cart_i(l) == i and cart_j(l) == j, or zero if no point
            !! is found. Used to accelerate cart_to_mesh_index
            class(mesh_cart_t), intent(inout) :: self
        end subroutine

        module subroutine deallocate_shaped_cart_arrays(self)
            !! Deallocates the shaped_cart_l array to reduce the memory
            !! requirement for the grid
            class(mesh_cart_t), intent(inout) :: self
        end subroutine

        pure logical module function is_inner_point(self, ind)
            !! Indicates if point is inner grid point
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
            integer, intent(in) :: ind
            !! Mesh index
        end function

        pure logical module function is_boundary_point(self, ind)
            !! Indicates if point is boundary point
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
            integer, intent(in) :: ind
            !! Mesh index
        end function

        pure logical module function is_ghost_point(self, ind)
            !! Indicates if point is ghost point
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
            integer, intent(in) :: ind
            !! Mesh index
        end function

        pure integer module function get_district(self, ind)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
            integer, intent(in) :: ind
            !! Mesh index
        end function

        module subroutine determine_interpolation_stencil(self, xp, yp, &
            intorder, ns_max_nearest, ns_stencil, intorder_actual, &
            ind_interpol_stencil)
            !! Finds ns_stencil x ns_stencil indices of interpolation stencil
            !! around (xp, yp), if possible of order intorder
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
            real(FP), intent(in) :: xp
            !! x-coordinate of point
            real(FP), intent(in) :: yp
            !! y-coordinate of point
            integer, intent(in) :: intorder
            !! Requested stencil order
            integer, intent(in) :: ns_max_nearest
            !! Size of area that is searched for nearest point
            integer, intent(out) :: ns_stencil
            !! Size of determined stencil
            integer, intent(out) :: intorder_actual
            !! Order of determined stencil
            integer, allocatable, dimension(:,:), intent(out) :: ind_interpol_stencil
            !! Indices of determined stencil
        end subroutine

        module subroutine get_surrounding_indices(self, xp, yp, ns, ind_sur, ns_complete, ind_nearest)
            !! Finds ns x ns indices of points surrounding (xp, yp)
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
            real(FP), intent(in) :: xp
            !! x-coordinate of point
            real(FP), intent(in) :: yp
            !! y-coordinate of point
            integer, intent(in) :: ns
            !! Dimension of surrounding local grid
            integer, intent(out), optional, dimension(ns, ns) :: ind_sur
            !! Indices of surrounding grid points
            integer, intent(out), optional :: ns_complete
            !! Dimension of surrounding local grid, that is complete (w/o missing points)
            integer, intent(out), optional :: ind_nearest
            !! Index of nearest point on surrounding grid
        end subroutine

        module subroutine normal_to_boundary(self, ind, nbx, nby)
            !! Returns the discrete normal vector to the boundary
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
            integer, intent(in) :: ind
            !! Mesh index, must be index of a boundary point
            integer, intent(out) :: nbx
            !! x-component of discrete normal vector
            integer, intent(out) :: nby
            !! y-component of discrete normal vector
        end subroutine

        module subroutine display_mesh_cart(self)
            !! Displays information for mesh
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
        end subroutine

        module subroutine write_netcdf_mesh_cart(self, fgid)
            !! Writes the mesh to netcdf
            class(mesh_cart_t), intent(inout) :: self
            !! Instance of the type
            integer, intent(in) :: fgid
            !! File or group id number of existing Netcdf4 file
        end subroutine

        module subroutine read_netcdf_mesh_cart(self, fgid)
            !! Reads mesh from netcdf
            class(mesh_cart_t), intent(inout) :: self
            !! Instance of the type
            integer, intent(in) :: fgid
            !! File or group id number of existing Netcdf4 file
        end subroutine

        module subroutine init_mesh_cart(self, equi, phi, lvl, spacing_f, &
                                         size_neighbor, size_ghost_layer, &
                                         extend_beyond_wall, dbgout)
            !! Builds complete mesh
            class(mesh_cart_t), intent(out) :: self
            !! Instance of the type
            class(equilibrium_t), intent(inout) :: equi
            !! Equilibrium
            real(FP), intent(in) :: phi
            !! Toroidal angle
            integer, intent(in) :: lvl
            !! Coarseness level
            real(FP), intent(inout) :: spacing_f
            !! Grid spacing on finest level
            integer, intent(in) :: size_neighbor
            !! Number of neighbor points determined in each direction
            integer, intent(in) :: size_ghost_layer
            !! Depth of ghost point layer
            logical, intent(in) ::extend_beyond_wall
            !! If true, mesh is extended beyond the wall
            integer, intent(in), optional ::dbgout
            !! Debug output level
        end subroutine

        module subroutine build_cart(self, equi, lvl, spacing_f)
            !! Builds Cartesian grid
            class(mesh_cart_t), intent(inout) :: self
            !! Instance of the type
            class(equilibrium_t), intent(inout) :: equi
            !! Equilibrium
            integer, intent(in) :: lvl
            !! Coarseness level
            real(FP), intent(in) :: spacing_f
            !! Grid spacing on finest level
        end subroutine

        module subroutine build_connectivity(self, size_neighbor)
            !! Establishes connectivity among grid points
            class(mesh_cart_t), intent(inout) :: self
            !! Instance of the type
            integer, intent(in) :: size_neighbor
            !! Number of neighbor points in each direction (left, right, bottom, top)
        end subroutine

        module subroutine build_boundary(self)
            !! Builds discrete boundary, i.e. finds point that are located on boundary
            class(mesh_cart_t), intent(inout) :: self
            !! Instance of the type
        end subroutine

        module subroutine build_ghost_layer(self, size_ghost_layer)
            !! Builds ghost layer surrounding inner grid
            class(mesh_cart_t), intent(inout) :: self
            !! Instance of the type
            integer, intent(in) :: size_ghost_layer
            !! Depth of ghost layer
        end subroutine

        module subroutine build_pinfo(self)
            !! Build information for individual mesh points
            class(mesh_cart_t), intent(inout) :: self
            !! Instance of the type
        end subroutine

        module subroutine build_district(self, equi)
            !! Build district (logical location) for individual mesh points
            class(mesh_cart_t), intent(inout) :: self
            !! Instance of the type
            class(equilibrium_t), intent(in) :: equi
            !! Equilibrium
        end subroutine

        module subroutine build_patch(self)
            !! Applies patch to mesh
            !! boundary points without connection to inner points are moved the ghost points
            class(mesh_cart_t), intent(inout) :: self
            !! Instance of the type
        end subroutine

        module subroutine build_redblack(self)
            !! Builds index list identifying red and black points (chequerboard) of mesh
            class(mesh_cart_t), intent(inout) :: self
            !! Instance of the type
        end subroutine

        module subroutine build_cart_slab(self, equi, lvl, npwr)
            !! Builds Cartesian grid for slab geometry
            class(mesh_cart_t), intent(inout) :: self
            !! Instance of the type
            class(equilibrium_t), intent(inout) :: equi
            !! Equilibrium
            integer, intent(in) :: lvl
            !! Coarseness level
            integer, intent(in) :: npwr
            !! Power exponent for number of grid points in x direction nxf = 2^npwr+1
        end subroutine

        module subroutine reorder(self, grid_reorder_block, dbgout)
            !! Reorders mesh indices for cache optimisation
            class(mesh_cart_t), intent(inout) :: self
            !! Instance of the type
            integer, intent(in)  :: grid_reorder_block
            !! Size of basic unshuffled grid square
            integer, intent(in), optional ::dbgout
            !! Debug output level
        end subroutine

        logical module function point_inside(self, district)
            !! Definition which district (point location in logical sense)
            !! is inside the mesh
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
            integer, intent(in) :: district
            !! District descriptor
        end function

        module subroutine exchange_mesh_mpi(self, comm, step, mesh_received)
            !! MPI communication of mesh
            !! Sends mesh to rank-step and receives from rank+step
            class(mesh_cart_t), intent(in) :: self
            !! Instance of the type
            integer, intent(in) :: comm
            !! MPI communicator
            integer, intent(in) :: step
            !! Step size of MPI communication
            type(mesh_cart_t), intent(out) :: mesh_received
            !! Mesh received from rank+step
        end subroutine

        module subroutine expose_data(self, data_object)
            !! Exposes mesh data through mesh_cart_data_t object
            class(mesh_cart_t), intent(in), target :: self
            !! Instance of the type
            type(mesh_cart_data_t), intent(out)  :: data_object
            !! Destination mesh cart data object.
            !! **Warning**: the purpose of this method is to allow
            !! access to the data of the instance.
        end subroutine

    end interface

end module