<commit_before>!>------------------------------------------------------------
!!  Model Output
!!
!!  Writes all model data to a (mostly?) CF compliant netcdf file. 
!!  Eventually this should be updated to work with generic data structures rather
!!  than specifying / hard codeing every possible variable name and attribute. 
!!
!!  @author
!!  <NAME> (<EMAIL>)
!!
!!------------------------------------------------------------
module output
    use netcdf        ! nc_* routines
    use time          ! calendar_date, calendar, YEAR_ZERO, GREGORIAN, NOLEAP, THREESIXTY
    use string        ! str
    use io_routines   ! io_* routines, file_exists, check
    use data_structures
    implicit none
    private
    public :: write_domain
    
    integer, parameter :: ndims = 4     !> number of dimensions in output (x,y,z,t)
    integer, parameter :: nvars = 37    !> current number of vars = 37
    !> This will be the netCDF ID for the file and data variable.
    integer :: ncid, temp_id
    !> dimension IDs
    integer :: t_id, x_id, y_id, xu_id, yv_id, soil_id
    !> arrays to store dims for a given variable
    integer :: dimids(ndims)
    integer :: dimtwo(2)
    integer :: dimtwo_time(3)
    !> variable IDs
    integer :: lat_id,lon_id,time_id
    !> array to store ALL var ids
    integer :: varid(nvars)
    
    !> the number of time steps to save in each file
    integer, parameter :: time_steps_per_file = 24
    integer, parameter :: EVERY_STEP = 0
    integer, parameter :: MONTHLY_FREQUENCY = 2
    integer, parameter :: DAILY_FREQUENCY = 1
    integer :: output_frequency = DAILY_FREQUENCY
    integer :: current_step
    character(len=255) :: filename = "default_output.nc"
    
    integer :: start_three_D(4) = [1,1,1,1]
    integer :: start_two_D(3)  = [1,1,1]
    integer :: start_scalar(1) = [1]

    real, allocatable, dimension(:,:) :: last_rain
    logical :: surface_io_only
    ! We are writing 3D data, a (ny x nz x nx) grid or (ny x nsoil x nx) grid
    integer :: nx,ny,nz,i,nsoil
    
