diagnostic_variable_m.f90 Source File


Contents


Source Code

module diagnostic_variable_m
    !! Definition of diagnostic variable
    use MPI
    use netcdf
    use precision_grillix_m, only : GP
    use error_handling_grillix_m, only: handle_error_netcdf, handle_error
    use status_codes_grillix_m, only : GRILLIX_ERR_ALLOC

    ! from PARALLAX
    use screen_io_m, only :  get_stdout
    implicit none

    type, public :: diagnostic_variable_t
        !! Datatype for diagnostic variables
        integer, private :: ndim
        !! Dimension of diagnostic variable
        real(GP), allocatable, dimension(:), public :: vals
        !! Values of diagnostic variable
        character(len=:), allocatable, private :: varname
        !! Name of diagnostic variable
        character(len=:), allocatable, private :: dimname
        !! Name of dimension of diagnostic variable
    contains
        procedure, public :: get_ndim
        procedure, public :: init => init_diagnostic_variable
        procedure, public :: write_netcdf => write_netcdf_diagnostic_variable
        final :: destructor
    end type

contains

    pure integer function get_ndim(self)
        !! Returns dimension of variable
        class(diagnostic_variable_t), intent(in) :: self
        !! Instance of the type
        get_ndim = self%ndim
    end function

    subroutine init_diagnostic_variable(self, ndim, dimname, varname)
        !! Writes variable to netcdf file
        class(diagnostic_variable_t), intent(inout) :: self
        !! Instance of the type
        integer, intent(in) :: ndim
        !! Dimension of diagnostic variable
        character(len=*), intent(in) :: dimname
        !! Name of dimension of diagnostic variable
        character(len=*), intent(in) :: varname
        !! Name of diagnostic variable

        self%ndim = ndim
        self%dimname = dimname
        self%varname = varname

        if (.not. allocated(self%vals)) then
            allocate(self%vals(self%ndim))
        else
            call handle_error('Already allocated', &
                              GRILLIX_ERR_ALLOC, __LINE__, __FILE__)
        endif
    end subroutine

    subroutine write_netcdf_diagnostic_variable(self, fid, n_diag)
        !! Writes variable to netcdf file
        class(diagnostic_variable_t), intent(in) :: self
        !! Instance of the type
        integer, intent(in) :: fid
        !! NetCDF file id
        integer, intent(in) :: n_diag
        !! Diagnostic snapshot index

        integer :: nf90_stat, id_dim_points, id_dim_n_diag, id_variable

        ! Set diagnostic snapshot dimension
        nf90_stat = nf90_inq_dimid(fid, 'n_diag', id_dim_n_diag)
        if (nf90_stat /= 0) then
            nf90_stat = nf90_def_dim(fid, 'n_diag', nf90_unlimited, &
                                     id_dim_n_diag)
            call handle_error_netcdf(nf90_stat, __LINE__, __FILE__)
        endif

        ! Set variable-specific points dimension
        nf90_stat = nf90_inq_dimid(fid, self%dimname, id_dim_points)
        if (nf90_stat /= 0) then
            nf90_stat = nf90_def_dim(fid, self%dimname, self%ndim, &
                                     id_dim_points)
            call handle_error_netcdf(nf90_stat, __LINE__, __FILE__)
        endif

        ! Define variable
        nf90_stat = nf90_inq_varid(fid, self%varname, id_variable)
        if (nf90_stat /= 0) then
            nf90_stat = nf90_def_var(fid, self%varname, NF90_DOUBLE, &
                                     [id_dim_points, id_dim_n_diag], &
                                     id_variable)
            call handle_error_netcdf(nf90_stat, __LINE__, __FILE__)
        endif

        nf90_stat = nf90_enddef(fid)
        call handle_error_netcdf(nf90_stat, __LINE__, __FILE__)

        ! Store variable
        nf90_stat = nf90_put_var(fid, id_variable, self%vals, [1, n_diag])
        call handle_error_netcdf(nf90_stat, __LINE__, __FILE__)

        ! Reset file to define mode
        nf90_stat = nf90_redef(fid)
        call handle_error_netcdf(nf90_stat, __LINE__, __FILE__)

    end subroutine

    subroutine destructor(self)
        !! Frees memory associated with variable
        type(diagnostic_variable_t), intent(inout) :: self
        !! Instance of the type

        self%ndim = 0
        if (allocated(self%vals)) deallocate(self%vals)
        if (allocated(self%varname)) deallocate(self%varname)
        if (allocated(self%dimname)) deallocate(self%dimname)
    end subroutine

end module