diff --git a/src/main/cx_netcdf4_mod.f90 b/src/main/cx_netcdf4_mod.f90 index 50302286eeadda3631627c3266239ff2fc53c978..d06efdd8500bf873361616bc02986ffa75026f8a 100644 --- a/src/main/cx_netcdf4_mod.f90 +++ b/src/main/cx_netcdf4_mod.f90 @@ -38,7 +38,13 @@ module CX_NETCDF4_MOD , NF90_BYTE & , NF90_SHORT & , NF90_FLOAT & - , NF90_DOUBLE + , NF90_DOUBLE, & + NF90_UBYTE, & + NF90_USHORT, & + NF90_INT, & + NF90_UINT, & + NF90_INT64 + use LEVEL2_STRUCTURES_MOD, only: Sds_Struct, L2_Glob_Attr_Definition, Clavrx_Global_Attr @@ -692,34 +698,45 @@ module CX_NETCDF4_MOD end subroutine read_and_unscale_netcdf_1d ! ---------------------------------------------------------- - ! Read and Unscale 2D arrays Two-Byte Integers + ! Read and Unscale 2D arrays ! ---------------------------------------------------------- - subroutine read_and_unscale_netcdf_2d (nc_file_id, var_start, var_stride, & - var_dim, var_name, var_output_unscaled) + subroutine read_and_unscale_netcdf_2d(nc_file_id, var_start, var_stride, & + var_dim, var_name, var_output) - use univ_kind_defs_mod, only: i1, i2, i4 + use univ_kind_defs_mod, only: i1, i2, i4, i8, f4, f8 + use univ_fp_comparison_mod, only: operator(.NEfp.) + + !!! NOTE: This routine casts all types of variable to a 4-byte + !!! floating-point output array. + !!! *** Depending on the values of the variable, this behavior could + !!! result in overflows and/or loss of precision for native + !!! 4-byte integer and 8-byte (integer and floating-point) data. integer, intent(in) :: nc_file_id integer, dimension(2), intent(in) :: var_start integer, dimension(2), intent(in) :: var_stride integer, dimension(2), intent(in) :: var_dim character(len=*), intent(in) :: var_name + real(f4), dimension(:,:), intent(OUT) :: var_output -! integer(kind=i4), dimension(var_dim(1),var_dim(2)) :: var_output_scaled - - integer(kind=i1), dimension(:,:), allocatable :: var_output_scaled_i1 - integer(kind=i2), dimension(:,:), allocatable :: var_output_scaled_i2 - integer(kind=4), dimension(:,:), allocatable :: var_output_scaled_r4 - integer(kind=8), dimension(:,:), allocatable :: var_output_scaled_r8 + integer(i1), dimension(:,:), allocatable :: var_raw_i1 + integer(i2), dimension(:,:), allocatable :: var_raw_i2 + integer(i4), dimension(:,:), allocatable :: var_raw_i4 + integer(i8), dimension(:,:), allocatable :: var_raw_i8 + real(f4), dimension(:,:), allocatable :: var_raw_f4 + real(f8), dimension(:,:), allocatable :: var_raw_f8 - real(kind=4) , intent(out), dimension(:,:) :: var_output_unscaled - real(kind=4) , dimension(var_dim(1),var_dim(2)) :: var_output_unscaled_temp - real(kind=4):: add_offset, scale_factor + real(f4), dimension(var_dim(1),var_dim(2)) :: var_output_temp - integer(kind=2):: Fill_Value + integer(i1) :: scale_fac_i1, offset_i1, fill_val_i1 + integer(i2) :: scale_fac_i2, offset_i2, fill_val_i2 + integer(i4) :: scale_fac_i4, offset_i4, fill_val_i4 + integer(i8) :: scale_fac_i8, offset_i8, fill_val_i8 + real(f4) :: scale_fac_f4, offset_f4, fill_val_f4 + real(f8) :: scale_fac_f8, offset_f8, fill_val_f8 - integer :: nc_var_id, xtype - integer :: status + integer :: nc_var_id, v_type, sf_type, of_type, status + logical :: var_is_scaled, var_is_offset status = nf90_inq_varid(nc_file_id, trim(var_name), nc_var_id) if (status /= nf90_noerr) then @@ -727,68 +744,183 @@ module CX_NETCDF4_MOD return endif - status = nf90_inquire_variable(nc_file_id, nc_var_id, xtype=xtype) + status = nf90_inquire_variable(nc_file_id, nc_var_id, xtype=v_type) if (status /= nf90_noerr) then - print *, "Unable to determine variable type", trim(var_name) + print *, "Unable to determine variable datatype", trim(var_name) STOP 51 endif - - !if (xtype .eq. NF90_FLOAT) then - ! print *, xtype, NF90_FLOAT - ! print *, "TypeError: Do not use READ_AND_UNSCALE() on float variable: ", trim(var_name) - ! STOP 52 - !else if(xtype .eq. NF90_DOUBLE) then - ! print *, "TypeError: Do not use READ_AND_UNSCALE() on double variable: ", trim(var_name) - ! STOP 52 - !endif - - status = nf90_get_att(nc_file_id, nc_var_id, "add_offset", add_offset) - if (status /= 0) add_offset = 0.0 - status = nf90_get_att(nc_file_id, nc_var_id, "scale_factor", scale_factor) - if (status /= 0) scale_factor = 1.0 + ! Retrieve "scale_factor" attribute value, if it exists: + status = nf90_inquire_attribute(nc_file_id, nc_var_id, 'scale_factor', & + xtype=sf_type) + var_is_scaled = ( status == nf90_noerr ) + if (var_is_scaled) then + select case (sf_type) + case (NF90_BYTE) + status = nf90_get_att(nc_file_id, nc_var_id, 'scale_factor', & + scale_fac_i1) + case (NF90_UBYTE) + status = nf90_get_att(nc_file_id, nc_var_id, 'scale_factor', & + scale_fac_i2) + case (NF90_SHORT) + status = nf90_get_att(nc_file_id, nc_var_id, 'scale_factor', & + scale_fac_i2) + case (NF90_USHORT) + status = nf90_get_att(nc_file_id, nc_var_id, 'scale_factor', & + scale_fac_i4) + case (NF90_INT) + status = nf90_get_att(nc_file_id, nc_var_id, 'scale_factor', & + scale_fac_i4) + case (NF90_UINT) + status = nf90_get_att(nc_file_id, nc_var_id, 'scale_factor', & + scale_fac_i8) + case (NF90_INT64) + status = nf90_get_att(nc_file_id, nc_var_id, 'scale_factor', & + scale_fac_i8) + case (NF90_FLOAT) + status = nf90_get_att(nc_file_id, nc_var_id, 'scale_factor', & + scale_fac_f4) + case (NF90_DOUBLE) + status = nf90_get_att(nc_file_id, nc_var_id, 'scale_factor', & + scale_fac_f8) + end select + end if - status = nf90_get_att(nc_file_id, nc_var_id, "_FillValue", fill_value) - if (status /= 0) fill_value = -999.0 + ! Retrieve "add_offset" attribute value, if it exists: + status = nf90_inquire_attribute(nc_file_id, nc_var_id, 'add_offset', & + xtype=of_type) + var_is_offset = ( status == nf90_noerr ) + if (status == nf90_noerr) then + select case (of_type) + case (NF90_BYTE) + status = nf90_get_att(nc_file_id, nc_var_id, 'add_offset', & + offset_i1) + case (NF90_UBYTE) + status = nf90_get_att(nc_file_id, nc_var_id, 'add_offset', & + offset_i2) + case (NF90_SHORT) + status = nf90_get_att(nc_file_id, nc_var_id, 'add_offset', & + offset_i2) + case (NF90_USHORT) + status = nf90_get_att(nc_file_id, nc_var_id, 'add_offset', & + offset_i4) + case (NF90_INT) + status = nf90_get_att(nc_file_id, nc_var_id, 'add_offset', & + offset_i4) + case (NF90_UINT) + status = nf90_get_att(nc_file_id, nc_var_id, 'add_offset', & + offset_i8) + case (NF90_INT64) + status = nf90_get_att(nc_file_id, nc_var_id, 'add_offset', & + offset_i8) + case (NF90_FLOAT) + status = nf90_get_att(nc_file_id, nc_var_id, 'add_offset', & + offset_f4) + case (NF90_DOUBLE) + status = nf90_get_att(nc_file_id, nc_var_id, 'add_offset', & + offset_f8) + end select + end if - !get Variable - select case (xtype) - case (NF90_BYTE) - allocate(var_output_scaled_i1(var_dim(1),var_dim(2))) - status = nf90_get_var(nc_file_id, nc_var_id, var_output_scaled_i1, start=var_start, & - count=var_dim, stride=var_stride) - case (NF90_SHORT) - allocate(var_output_scaled_i2(var_dim(1),var_dim(2))) - status = nf90_get_var(nc_file_id, nc_var_id, var_output_scaled_i2, start=var_start, & - count=var_dim, stride=var_stride) - case (NF90_FLOAT) - allocate(var_output_scaled_r4(var_dim(1),var_dim(2))) - status = nf90_get_var(nc_file_id, nc_var_id, var_output_scaled_r4, start=var_start, & - count=var_dim, stride=var_stride) - case (NF90_DOUBLE) - allocate(var_output_scaled_r8(var_dim(1),var_dim(2))) - status = nf90_get_var(nc_file_id, nc_var_id, var_output_scaled_r8, start=var_start, & - count=var_dim, stride=var_stride) + ! Retrieve "_FillValue" attribute value, if it exists (set to a default + ! value if it does not): + select case (v_type) + case (NF90_BYTE) + status = nf90_get_att(nc_file_id, nc_var_id, '_FillValue', & + fill_val_i1) + if (status /= nf90_noerr) fill_val_i1 = -99_i1 + case (NF90_UBYTE) + status = nf90_get_att(nc_file_id, nc_var_id, '_FillValue', & + fill_val_i2) + if (status /= nf90_noerr) fill_val_i2 = -999_i2 + case (NF90_SHORT) + status = nf90_get_att(nc_file_id, nc_var_id, '_FillValue', & + fill_val_i2) + if (status /= nf90_noerr) fill_val_i2 = -999_i2 + case (NF90_USHORT) + status = nf90_get_att(nc_file_id, nc_var_id, '_FillValue', & + fill_val_i4) + if (status /= nf90_noerr) fill_val_i4 = -999_i4 + case (NF90_INT) + status = nf90_get_att(nc_file_id, nc_var_id, '_FillValue', & + fill_val_i4) + if (status /= nf90_noerr) fill_val_i4 = -999_i4 + case (NF90_UINT) + status = nf90_get_att(nc_file_id, nc_var_id, '_FillValue', & + fill_val_i8) + if (status /= nf90_noerr) fill_val_i8 = -999_i8 + case (NF90_INT64) + status = nf90_get_att(nc_file_id, nc_var_id, '_FillValue', & + fill_val_i8) + if (status /= nf90_noerr) fill_val_i8 = -999_i8 + case (NF90_FLOAT) + status = nf90_get_att(nc_file_id, nc_var_id, '_FillValue', & + fill_val_f4) + if (status /= nf90_noerr) fill_val_f4 = -999._f4 + case (NF90_DOUBLE) + status = nf90_get_att(nc_file_id, nc_var_id, '_FillValue', & + fill_val_f8) + if (status /= nf90_noerr) fill_val_f8 = -999._f8 + end select + + ! Retrieve values from the variable: + select case (v_type) + case (NF90_BYTE) + allocate(var_raw_i1(var_dim(1),var_dim(2))) + status = nf90_get_var(nc_file_id, nc_var_id, var_raw_i1, & + start=var_start, count=var_dim, stride=var_stride) + case (NF90_UBYTE) + allocate(var_raw_i2(var_dim(1),var_dim(2))) + status = nf90_get_var(nc_file_id, nc_var_id, var_raw_i2, & + start=var_start, count=var_dim, stride=var_stride) + case (NF90_SHORT) + allocate(var_raw_i2(var_dim(1),var_dim(2))) + status = nf90_get_var(nc_file_id, nc_var_id, var_raw_i2, & + start=var_start, count=var_dim, stride=var_stride) + case (NF90_USHORT) + allocate(var_raw_i4(var_dim(1),var_dim(2))) + status = nf90_get_var(nc_file_id, nc_var_id, var_raw_i4, & + start=var_start, count=var_dim, stride=var_stride) + case (NF90_INT) + allocate(var_raw_i4(var_dim(1),var_dim(2))) + status = nf90_get_var(nc_file_id, nc_var_id, var_raw_i4, & + start=var_start, count=var_dim, stride=var_stride) + case (NF90_UINT) + allocate(var_raw_i8(var_dim(1),var_dim(2))) + status = nf90_get_var(nc_file_id, nc_var_id, var_raw_i8, & + start=var_start, count=var_dim, stride=var_stride) + case (NF90_INT64) + allocate(var_raw_i8(var_dim(1),var_dim(2))) + status = nf90_get_var(nc_file_id, nc_var_id, var_raw_i8, & + start=var_start, count=var_dim, stride=var_stride) + case (NF90_FLOAT) + allocate(var_raw_f4(var_dim(1),var_dim(2))) + status = nf90_get_var(nc_file_id, nc_var_id, var_raw_f4, & + start=var_start, count=var_dim, stride=var_stride) + case (NF90_DOUBLE) + allocate(var_raw_f8(var_dim(1),var_dim(2))) + status = nf90_get_var(nc_file_id, nc_var_id, var_raw_f8, & + start=var_start, count=var_dim, stride=var_stride) end select - !status = nf90_get_var(nc_file_id, nc_var_id, var_output_scaled, start=var_start, & - ! count=var_dim, stride=var_stride) - if ((status /= nf90_noerr)) then print *,'Error: ', trim(nf90_strerror(status)),' ', trim(var_name) print *, "in read_and_unscale_netcdf_2d" print *, "var name = ", trim(var_name) + print *, 'var_type = ', v_type print *, "var start = ", var_start print *, "var count = ", var_dim print *, "var stride = ", var_stride print *, "varname = ",trim(var_name) print *, "shape var_output_scaled = ", var_dim(1), var_dim(2) - if (allocated(var_output_scaled_i1)) deallocate(var_output_scaled_i1) - if (allocated(var_output_scaled_i2)) deallocate(var_output_scaled_i2) - if (allocated(var_output_scaled_r4)) deallocate(var_output_scaled_r4) - if (allocated(var_output_scaled_r8)) deallocate(var_output_scaled_r8) + if (allocated(var_raw_i1)) deallocate(var_raw_i1) + if (allocated(var_raw_i2)) deallocate(var_raw_i2) + if (allocated(var_raw_i4)) deallocate(var_raw_i4) + if (allocated(var_raw_i8)) deallocate(var_raw_i8) + if (allocated(var_raw_f4)) deallocate(var_raw_f4) + if (allocated(var_raw_f8)) deallocate(var_raw_f8) stop - return +! return endif !--- unscale @@ -797,43 +929,252 @@ module CX_NETCDF4_MOD !elsewhere ! var_output_unscaled_temp = Missing_Value_Netcdf !endwhere - - select case (xtype) - case (NF90_BYTE) - where(var_output_scaled_i1 /= fill_value) - var_output_unscaled_temp = add_offset + scale_factor * var_output_scaled_i1 - elsewhere - var_output_unscaled_temp = Missing_Value_Netcdf - endwhere - case (NF90_SHORT) - where(var_output_scaled_i2 /= fill_value) - var_output_unscaled_temp = add_offset + scale_factor * var_output_scaled_i2 - elsewhere - var_output_unscaled_temp = Missing_Value_Netcdf - endwhere - case (NF90_FLOAT) - where(var_output_scaled_r4 /= fill_value) - var_output_unscaled_temp = add_offset + scale_factor * var_output_scaled_r4 - elsewhere - var_output_unscaled_temp = Missing_Value_Netcdf - endwhere - case (NF90_DOUBLE) - where(var_output_scaled_r8 /= fill_value) - var_output_unscaled_temp = add_offset + scale_factor * var_output_scaled_r8 - elsewhere - var_output_unscaled_temp = Missing_Value_Netcdf - endwhere - end select - - var_output_unscaled = Missing_Value_Netcdf - var_output_unscaled(1:var_dim(1),1:var_dim(2)) = var_output_unscaled_temp - - !--- deallocate - if (allocated(var_output_scaled_i1)) deallocate(var_output_scaled_i1) - if (allocated(var_output_scaled_i2)) deallocate(var_output_scaled_i2) - if (allocated(var_output_scaled_r4)) deallocate(var_output_scaled_r4) - if (allocated(var_output_scaled_r8)) deallocate(var_output_scaled_r8) - + + if (var_is_scaled .and. var_is_offset) then + select case (v_type) + case (NF90_BYTE) + where (var_raw_i1 /= fill_val_i1) + var_output_temp = offset_i1+scale_fac_i1*var_raw_i1 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_UBYTE) + where (var_raw_i2 /= fill_val_i2) + var_output_temp = offset_i2+scale_fac_i2*var_raw_i2 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_SHORT) + where (var_raw_i2 /= fill_val_i2) + var_output_temp = offset_i2+scale_fac_i2*var_raw_i2 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_USHORT) + where (var_raw_i4 /= fill_val_i4) + var_output_temp = offset_i4+scale_fac_i4*var_raw_i4 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_INT) + where (var_raw_i4 /= fill_val_i4) + var_output_temp = offset_i4+scale_fac_i4*var_raw_i4 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_UINT) + where (var_raw_i8 /= fill_val_i8) + var_output_temp = offset_i8+scale_fac_i8*var_raw_i8 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_INT64) + where (var_raw_i8 /= fill_val_i8) + var_output_temp = offset_i8+scale_fac_i8*var_raw_i8 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_FLOAT) + where (var_raw_f4 .NEfp. fill_val_f4) + var_output_temp = offset_f4+scale_fac_f4*var_raw_f4 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_DOUBLE) + where (var_raw_f8 .NEfp. fill_val_f8) + var_output_temp = offset_f8+scale_fac_f8*var_raw_f8 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + end select + + else if ((.not.var_is_scaled) .and. (.not.var_is_offset)) then + select case (v_type) + case (NF90_BYTE) + where (var_raw_i1 /= fill_val_i1) + var_output_temp = var_raw_i1 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_UBYTE) + where (var_raw_i2 /= fill_val_i2) + var_output_temp = var_raw_i2 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_SHORT) + where (var_raw_i2 /= fill_val_i2) + var_output_temp = var_raw_i2 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_USHORT) + where (var_raw_i4 /= fill_val_i4) + var_output_temp = var_raw_i4 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_INT) + where (var_raw_i4 /= fill_val_i4) + var_output_temp = var_raw_i4 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_UINT) + where (var_raw_i8 /= fill_val_i8) + var_output_temp = var_raw_i8 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_INT64) + where (var_raw_i8 /= fill_val_i8) + var_output_temp = var_raw_i8 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_FLOAT) + where (var_raw_f4 .NEfp. fill_val_f4) + var_output_temp = var_raw_f4 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_DOUBLE) + where (var_raw_f8 .NEfp. fill_val_f8) + var_output_temp = var_raw_f8 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + end select + + else if (var_is_scaled .and. (.not.var_is_offset)) then + select case (v_type) + case (NF90_BYTE) + where (var_raw_i1 /= fill_val_i1) + var_output_temp = scale_fac_i1*var_raw_i1 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_UBYTE) + where (var_raw_i2 /= fill_val_i2) + var_output_temp = scale_fac_i2*var_raw_i2 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_SHORT) + where (var_raw_i2 /= fill_val_i2) + var_output_temp = scale_fac_i2*var_raw_i2 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_USHORT) + where (var_raw_i4 /= fill_val_i4) + var_output_temp = scale_fac_i4*var_raw_i4 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_INT) + where (var_raw_i4 /= fill_val_i4) + var_output_temp = scale_fac_i4*var_raw_i4 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_UINT) + where (var_raw_i8 /= fill_val_i8) + var_output_temp = scale_fac_i8*var_raw_i8 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_INT64) + where (var_raw_i8 /= fill_val_i8) + var_output_temp = scale_fac_i8*var_raw_i8 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_FLOAT) + where (var_raw_f4 .NEfp. fill_val_f4) + var_output_temp = scale_fac_f4*var_raw_f4 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_DOUBLE) + where (var_raw_f8 .NEfp. fill_val_f8) + var_output_temp = scale_fac_f8*var_raw_f8 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + end select + + else if ((.not.var_is_scaled) .and. var_is_offset) then + select case (v_type) + case (NF90_BYTE) + where (var_raw_i1 /= fill_val_i1) + var_output_temp = offset_i1+var_raw_i1 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_UBYTE) + where (var_raw_i2 /= fill_val_i2) + var_output_temp = offset_i2+var_raw_i2 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_SHORT) + where (var_raw_i2 /= fill_val_i2) + var_output_temp = offset_i2+var_raw_i2 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_USHORT) + where (var_raw_i4 /= fill_val_i4) + var_output_temp = offset_i4+var_raw_i4 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_INT) + where (var_raw_i4 /= fill_val_i4) + var_output_temp = offset_i4+var_raw_i4 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_UINT) + where (var_raw_i8 /= fill_val_i8) + var_output_temp = offset_i8+var_raw_i8 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_INT64) + where (var_raw_i8 /= fill_val_i8) + var_output_temp = offset_i8+var_raw_i8 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_FLOAT) + where (var_raw_f4 .NEfp. fill_val_f4) + var_output_temp = offset_f4+var_raw_f4 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + case (NF90_DOUBLE) + where (var_raw_f8 .NEfp. fill_val_f8) + var_output_temp = offset_f8+var_raw_f8 + elsewhere + var_output_temp = Missing_Value_Netcdf + end where + end select + + end if + + var_output = Missing_Value_Netcdf + var_output(1:var_dim(1),1:var_dim(2)) = var_output_temp + + ! Deallocate any detritus: + if (allocated(var_raw_i1)) deallocate(var_raw_i1) + if (allocated(var_raw_i2)) deallocate(var_raw_i2) + if (allocated(var_raw_i4)) deallocate(var_raw_i4) + if (allocated(var_raw_i8)) deallocate(var_raw_i8) + if (allocated(var_raw_f4)) deallocate(var_raw_f4) + if (allocated(var_raw_f8)) deallocate(var_raw_f8) + end subroutine read_and_unscale_netcdf_2d ! ----------------------------------------------------------