user2030765
user2030765

Reputation: 149

Fortran - Compile Error - Must have explicit type

I am running into the following compiler error, and have been unable to find any information on how to solve the following:

CAM_netcdf_to_WRF_intermediate.f90(382): warning #8236: Deferred character length in a data object or component declaration is an extension of Standard F90.
  character(len=:),allocatable :: lon_netcdf_units(:),lon_netcdf_title(:) &
----------------^
CAM_netcdf_to_WRF_intermediate.f90(470): error #6404: This name does not have a type, and must have an explicit type.   [NF90_GET_ATTRIBUTE]
  STATUS = NF90_GET_ATTRIBUTE(NCID, lon_var_id, 'units', lon_netcdf_units)
-----------^

The program is compiled as:

ifort -c -CB -CU -ftrapuv -par_report0 -vec_report0 -heap-arrays -O0 -stand f90 -check all -traceback -fstack-protector -assume protect_parens -implicitnone -debug -gen-interfaces -check arg_temp_created -ftrapuv -g -traceback -convert big_endian -I/opt/cray/netcdf/4.3.0/INTEL/130/include/ CAM_netcdf_to_WRF_intermediate.f90 ; ifort CAM_netcdf_to_WRF_intermediate.o -L/opt/cray/netcdf/4.3.0/INTEL/130/lib -lnetcdf -lnetcdff

The program:

program CAM_netcdf_to_WRF_intermediate
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  use netcdf
  implicit none

  ! Declarations:
  integer, parameter :: outfile_intermediate = 10
  integer, parameter :: outfile_intermediate_SST = 11
  integer, parameter :: outfile_diagnostics = 16
  integer, parameter :: infile_CAM_files_and_dates = 15
  character(len=24) :: HDATE

  ! dimensions:
  integer, parameter :: nx_CAM=288,ny_CAM=192,nz_CAM=26 &
       ,nfields=5,nfields2d=9,nfields2d_to_read=5 &
       ,nz_soil=4,nz_CLM=1,nfields_soil=2
  integer, parameter :: nz_WRF=38
  character(len=128) :: netcdf_cam_filename,netcdf_clm_filename,netcdf_pop_filename
  character(len=128) :: netcdf_ice_filename
  integer :: iEOF
  logical :: EOF
  ! open outpuf log file:
  open(outfile_diagnostics,form='formatted',file="Output/CCSM2WRF.log")

  ! read the first date and netcdf file name from the input file:
  open(infile_CAM_files_and_dates,form='formatted',file="Input/CCSM2WRF.input")
  read(infile_CAM_files_and_dates,*,iostat=iEOF) netcdf_cam_filename,netcdf_clm_filename,&
                        netcdf_pop_filename,netcdf_ice_filename,hdate
  if (iEOF<0) then;
print *, "EOF True"
     EOF=.true.;
  else;
print *, "EOF False"
     EOF=.false.;
  end if
     call dummy_read(nz_WRF,hdate,outfile_diagnostics,outfile_intermediate &
                    ,outfile_intermediate_SST,netcdf_cam_filename &
                    ,netcdf_clm_filename,netcdf_pop_filename &
                    ,netcdf_ice_filename,nx_CAM,ny_CAM,nz_CAM,nfields,nfields2d)
  stop
end program CAM_netcdf_to_WRF_intermediate

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
SUBROUTINE HANDLE_ERR(STATUS)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  use netcdf
  implicit none
  INTEGER STATUS
!  INCLUDE '/opt/cray/netcdf/4.3.0/INTEL/130/include/netcdf.inc'
  IF (STATUS .NE. NF90_NOERR) THEN
     PRINT *, NF90_STRERROR(STATUS)
     STOP 'Stopped'
  ENDIF
