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