module m_read_CLS_TSLA integer, parameter, private :: STRLEN = 512 real(8), parameter, private :: RE_MULTIPLE = 0.7d0 character(*), parameter, private :: RE_FNAME = "re_sla.nc" contains subroutine read_CLS_TSLA(filename, gr, data) use mod_measurement use mod_grid use nfw_mod implicit none character(*), intent(in) :: filename type(grid), intent(inout) :: gr ! CLS measurement grid type(measurement), intent(inout) :: data(:) integer :: data_ID, track_ID, cycl_ID integer :: vNbpoint_ID, vLongitude_ID, vLatitude_ID, vBegindate_ID, vSLA_ID ! array dimensions integer :: nb, ntracks, ncycles ! data arrays real(8), allocatable :: vsla(:,:), vlon(:), vlat(:), vbegindate(:,:) integer, allocatable :: vnbpoint(:) logical, allocatable :: isgood(:,:) integer :: ncid real(8), dimension(1) :: undef_sla, undef_lat, undef_lon, undef_begindate real(8) :: varsat integer, dimension(1) :: undef_nbpoint integer :: i, j, k, nobs, obsid, sid, age real(8), parameter :: EPS = 0.01 ! test for undefined values character(STRLEN) :: ftemplate character(STRLEN) :: fname character(STRLEN) :: fpath logical :: ex print *, 'read_CLS_TSLA():' fpath='./' read(filename,'(i7)') age nobs = 0 do sid = 1, 7 ! loop over satellite ID select case(sid) case(1) ftemplate = trim(fpath)//'sla_'//trim(filename)//'_en*.nc' varsat = 0.0009 ! 3 cm for ENVISAT print *, ' ENVISSAT:' case(2) ftemplate = trim(fpath)//'sla_'//trim(filename)//'_j1*.nc' varsat = 0.0009 ! 3 cm for ENVISAT Jason1 print *, ' Jason1:' case(3) ftemplate = trim(fpath)//'sla_'//trim(filename)//'_j2*.nc' varsat = 0.0009 ! 3 cm for ENVISAT Jason2 print *, ' Jason2:' case(4) ftemplate = trim(fpath)//'sla_'//trim(filename)//'_e1*.nc' varsat = 0.0075 ! 8.5 cm for e1 print *, ' ERS1:' case(5) ftemplate = trim(fpath)//'sla_'//trim(filename)//'_e2*.nc' varsat = 0.0075 ! 8.5 cm for e2 print *, ' ERS2:' case(6) ftemplate = trim(fpath)//'sla_'//trim(filename)//'_tp*.nc' varsat = 0.0030 ! 5.5 cm for TOPEX print *, ' TOPEX:' case(7) ftemplate = trim(fpath)//'sla_'//trim(filename)//'_g2*.nc' varsat = 0.0030 ! GEOSAT print *, ' GEOSAT2:' end select call fname_fromtemplate(ftemplate, fname) inquire(file = trim(fname), exist = ex) if (.not. ex) then cycle end if ! Reading the observation file of satellite call nfw_open(fname, nf_nowrite, ncid) call nfw_inq_dimid(fname, ncid, 'Data', data_ID) call nfw_inq_dimid(fname, ncid, 'Tracks', track_ID) call nfw_inq_dimid(fname, ncid, 'Cycles', cycl_ID) call nfw_inq_dimlen(fname, ncid, data_ID, nb) call nfw_inq_dimlen(fname, ncid, track_ID, ntracks) call nfw_inq_dimlen(fname, ncid, cycl_ID, ncycles) print '(1x, a, 3i8)', ' dimensions (# obs, # tracks, # cycles):', nb, ntracks, ncycles allocate(vlon(nb), vlat(nb), vsla(ncycles, nb)) allocate(vnbpoint(ntracks), vbegindate(ncycles, ntracks)) allocate(isgood(ncycles, ntracks)) ! Variable ids in netcdf file call nfw_inq_varid(fname, ncid, 'Latitudes', vLatitude_ID) call nfw_inq_varid(fname, ncid,'Longitudes', vLongitude_ID) call nfw_inq_varid(fname, ncid,'BeginDates', vBegindate_ID) call nfw_inq_varid(fname, ncid,'NbPoints', vNbpoint_ID) call nfw_inq_varid(fname, ncid,'SLA', vSLA_ID) ! Variable _FillValue attributes call nfw_get_att_double(fname, ncid, vLatitude_ID , '_FillValue', undef_lat(1)) call nfw_get_att_double(fname, ncid, vLongitude_ID , '_FillValue', undef_lon(1)) call nfw_get_att_double(fname, ncid, vSLA_ID, '_FillValue', undef_sla(1)) call nfw_get_att_int(fname, ncid, vNbpoint_ID, '_FillValue', undef_nbpoint(1)) call nfw_get_att_double(fname, ncid,vBegindate_ID, '_FillValue', undef_begindate(1)) gr % undef = undef_sla(1) call nfw_get_var_double(fname, ncid, vLongitude_ID, vlon) call nfw_get_var_double(fname, ncid, vLatitude_ID, vlat) call nfw_get_var_double(fname, ncid, vSLA_ID, vsla) !lon = ang180(lon) vlon = vlon * 1.e-06 vlat = vlat * 1.e-06 print '(1x, a, 2f10.2)', ' range Lon = ', minval(vlon), maxval(vlon) print '(1x, a, 2f10.2)', ' range Lat = ', minval(vlat), maxval(vlat) print '(1x, a, 2f10.2)', ' range SLA = ', minval(vsla), maxval(vsla) call nfw_get_var_int(fname, ncid, vNbpoint_ID, vnbpoint) call nfw_get_var_double(fname, ncid, vBegindate_ID, vbegindate) print '(1x, a, 2i8)', ' range nbpoints = ', minval(vnbpoint), maxval(vnbpoint) print *, ' age = ', age isgood = .false. where (vbegindate /= undef_begindate(1)) vbegindate = age - floor(vbegindate) - 1 isgood = .true. end where print '(3x,a,2G10.3)',' range begin_date (days from assim) = ', & minval(pack(vbegindate, isgood)), maxval(pack(vbegindate, isgood)) call nfw_close(fname, ncid) ! Here we set the reference the date with respect to the assimilation ! date (0=today, 6=is 6 day old). ! Fanf: We assume that the data from the same pass have the same ! date=begindate(passnb). ! We also assume that envisat, J1 and J2 have similar accuracy, and ! thus use data%var to store the age of the data. Only data that are ! younger than 6 days are retained such that we do not assimilate the ! same obs twice. do k = 1, ncycles obsid = 0 do i = 1, ntracks do j = 1, vnbpoint(i) obsid = obsid + 1 ! only consider data above -30 of lat if (vlat(obsid) <= -30.0 .or.& vbegindate(k, i) >= 7 .or. vbegindate(k, i) <= -1 .or.& vlon(obsid) == undef_lon(1) .or.& vlat(obsid) == undef_lat(1) .or.& vsla(k, obsid) == undef_sla(1)) then cycle end if nobs = nobs + 1 data(nobs) % id = 'TSLA' data(nobs) % d = vsla(k, obsid) * 0.001 ! conversion to meters data(nobs) % ipiv = -1 ! to be filled data(nobs) % jpiv = -1 data(nobs) % lat = vlat(obsid) data(nobs) % lon = ang180(vlon(obsid)) data(nobs) % a1 = -1.0e10 ! to be filled data(nobs) % a2 = -1.0e10 data(nobs) % a3 = -1.0e10 data(nobs) % a4 = -1.0e10 data(nobs) % ns = 0 data(nobs) % var = varsat data(nobs) % date = int(vbegindate(k, i)) data(nobs) % depth = 0.0 data(nobs) % status = .true. enddo ! Vnbpoint enddo ! track enddo ! cycle print*, ' # of obs read so far = ', nobs deallocate(vlat, vlon, vsla, vnbpoint, vbegindate, isgood) end do ! satellite id gr % nx = nobs end subroutine read_CLS_TSLA subroutine read_MYO_TSLA(julday,dayinweek, gr, data) use mod_measurement use mod_grid use nfw_mod implicit none !Fanf: this routine assume that you have one seperate file for each day. !Call prepobs 7 times (for each cycle days with the date and the corrsponding !day in the cycle ! character(*), intent(in) :: filename character(*), intent(in) :: julday, dayinweek type(grid), intent(inout) :: gr ! MYO measurement grid type(measurement), intent(inout) :: data(:) integer :: time_ID !data_ID, track_ID, cycl_ID integer :: vNbpoint_ID, vLongitude_ID, vLatitude_ID, vBegindate_ID, vSLA_ID, vtime_ID ! array dimensions integer :: nb !, ntracks, ncycles ! data arrays real(8), allocatable :: vsla(:), vlon(:), vlat(:), vtime(:)!, vbegindate(:,:) logical, allocatable :: isgood(:) integer :: ncid real(8), dimension(1) :: undef_sla, undef_lat, undef_lon, undef_begindate, undef_time real(8) :: varsat integer, dimension(1) :: undef_nbpoint integer :: i, j, k, nobs, obsid, sid, age, idayinweek real(8), parameter :: EPS = 0.01 ! test for undefined values character(STRLEN) :: ftemplate character(STRLEN) :: fname character(STRLEN) :: fpath logical :: ex print *, 'read_MYO_TSLA():' fpath='./' read(julday,'(i7)') age read(dayinweek,'(i2)') idayinweek nobs = 0 do sid = 1, 9 ! loop over satellite ID select case(sid) case(1) ftemplate = trim(fpath)//'sla_'//trim(julday)//'_en*.nc' varsat = 0.0009 ! 3 cm for ENVISAT print *, ' ENVISSAT:' case(2) ftemplate = trim(fpath)//'sla_'//trim(julday)//'_j1*.nc' varsat = 0.0009 ! 3 cm for ENVISAT Jason1 print *, ' Jason1:' case(3) ftemplate = trim(fpath)//'sla_'//trim(julday)//'_j2*.nc' varsat = 0.0009 ! 3 cm for ENVISAT Jason2 print *, ' Jason2:' case(4) ftemplate = trim(fpath)//'sla_'//trim(julday)//'_e1*.nc' varsat = 0.0075 ! 8.5 cm for e1 print *, ' ERS1:' case(5) ftemplate = trim(fpath)//'sla_'//trim(julday)//'_e2*.nc' varsat = 0.0075 ! 8.5 cm for e2 print *, ' ERS2:' case(6) ftemplate = trim(fpath)//'sla_'//trim(julday)//'_tp*.nc' varsat = 0.0030 ! 5.5 cm for TOPEX print *, ' TOPEX:' case(7) ftemplate = trim(fpath)//'sla_'//trim(julday)//'_g2*.nc' varsat = 0.0030 ! GEOSAT print *, ' GEOSAT2:' case(8) ftemplate = trim(fpath)//'sla_'//trim(julday)//'_c2*.nc' varsat = 0.0030 ! CRYOSAT-2 print *, ' CRYOSAT2:' case(9) ftemplate = trim(fpath)//'sla_'//trim(julday)//'_al*.nc' varsat = 0.0009 ! ALTIKA print *, ' ALTIKA:' end select call fname_fromtemplate(ftemplate, fname) inquire(file = trim(fname), exist = ex) if (.not. ex) then cycle end if ! Reading the observation file of satellite call nfw_open(fname, nf_nowrite, ncid) call nfw_inq_dimid(fname, ncid, 'time', time_ID) call nfw_inq_dimlen(fname, ncid, time_ID, nb) print '(1x, a, i8)', ' dimensions (# obs):', nb !, ntracks, ncycles allocate(vlon(nb), vlat(nb), vsla(nb), vtime(nb)) allocate(isgood(nb)) ! Variable ids in netcdf file call nfw_inq_varid(fname, ncid, 'latitude', vLatitude_ID) call nfw_inq_varid(fname, ncid,'longitude', vLongitude_ID) call nfw_inq_varid(fname, ncid, 'time', vtime_ID) call nfw_inq_varid(fname, ncid,'SLA', vSLA_ID) ! Variable _FillValue attributes call nfw_get_att_double(fname, ncid, vSLA_ID, '_FillValue', undef_sla(1)) gr % undef = undef_sla(1) call nfw_get_var_double(fname, ncid, vLongitude_ID, vlon) call nfw_get_var_double(fname, ncid, vLatitude_ID, vlat) call nfw_get_var_double(fname, ncid, vSLA_ID, vsla) call nfw_get_var_double(fname, ncid, vtime_ID, vtime) !lon = ang180(lon) vlon = vlon * 1.e-06 vlat = vlat * 1.e-06 print '(1x, a, 2f10.2)', ' range Lon = ', minval(vlon), maxval(vlon) print '(1x, a, 2f10.2)', ' range Lat = ', minval(vlat), maxval(vlat) print '(1x, a, 2f10.2)', ' range SLA = ', minval(vsla), maxval(vsla) print *, ' age = ', age print '(3x,a,G10.3)',' Days before assim = ', idayinweek call nfw_close(fname, ncid) ! Here we set the reference the date with respect to the assimilation ! date (0=today, 6=is 6 day old). ! Fanf: We assume that the data from the same pass have the same ! date=begindate(passnb). ! We also assume that envisat, J1 and J2 have similar accuracy, and ! thus use data%var to store the age of the data. Only data that are ! younger than 6 days are retained such that we do not assimilate the ! same obs twice. obsid = 0 do k = 1, nb obsid = obsid + 1 ! only consider data above -30 of lat if (vlat(obsid) <= -30.0 .or.& vsla(obsid) == undef_sla(1)) then cycle end if nobs = nobs + 1 data(nobs) % id = 'TSLA' data(nobs) % d = vsla(obsid) * 0.001 ! conversion to meters data(nobs) % ipiv = -1 ! to be filled data(nobs) % jpiv = -1 data(nobs) % lat = vlat(obsid) data(nobs) % lon = ang180(vlon(obsid)) data(nobs) % a1 = -1.0e10 ! to be filled data(nobs) % a2 = -1.0e10 data(nobs) % a3 = -1.0e10 data(nobs) % a4 = -1.0e10 data(nobs) % ns = 0 data(nobs) % var = varsat data(nobs) % date = idayinweek data(nobs) % depth = 0.0 data(nobs) % status = .true. enddo ! cycle print*, ' # of obs read so far = ', nobs, obsid deallocate(vlat, vlon, vsla, vtime, isgood) end do ! satellite id gr % nx = nobs end subroutine read_MYO_TSLA subroutine set_re_TSLA(nrobs, obs, nx, ny, modlon, modlat) use mod_measurement use nfw_mod integer, intent(in) :: nrobs type(measurement), dimension(nrobs), intent(inout) :: obs integer, intent(in) :: nx, ny real, dimension(nx, ny), intent(in) :: modlon, modlat integer :: ncid, reid real, dimension(nx, ny) :: re real :: reo integer :: o print *, ' reading representation error from "', trim(RE_FNAME), '"' call nfw_open(RE_FNAME, nf_nowrite, ncid) call nfw_inq_varid(RE_FNAME, ncid, 're_sla', reid) call nfw_get_var_double(RE_FNAME, ncid, reid, re) call nfw_close(RE_FNAME, ncid) do o = 1, nrobs reo = re(obs(o) % ipiv, obs(o) % jpiv) if (reo < 0 .or. reo > 1.0d5) then cycle end if ! PS 1.4.2010 Increased the multiple for representation error from ! 0.3 to 0.5 - it seems that with 0.3 it wants to do more in the Gulf ! Stream region than the model can sustain. ! PS June 2010 - further increased the multiple to 0.7. obs(o) % var = obs(o) % var + RE_MULTIPLE * reo end do end subroutine set_re_TSLA subroutine fname_fromtemplate(ftemplate, fname) character(*), intent(in) :: ftemplate character(*), intent(inout) :: fname character(STRLEN) :: command ! (there may be a limit of 80 on some systems) integer :: ios command = 'ls '//trim(ftemplate)//' 2> /dev/null > tsla_files.txt' call system(trim(command)); open(10, file = 'tsla_files.txt') read(10, fmt = '(a)', iostat = ios) fname close(10) if (ios /= 0) then fname = "" end if end subroutine fname_fromtemplate end module m_read_CLS_TSLA