contains
    
    !>------------------------------------------------------------
    !! Keeps accumulated precip variables in reasonable bounds with a "bucket"
    !!
    !! Check if precip variables have exceeded kPRECIP_BUCKET_SIZE and if so, "tip" into the bucket
    !! i.e. add one to the bucket and subtract kPRECIP_BUCKET_SIZE from the precip variable
    !! and repeat while precip variable > kPRECIP_BUCKET_SIZE
    !!
    !! @param domain only: rain, crain, snow, graupel and their respective buckets
    !!
    !!------------------------------------------------------------
    subroutine tip_precip_to_buckets(domain)
        implicit none
        type(domain_type), intent(inout) :: domain
        
        ! loop variables
        integer :: nx, ny, i, j
        
        nx=size(domain%rain,1)
        ny=size(domain%rain,2)
        ! 2 to n-2 so we don't process the edges 
        do j=2,ny-2
            do i=2,nx-1
                if (domain%rain(i,j)>kPRECIP_BUCKET_SIZE) then
                    do while (domain%rain(i,j)>kPRECIP_BUCKET_SIZE)
                        domain%rain(i,j) = domain%rain(i,j)-kPRECIP_BUCKET_SIZE
                        domain%rain_bucket(i,j) = domain%rain_bucket(i,j)+1
                        last_rain(i,j)=last_rain(i,j)-kPRECIP_BUCKET_SIZE
                    end do
                endif
                if (domain%crain(i,j)>kPRECIP_BUCKET_SIZE) then
                    do while (domain%crain(i,j)>kPRECIP_BUCKET_SIZE)
                        domain%crain(i,j) = domain%crain(i,j)-kPRECIP_BUCKET_SIZE
                        domain%crain_bucket(i,j) = domain%crain_bucket(i,j)+1
                    end do
                endif
                if (domain%snow(i,j)>kPRECIP_BUCKET_SIZE) then
                    do while (domain%snow(i,j)>kPRECIP_BUCKET_SIZE)
                        domain%snow(i,j) = domain%snow(i,j)-kPRECIP_BUCKET_SIZE
                        domain%snow_bucket(i,j) = domain%snow_bucket(i,j)+1
                    end do
                endif
                if (domain%graupel(i,j)>kPRECIP_BUCKET_SIZE) then
                    do while (domain%graupel(i,j)>kPRECIP_BUCKET_SIZE)
                        domain%graupel(i,j) = domain%graupel(i,j)-kPRECIP_BUCKET_SIZE
                        domain%graupel_bucket(i,j) = domain%graupel_bucket(i,j)+1
                    end do
                endif
            end do
        end do
    end subroutine tip_precip_to_buckets
    
    !>------------------------------------------------------------
    !! Creates a new NetCDF output file
    !!
    !! Creates a new file including all variables, dimensions, and attributes
    !!
    !! @param filename  name of NetCDF output file to be created
    !! @param options   model wide options so the correct output can be created 
    !!
    !!------------------------------------------------------------
    subroutine create_file(filename,options)
        character(len=255), intent(in) :: filename
        type(options_type), intent(in) :: options
        
        ! store real (not model) timestamp
        character(len=19) :: todays_date_time
        integer,dimension(8) :: date_time
        character(len=49) :: date_format
        character(len=5) :: UTCoffset
        character(len=MAXFILELENGTH) :: err
        
        
        call date_and_time(values=date_time,zone=UTCoffset)
        date_format='(I4,"/",I2.2,"/",I2.2," ",I2.2,":",I2.2,":",I2.2)'
        write(todays_date_time,date_format) date_time(1:3),date_time(5:7)
    
        ! create the file (clobbering any existing files!)
        err="Creating:"//trim(filename)
        call check( nf90_create(filename, NF90_CLOBBER, ncid), trim(err))
        
        err="Creating global attributes"
        call check( nf90_put_att(ncid,NF90_GLOBAL,"Conventions","CF-1.6"), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"title","Intermediate Complexity Atmospheric Research Model output"), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"institution","National Center for Atmospheric Research"), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"source","Intermediate Complexity Atmospheric Model version:"//trim(options%version)), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"history","Created:"//todays_date_time//UTCoffset), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"references", &
                    "Gutmann et al. 2016: The Intermediate Complexity Atmospheric Model. JHM (in revision)"), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"comment",trim(options%comment)), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"contact","<NAME> : <EMAIL>"), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"git",VERSION), trim(err))

        call check( nf90_put_att(ncid,NF90_GLOBAL,"bucket_size",kPRECIP_BUCKET_SIZE), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"dx",options%dx), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"wind_smoothing",options%smooth_wind_distance), trim(err))
        
        ! only output linear wind parameters if ICAR is using the linear wind calculations
        if (options%physics%windtype>0) then
            call check( nf90_put_att(ncid,NF90_GLOBAL,"vert_smooth",options%vert_smooth), trim(err))
            call check( nf90_put_att(ncid,NF90_GLOBAL,"linear_contribution",options%lt_options%linear_contribution), trim(err))
            if (options%lt_options%variable_N) then
                call check( nf90_put_att(ncid,NF90_GLOBAL,"variable_N","time varying N"), trim(err))
            else
                call check( nf90_put_att(ncid,NF90_GLOBAL,"fixed_N",options%lt_options%N_squared), trim(err))
            endif
            if (options%lt_options%remove_lowres_linear) then
                if (.not.options%lt_options%variable_N) then
                    call check( nf90_put_att(ncid,NF90_GLOBAL,"rm_lin_frac_fixed_N",options%lt_options%rm_N_squared), trim(err))
                endif
                call check( nf90_put_att(ncid,NF90_GLOBAL,"remove_lin_fraction",options%lt_options%rm_linear_contribution), trim(err))
            endif
            if (options%lt_options%spatial_linear_fields) then
                call check( nf90_put_att(ncid,NF90_GLOBAL,"spatially_variable_N","spatially varying N"), trim(err))
            endif
        endif
        ! general physics options
        call check( nf90_put_att(ncid,NF90_GLOBAL,"microphysics",options%physics%microphysics), trim(err))<commit_msg>updated reference in output files to include DOI<commit_after>!>------------------------------------------------------------