END SUBROUTINE HANDLE_ERR

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Subroutine dummy_read &
     (nz_WRF,hdate,outfile_diagnostics,outfile_intermediate &
     ,outfile_intermediate_SST,netcdf_cam_filename &
     ,netcdf_clm_filename,netcdf_pop_filename &
     ,netcdf_ice_filename,nx_CAM,ny_CAM,nz_CAM,nfields,nfields2d)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!  !DEC$ ATTRIBUTES REFERENCE :: HDATE
  use netcdf
  implicit none
  integer :: nz_WRF
  integer :: nx_CAM,ny_CAM,nz_CAM,nfields,nfields2d
  character(len=128) :: filename
  character(len=24) :: HDATE
  integer :: outfile_diagnostics,outfile_intermediate,outfile_intermediate_SST
  integer :: STATUS, NCID, NCID_clm, NCID_pop, NCID_ice
  character(len=128) :: netcdf_cam_filename, netcdf_clm_filename, netcdf_pop_filename
  character(len=128) :: netcdf_ice_filename
  integer :: lat_var_id,lon_var_id,lev_var_id,time_var_id,nlon_var_id &
            ! 3d fields
            ,T_var_id,RH_var_id,U_var_id,V_var_id,GEOP_var_id &
            ! 2d fields
            ,PS_var_id,PSL_var_id,LANDFRAC_var_id,TS_var_id,SEAICE_var_id &
            ! pressure variables
            ,P0_var_id,hyam_var_id,hybm_var_id &
            ! soil variables
            ,SM_var_id,ST_var_id &
            ! surface geopotential
            ,TOPO_var_id
  integer :: field_var_id(nfields),field2d_var_id(nfields2d) &
            ,lon_lat_netcdf_units_length,lon_lat_netcdf_title_length
  character(len=:),allocatable :: lon_netcdf_units(:),lon_netcdf_title(:) &
                                 ,lat_netcdf_units(:),lat_netcdf_title(:)
!  INCLUDE '/opt/cray/netcdf/4.3.0/INTEL/130/include/netcdf.inc'

  ! open output files for metgrid in WRF/WPS intermediate format:
  write(filename,'("Output/FILE:",A13)') hdate(1:13)
  write(outfile_diagnostics,*) "output intermediate file filename=",filename
  open(outfile_intermediate,form='unformatted',file=filename)

  write(filename,'("Output/SST:",A13)') hdate(1:13)
  write(outfile_diagnostics,*) "output intermediate SST file filename=",filename
  open(outfile_intermediate_SST,form='unformatted',file=filename)

  ! CAM
  STATUS = NF90_OPEN(netcdf_cam_filename, 0, NCID)
  IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS)
  ! CLM
  STATUS = NF90_OPEN(netcdf_clm_filename, 0, NCID_clm)
  IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS)
  ! POP
  STATUS = NF90_OPEN(netcdf_pop_filename, 0, NCID_pop)
  IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS)
  ! ICE
  STATUS = NF90_OPEN(netcdf_ice_filename, 0, NCID_ice)
  IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS)
  write(outfile_diagnostics,*) "done nf90_open"

  ! read netcdf data for all levels:
  ! ================================

  ! get variable IDs
  ! 3d:
  STATUS = NF90_INQ_VARID(NCID, 'lat', lat_var_id)
  STATUS = NF90_INQ_VARID(NCID, 'lon', lon_var_id)
  STATUS = NF90_INQ_VARID(NCID, 'lev', lev_var_id)
  STATUS = NF90_INQ_VARID(NCID, 'time', time_var_id)
  STATUS = NF90_INQ_VARID(NCID, 'nlon', nlon_var_id)
  STATUS = NF90_INQ_VARID(NCID, 'T', T_var_id)
  STATUS = NF90_INQ_VARID(NCID, 'Q', RH_var_id)
  STATUS = NF90_INQ_VARID(NCID, 'U', U_var_id)
  STATUS = NF90_INQ_VARID(NCID, 'V', V_var_id)
  STATUS = NF90_INQ_VARID(NCID, 'Z3', GEOP_var_id)
  IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS)

  ! 2d:
  STATUS = NF90_INQ_VARID(NCID, 'PS', PS_var_id)
  STATUS = NF90_INQ_VARID(NCID, 'PSL', PSL_var_id)
  STATUS = NF90_INQ_VARID(NCID, 'LANDFRAC', LANDFRAC_var_id)
  STATUS = NF90_INQ_VARID(NCID, 'PHIS', TOPO_var_id)
  IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS)

  ! pressure variables:
  STATUS = NF90_INQ_VARID(NCID, 'P0', P0_var_id)
  STATUS = NF90_INQ_VARID(NCID, 'hyam', hyam_var_id)
  STATUS = NF90_INQ_VARID(NCID, 'hybm', hybm_var_id)
  IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS)

  ! soil temp and moisture:
  STATUS = NF90_INQ_VARID(NCID_clm, 'SOILWATER_10CM', SM_var_id)
  STATUS = NF90_INQ_VARID(NCID_clm, 'TSOI_10CM', ST_var_id)
  IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS)

  ! Ying.Liu sst:
  STATUS = NF90_INQ_VARID(NCID_pop, 'tos', TS_var_id)
  IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS)

  ! Ying.Liu ice:
  STATUS = NF90_INQ_VARID(NCID_ice, 'aice_d', SEAICE_var_id)
  IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS)

  write(outfile_diagnostics,*) "done NF90_INQ_VARID, field_var_id=",field_var_id
  write(outfile_diagnostics,*) "field2d_var_id=",field2d_var_id

  ! get attribute values: title and units
  ! =====================================
  ! get units and titles for lon:
  STATUS = NF90_INQUIRE_ATTRIBUTE(NCID, lon_var_id, 'units', lon_lat_netcdf_units_length)
  STATUS = NF90_INQUIRE_ATTRIBUTE(NCID, lon_var_id, 'long_name', lon_lat_netcdf_title_length)
  IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS)
  write(outfile_diagnostics,*) " lon: netcdf units length=",lon_lat_netcdf_units_length &
       ,"; netcdf title length=",lon_lat_netcdf_title_length
