Opened 8 years ago
Closed 8 years ago
#468 closed defect (fixed)
Misprocessing of DTocc information in UCAR files
Reported by: | Ian Culverwell | Owned by: | Ian Culverwell |
---|---|---|---|
Priority: | normal | Milestone: | 9.0 |
Component: | ropp_io | Version: | 8.0 |
Keywords: | UCAR | Cc: |
Description
Axel von Engeln (EUM) reports:
Some more trouble with new UCAR files, an example for the trouble is attached. It has second of 59.506... which is converted in ropp_io_read_ncdf_get.f90 with an NINT to seconds, leading to 60 seconds here. CALL ncdf_getatt('second', sec) DTocc%Second = NINT(sec) DTocc%Msec = 0 This in turn seems to lead to a start time of 0 seconds in the ROPP output file when running through ucar2ropp (or I believe this is the reason, I didn't go fully into the details of it just saw that the DTocc has 60 seconds and my ROPP output file has a start time of 0s).
Axel's file is attached. Clearly we need a better breakdown of second into dtocc%second and dtocc%msec.
Attachments (1)
Change history (10)
by , 8 years ago
Attachment: | atmPrf_MTPA.2013.001.01.55.G30_2016.0120_nc added |
---|
comment:1 by , 8 years ago
By replacing
DTocc%Second = NINT(sec) DTocc%Msec = 0
by
DTocc%Second = INT(sec) DTocc%Msec = NINT(1000.0*(sec - DTocc%Second))
in SUBROUTINE gettime in ropp_io_read_ncdf_get.f90, the results of passing the attached file through ucar2ropp change from
ncks -H -Q -vyear,month,day,hour,minute,second,msec,start_time atmPrf_MTPA.2013.001.01.55.G30_2016.0120_test.nc day[0]=1 hour[0]=1 minute[0]=55 month[0]=1 msec[0]=0 second[0]=99 start_time[0]=0 year[0]=2013
to
ncks -H -Q -vyear,month,day,hour,minute,second,msec,start_time atmPrf_MTPA.2013.001.01.55.G30_2016.0120_test.nc day[0]=1 hour[0]=1 minute[0]=55 month[0]=1 msec[0]=507 second[0]=59 start_time[0]=410320559.507 year[0]=2013
which looks OK, given that second = 59.5067520141602
in the input file. (Check: 01/01/2013 ~ 410 000 000 secs after 01/01/2000, and the ROPP start_time:units = "seconds since 2000-01-01 00:00:00"
.)
comment:2 by , 8 years ago
The root of the problem, as is often the case, is range-checking. In this case, NINT(59.5067520141602) = 60, which is outside the valid range of seconds ([0, 59]). Range-checking therefore sets ROdata%DTocc%Second to 99. The code to define the start_time (Sec 1.5.1 of ropp_io_write_ncdf_put.f90) says
IF (isroppinrange(data%dtocc)) THEN DT8 = (/data%dtocc%year,data%dtocc%month, data%dtocc%day,0, & data%dtocc%hour,data%dtocc%minute,data%dtocc%second, & data%dtocc%msec/) CALL TimeSince ( DT8, time, 1, Base="JS2000" ) ELSE time = 0.0_wp ENDIF CALL ncdf_putvar('start_time', time, rec = irec)
isroppinrange(data%dtocc)
checks that every element of data%dtocc, including data%dtocc%second, is in the required range, and this obviously fails in this case. Hence time
, and start_time
, are set to zero.
comment:3 by , 8 years ago
This change has been tested on the dataset above, and with earlier COSMIC files whose seconds were artificially set to 59.9. (Note that for these files second
was always a whole number in real form, like 25.
, so the problem would not have arisen. This also, presumably, explains the original design decision to set
DTocc%Msec
to zero, and to round DTocc%Second
to the nearest integer, not the one below.)
comment:5 by , 8 years ago
Stig Syndergaard (DMI) suggests that a better fix would be to replace
DTocc%Msec = NINT(1000.0*(sec - DTocc%Second))
by
DTocc%Msec = INT(1000.0_wp*(sec - DTocc%Second))
I agree!
comment:6 by , 8 years ago
Checked that the above correction works if sec=59.999. But sec
is defined as single precision in the calling routine; the above trick therefore fails if (for example) second = 59.99999999
, since this is rounded to sec = 60.0
before we even start mucking around with DTocc
. Defining
REAL(wp) :: sec
in SUBROUTINE gettime(DTocc) allows second = 59.99999999
and even second = 59.99999999999999
to work, although it fails (ie, DTocc%Second
gets set to 99, DTocc%Msec
gets set to 0, and start_time
gets set to 0) if second = 59.999999999999999
- a contingency with which we can probably live.
comment:7 by , 8 years ago
There is one slight infelicity, which is that 59.9_dp is stored in the computer as 59.8999999999999985789145285, which results in msec
being set to 899 according to the rounding down rule employed by INT
function. Perhaps this was why went for NINT
originally?
comment:8 by , 8 years ago
We can get around this last objection by saying
IF ( sec - DTocc%Second > 0.999_wp ) THEN DTocc%Msec = INT(1000.0_wp*(sec - DTocc%Second)) ELSE DTocc%Msec = NINT(1000.0_wp*(sec - DTocc%Second)) END IF
Then second=59.9 ==> second=59 and msec=900.
comment:9 by , 8 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
This change has been committed at r5051. Closing ticket as 'fixed'.
atmPrf_MTPA.2013.001.01.55.G30_2016.0120_nc