!!  Model Output
!!
!!  Writes all model data to a (mostly?) CF compliant netcdf file. 
!!  Eventually this should be updated to work with generic data structures rather
!!  than specifying / hard codeing every possible variable name and attribute. 
!!
!!  @author
!!  <NAME> (<EMAIL>)
!!
!!------------------------------------------------------------
module output
    use netcdf        ! nc_* routines
    use time          ! calendar_date, calendar, YEAR_ZERO, GREGORIAN, NOLEAP, THREESIXTY
    use string        ! str
    use io_routines   ! io_* routines, file_exists, check
    use data_structures
    implicit none
    private
    public :: write_domain
    
    integer, parameter :: ndims = 4     !> number of dimensions in output (x,y,z,t)
    integer, parameter :: nvars = 37    !> current number of vars = 37
    !> This will be the netCDF ID for the file and data variable.
    integer :: ncid, temp_id
    !> dimension IDs
    integer :: t_id, x_id, y_id, xu_id, yv_id, soil_id
    !> arrays to store dims for a given variable
    integer :: dimids(ndims)
    integer :: dimtwo(2)
    integer :: dimtwo_time(3)
    !> variable IDs
    integer :: lat_id,lon_id,time_id
    !> array to store ALL var ids
    integer :: varid(nvars)
    
    !> the number of time steps to save in each file
    integer, parameter :: time_steps_per_file = 24
    integer, parameter :: EVERY_STEP = 0
    integer, parameter :: MONTHLY_FREQUENCY = 2
    integer, parameter :: DAILY_FREQUENCY = 1
    integer :: output_frequency = DAILY_FREQUENCY
    integer :: current_step
    character(len=255) :: filename = "default_output.nc"
    
    integer :: start_three_D(4) = [1,1,1,1]
    integer :: start_two_D(3)  = [1,1,1]
    integer :: start_scalar(1) = [1]

    real, allocatable, dimension(:,:) :: last_rain
    logical :: surface_io_only
    ! We are writing 3D data, a (ny x nz x nx) grid or (ny x nsoil x nx) grid
    integer :: nx,ny,nz,i,nsoil
    