!  allocate(lon_netcdf_units(lon_lat_netcdf_units_length))
!  allocate(lon_netcdf_title(lon_lat_netcdf_title_length))
  STATUS = NF90_GET_ATTRIBUTE(NCID, lon_var_id, 'units', lon_netcdf_units)
  STATUS = NF90_GET_ATTRIBUTE(NCID, lon_var_id, 'long_name', lon_netcdf_title)
  IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS)
  write(outfile_diagnostics,*) "netcdf title=",lon_netcdf_title,"; units=",lon_netcdf_units
  ! get units and titles for lat:
  STATUS = NF90_INQUIRE_ATTRIBUTE(NCID, lat_var_id, 'units', lon_lat_netcdf_units_length)
  STATUS = NF90_INQUIRE_ATTRIBUTE(NCID, lat_var_id, 'long_name', lon_lat_netcdf_title_length)
  IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS)
  write(outfile_diagnostics,*) " lat: netcdf units length=",lon_lat_netcdf_units_length &
       ,"; netcdf title length=",lon_lat_netcdf_title_length
!  allocate(lat_netcdf_units(lon_lat_netcdf_units_length))
!  allocate(lat_netcdf_title(lon_lat_netcdf_title_length))
  STATUS = NF90_GET_ATTRIBUTE(NCID, lat_var_id, 'units', lat_netcdf_units)
  STATUS = NF90_GET_ATTRIBUTE(NCID, lat_var_id, 'long_name', lat_netcdf_title)
  IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS)
  write(outfile_diagnostics,*) "netcdf title=",lat_netcdf_title,"; units=",lat_netcdf_units
!  deallocate(lon_netcdf_units,lon_netcdf_title,lat_netcdf_units,lat_netcdf_title)

  status=NF90_CLOSE(NCID)
  status=NF90_CLOSE(NCID_clm)
  status=NF90_CLOSE(NCID_pop)
  status=NF90_CLOSE(NCID_ice)

print *, "Leaving dummy, going to MAIN"
  return
end Subroutine dummy_read

A side question - if I uncomment out the lines allocating the lon[lat]_netcdf_units[title] at the very bottom of the program, there is another compiler error:

CAM_netcdf_to_WRF_intermediate.f90(467): error #8232: If any object being allocated in the ALLOCATE statement has deferred type parameter, either type specification or SOURCE= or MOLD= specifiers shall appear.   [LON_NETCDF_UNITS]
  allocate(lon_netcdf_units(lon_lat_netcdf_units_length))
-----------^

How would I go about allocating these characters? Should I be allocating it, or do I not need to do this?

Upvotes: 2

Views: 1809

Answers (1)

francescalus
francescalus

Reputation: 32366

According to the API documentation the function to use should be NF90_GET_ATT.

For the arguments of the correct function, the variable for the value of the attribute

should be a variable of type character with the len Fortran 90 attribute set to an appropriate value

It looks like the code is attempting to determine the length of the attributes' values and then for each allocate a deferred length character variable to the appropriate length. A laudable aim.

As the compiler warns, this is not a Fortran 90 feature, but that is not a problem beyond the warning. What is a problem is that there appears to be some confusion suggested by the declaration of the value variable

character(len=:),allocatable :: lon_netcdf_units(:)

This is a deferred length character variable, but is also an array. Instead:

character(len=:),allocatable :: lon_netcdf_units

Allocation for the length of this (now scalar) variable follows the form

allocate( character(len=lon_lat_netcdf_units_length) :: lon_netcdf_units )

which is the "type specification" method. [Alternatively, the mold= and source= options are available, but these are not worth going into here.]

[This is based on the nf90_inquire_attribute function returning the length of the attribute: my initial examination suggests that the call may not be correct and that the len= keyword is required.]

Upvotes: 4

Related Questions