contains
    
    !>------------------------------------------------------------
    !! Keeps accumulated precip variables in reasonable bounds with a "bucket"
    !!
    !! Check if precip variables have exceeded kPRECIP_BUCKET_SIZE and if so, "tip" into the bucket
    !! i.e. add one to the bucket and subtract kPRECIP_BUCKET_SIZE from the precip variable
    !! and repeat while precip variable > kPRECIP_BUCKET_SIZE
    !!
    !! @param domain only: rain, crain, snow, graupel and their respective buckets
    !!
    !!------------------------------------------------------------
    subroutine tip_precip_to_buckets(domain)
        implicit none
        type(domain_type), intent(inout) :: domain
        
        ! loop variables
        integer :: nx, ny, i, j
        
        nx=size(domain%rain,1)
        ny=size(domain%rain,2)
        ! 2 to n-2 so we don't process the edges 
        do j=2,ny-2
            do i=2,nx-1
                if (domain%rain(i,j)>kPRECIP_BUCKET_SIZE) then
                    do while (domain%rain(i,j)>kPRECIP_BUCKET_SIZE)
                        domain%rain(i,j) = domain%rain(i,j)-kPRECIP_BUCKET_SIZE
                        domain%rain_bucket(i,j) = domain%rain_bucket(i,j)+1
                        last_rain(i,j)=last_rain(i,j)-kPRECIP_BUCKET_SIZE
                    end do
                endif
                if (domain%crain(i,j)>kPRECIP_BUCKET_SIZE) then
                    do while (domain%crain(i,j)>kPRECIP_BUCKET_SIZE)
                        domain%crain(i,j) = domain%crain(i,j)-kPRECIP_BUCKET_SIZE
                        domain%crain_bucket(i,j) = domain%crain_bucket(i,j)+1
                    end do
                endif
                if (domain%snow(i,j)>kPRECIP_BUCKET_SIZE) then
                    do while (domain%snow(i,j)>kPRECIP_BUCKET_SIZE)
                        domain%snow(i,j) = domain%snow(i,j)-kPRECIP_BUCKET_SIZE
                        domain%snow_bucket(i,j) = domain%snow_bucket(i,j)+1
                    end do
                endif
                if (domain%graupel(i,j)>kPRECIP_BUCKET_SIZE) then
                    do while (domain%graupel(i,j)>kPRECIP_BUCKET_SIZE)
                        domain%graupel(i,j) = domain%graupel(i,j)-kPRECIP_BUCKET_SIZE
                        domain%graupel_bucket(i,j) = domain%graupel_bucket(i,j)+1
                    end do
                endif
            end do
        end do
    end subroutine tip_precip_to_buckets
    
    !>------------------------------------------------------------
    !! Creates a new NetCDF output file
    !!
    !! Creates a new file including all variables, dimensions, and attributes
    !!
    !! @param filename  name of NetCDF output file to be created
    !! @param options   model wide options so the correct output can be created 
    !!
    !!------------------------------------------------------------
    subroutine create_file(filename,options)
        character(len=255), intent(in) :: filename
        type(options_type), intent(in) :: options
        
        ! store real (not model) timestamp
        character(len=19) :: todays_date_time
        integer,dimension(8) :: date_time
        character(len=49) :: date_format
        character(len=5) :: UTCoffset
        character(len=MAXFILELENGTH) :: err
        
        
        call date_and_time(values=date_time,zone=UTCoffset)
        date_format='(I4,"/",I2.2,"/",I2.2," ",I2.2,":",I2.2,":",I2.2)'
        write(todays_date_time,date_format) date_time(1:3),date_time(5:7)
    
        ! create the file (clobbering any existing files!)
        err="Creating:"//trim(filename)
        call check( nf90_create(filename, NF90_CLOBBER, ncid), trim(err))
        
        err="Creating global attributes"
        call check( nf90_put_att(ncid,NF90_GLOBAL,"Conventions","CF-1.6"), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"title","Intermediate Complexity Atmospheric Research Model output"), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"institution","National Center for Atmospheric Research"), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"source","Intermediate Complexity Atmospheric Model version:"//trim(options%version)), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"history","Created:"//todays_date_time//UTCoffset), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"references", &
                    "Gutmann et al. 2016: The Intermediate Complexity Atmospheric Model (ICAR). J.Hydrometeor. doi:10.1175/JHM-D-15-0155.1, in press."), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"comment",trim(options%comment)), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"contact","<NAME> : <EMAIL>"), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"git",VERSION), trim(err))

        call check( nf90_put_att(ncid,NF90_GLOBAL,"bucket_size",kPRECIP_BUCKET_SIZE), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"dx",options%dx), trim(err))
        call check( nf90_put_att(ncid,NF90_GLOBAL,"wind_smoothing",options%smooth_wind_distance), trim(err))
        
        ! only output linear wind parameters if ICAR is using the linear wind calculations
        if (options%physics%windtype>0) then
            call check( nf90_put_att(ncid,NF90_GLOBAL,"vert_smooth",options%vert_smooth), trim(err))
            call check( nf90_put_att(ncid,NF90_GLOBAL,"linear_contribution",options%lt_options%linear_contribution), trim(err))
            if (options%lt_options%variable_N) then
                call check( nf90_put_att(ncid,NF90_GLOBAL,"variable_N","time varying N"), trim(err))
            else
                call check( nf90_put_att(ncid,NF90_GLOBAL,"fixed_N",options%lt_options%N_squared), trim(err))
            endif
            if (options%lt_options%remove_lowres_linear) then
                if (.not.options%lt_options%variable_N) then
                    call check( nf90_put_att(ncid,NF90_GLOBAL,"rm_lin_frac_fixed_N",options%lt_options%rm_N_squared), trim(err))
                endif
                call check( nf90_put_att(ncid,NF90_GLOBAL,"remove_lin_fraction",options%lt_options%rm_linear_contribution), trim(err))
            endif
            if (options%lt_options%spatial_linear_fields) then
                call check( nf90_put_att(ncid,NF90_GLOBAL,"spatially_variable_N","spatially varying N"), trim(err))
            endif
        endif
        ! general physics options
        call check( nf90_put_att(ncid,NF90_GLOBAL,"microphysics",options%physics%microphysics), trim(err))
{'fraction_non_alphanumeric': 0.14346359618515933, 'fraction_numerical': 0.018667131891137473, 'mean_word_length': 2.34116961336701, 'pattern_counts': {'":': 4, '<': 11, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1011945', 'n_tokens_mistral': 5643, 'n_tokens_neox': 5376, 'n_words': 1174}