21 subroutine get_amip_sst_ (Time, Interp, sst, err_msg, lon_model, lat_model)
22 type (time_type),
intent(in) :: Time
23 type (amip_interp_type),
target,
intent(inout) :: Interp
24 real(FMS_AMIP_INTERP_KIND_),
intent(out) :: sst(:,:)
25 character(len=*),
optional,
intent(out) :: err_msg
27 real(FMS_AMIP_INTERP_KIND_),
dimension(mobs,nobs) :: sice
28 real(FMS_AMIP_INTERP_KIND_),
allocatable,
save :: temp1(:,:), temp2(:,:)
30 integer :: year1, year2, month1, month2
31 real(FMS_AMIP_INTERP_KIND_) :: fmonth
32 type (date_type) :: Date1, Date2, Udate1, Udate2
34 type(time_type) :: Amip_Time
35 integer :: tod(3),dum(3)
38 real(FMS_AMIP_INTERP_KIND_),
intent(in),
dimension(:,:),
optional :: lon_model, lat_model
39 real(FMS_AMIP_INTERP_KIND_) :: pert
40 integer :: i, j, mobs_sst, nobs_sst
42 type (time_type) :: Udate
43 character(len=4) :: yyyy
44 integer :: nrecords, ierr, k, yr, mo, dy
45 integer,
dimension(:),
allocatable :: ryr, rmo, rdy
46 character(len=30) :: time_unit
47 real(FMS_AMIP_INTERP_KIND_),
dimension(:),
allocatable :: timeval
48 character(len=FMS_FILE_LEN) :: ncfilename
49 type(FmsNetcdfFile_t) :: fileobj
50 logical :: the_file_exists
52 logical,
parameter :: DEBUG = .false.
55 integer,
parameter :: lkind = fms_amip_interp_kind_
57 if(
present(err_msg)) err_msg =
''
58 if(.not.interp%I_am_initialized)
then
59 if(fms_error_handler(
'get_amip_sst',
'The amip_interp_type variable is not initialized',err_msg))
return
65 if ( use_ncep_sst .and. forecast_mode ) no_anom_sst = .false.
67 if (all(amip_date>0))
then
68 call get_date(time,dum(1),dum(2),dum(3),tod(1),tod(2),tod(3))
69 amip_time = set_date(amip_date(1),amip_date(2),amip_date(3),tod(1),tod(2),tod(3))
75 if ( .not.use_daily )
then
78 if ( .not.
allocated(temp1) )
allocate (temp1(mobs,nobs))
79 if ( .not.
allocated(temp2) )
allocate (temp2(mobs,nobs))
82 call zonal_sst_ (amip_time, sice, temp1)
83 call horiz_interp (interp%Hintrp, temp1, sst)
90 call time_interp (amip_time, fmonth, year1, year2, month1, month2)
92 if (interp%use_climo)
then
95 if (interp%use_annual)
then
101 date1 = date_type( year1, month1, 0 )
102 date2 = date_type( year2, month2, 0 )
108 if (date1 /= interp%Date1)
then
110 if (date1 == interp%Date2)
then
111 interp%Date1 = interp%Date2
112 interp%DATA1_ = interp%DATA2_
113 temp1(:,:) = temp2(:,:)
115 call read_record_ (
'sst', date1, udate1, temp1)
116 call horiz_interp ( interp%Hintrp, temp1, interp%DATA1_)
117 call clip_data_ (
'sst', interp%DATA1_)
124 if (date2 /= interp%Date2)
then
125 call read_record_ (
'sst', date2, udate2, temp2)
126 call horiz_interp ( interp%Hintrp, temp2, interp%DATA2_)
127 call clip_data_ (
'sst', interp%DATA2_)
134 sst = interp%DATA1_ + fmonth * (interp%DATA2_ - interp%DATA1_)
144 call get_date(amip_time,jhctod(1),jhctod(2),jhctod(3),jhctod(4),jhctod(5),jhctod(6))
146 write (*,200)
'JHC: use_daily = F, AMIP_Time: ',jhctod(1),jhctod(2),jhctod(3),jhctod(4),jhctod(5), &
148 write (*,300)
'JHC: use_daily = F, interped SST: ', sst(1,1),sst(5,5),sst(10,10)
157 call get_date(amip_time,jhctod(1),jhctod(2),jhctod(3),jhctod(4),jhctod(5),jhctod(6))
158 if (
mpp_pe() == mpp_root_pe())
write(*,200)
'amip_interp_mod: use_daily = T, Amip_Time = ',jhctod(1), &
159 & jhctod(2),jhctod(3),jhctod(4),jhctod(5),jhctod(6)
161 yr = jhctod(1); mo = jhctod(2); dy = jhctod(3)
163 write (yyyy,
'(i4)') jhctod(1)
165 file_name_sst =
'INPUT/' //
'sst.day.mean.'//yyyy//
'.v2.nc'
166 ncfilename = trim(file_name_sst)
167 time_unit =
'days since 1978-01-01 00:00:00'
169 mobs_sst = 1440; nobs_sst = 720
171 call set_sst_grid_edges_daily_ (mobs_sst, nobs_sst)
172 call horiz_interp_new ( interp%Hintrp2, lon_bnd_, lat_bnd_, &
173 lon_model, lat_model, interp_method=
"bilinear" )
175 the_file_exists = fms2_io_file_exists(ncfilename)
177 if ( (.NOT. the_file_exists) )
then
178 call mpp_error (
'amip_interp_mod', &
179 'cannot find daily SST input data file: '//trim(ncfilename), note)
181 if (
mpp_pe() == mpp_root_pe())
call mpp_error (
'amip_interp_mod', &
182 'Reading NetCDF formatted daily SST from: '//trim(ncfilename), note)
184 if(.not. open_file(fileobj, trim(ncfilename),
'read')) &
185 call error_mesg (
'get_amip_sst',
'Error in opening file '//trim(ncfilename), fatal)
187 call get_dimension_size(fileobj,
'TIME', nrecords)
188 if (nrecords < 1)
call mpp_error(
'amip_interp_mod', &
189 'Invalid number of SST records in daily SST data file: '//trim(ncfilename), fatal)
190 allocate(timeval(nrecords), ryr(nrecords), rmo(nrecords), rdy(nrecords))
191 call fms2_io_read_data(fileobj,
'TIME', timeval)
195 print *,
'JHC: nrecords = ', nrecords
196 print *,
'JHC: TIME = ', timeval
203 udate = get_cal_time(timeval(k), time_unit,
'julian')
204 call get_date(udate,jhctod(1),jhctod(2),jhctod(3),jhctod(4),jhctod(5),jhctod(6))
205 ryr(k) = jhctod(1); rmo(k) = jhctod(2); rdy(k) = jhctod(3)
207 if ( yr == ryr(k) .and. mo == rmo(k) .and. dy == rdy(k) ) ierr = 0
214 print *,
'JHC: k =', k
215 print *,
'JHC: ryr(k) rmo(k) rdy(k)',ryr(k), rmo(k), rdy(k)
216 print *,
'JHC: yr mo dy ',yr, mo, dy
220 if (ierr .ne. 0)
call mpp_error(
'amip_interp_mod', &
221 'Model time is out of range not in SST data: '//trim(ncfilename), fatal)
226 if ( .not.
allocated(tempamip) ) &
227 &
allocate (tempamip(mobs_sst,nobs_sst))
229 if (the_file_exists)
then
230 call fms2_io_read_data(fileobj,
'SST', tempamip, unlim_dim_level=k)
231 call close_file(fileobj)
232 tempamip = tempamip + tfreeze
237 print*,
'JHC: TFREEZE = ', real(tfreeze, fms_amip_interp_kind_)
240 print*, lbound(tempamip)
241 print*, ubound(tempamip)
242 write(*,300)
'JHC: tempamip : ', tempamip(100,100), tempamip(200,200), tempamip(300,300)
246 call horiz_interp ( interp%Hintrp2, tempamip_, sst )
247 call clip_data_ (
'sst', sst)
253 write(*,300)
'JHC: use_daily = T, daily SST: ', sst(1,1),sst(5,5),sst(10,10)
254 print *,
'JHC: use_daily = T, daily SST: ', sst
258 200
format(a35, 6(i5,1x))
259 300
format(a35, 3(f7.3,2x))
267 if ( do_sst_pert )
then
269 if ( trim(sst_pert_type) ==
'fixed' )
then
270 sst = sst + real(sst_pert, fms_amip_interp_kind_)
271 else if ( trim(sst_pert_type) ==
'random' )
then
276 print*,
'mobs = ', mobs
277 print*,
'nobs = ', nobs
283 do i = 1,
size(sst,1)
284 do j = 1,
size(sst,2)
285 call random_number(pert)
286 sst(i,j) = sst(i,j) + real(sst_pert, fms_amip_interp_kind_)*((pert-0.5_lkind)*2)
293 end subroutine get_amip_sst_
296 subroutine get_amip_ice_ (Time, Interp, ice, err_msg)
297 type (time_type),
intent(in) :: Time
298 type (amip_interp_type),
target,
intent(inout) :: Interp
299 real(FMS_AMIP_INTERP_KIND_),
intent(out) :: ice(:,:)
300 character(len=*),
optional,
intent(out) :: err_msg
302 real(FMS_AMIP_INTERP_KIND_),
dimension(mobs,nobs) :: sice, temp
304 integer :: year1, year2, month1, month2
305 real(FMS_AMIP_INTERP_KIND_) :: fmonth
306 type (date_type) :: Date1, Date2, Udate1, Udate2
308 type(time_type) :: Amip_Time
309 integer :: tod(3),dum(3)
310 integer,
parameter :: lkind = fms_amip_interp_kind_
312 if(
present(err_msg)) err_msg =
''
313 if(.not.interp%I_am_initialized)
then
314 if(fms_error_handler(
'get_amip_ice',
'The amip_interp_type variable is not initialized',err_msg))
return
321 if (any(amip_date>0))
then
323 call get_date(time,dum(1),dum(2),dum(3),tod(1),tod(2),tod(3))
325 amip_time = set_date(amip_date(1),amip_date(2),amip_date(3),tod(1),tod(2),tod(3))
335 call zonal_sst_ (amip_time, sice, temp)
336 call horiz_interp ( interp%Hintrp, sice, ice )
344 call time_interp (amip_time, fmonth, year1, year2, month1, month2)
347 if (interp%use_climo)
then
350 if (interp%use_annual)
then
356 date1 = date_type( year1, month1, 0 )
357 date2 = date_type( year2, month2, 0 )
362 if (date1 /= interp%Date1)
then
364 if (date1 == interp%Date2)
then
365 interp%Date1 = interp%Date2
366 interp%DATA1_ = interp%DATA2_
371 call read_record_ (
'ice', date1, udate1, sice)
373 call horiz_interp ( interp%Hintrp, sice, interp%DATA1_)
374 call clip_data_ (
'ice', interp%DATA1_)
381 if (date2 /= interp%Date2)
then
384 call read_record_ (
'ice', date2, udate2, sice)
386 call horiz_interp ( interp%Hintrp, sice, interp%DATA2_)
387 call clip_data_ (
'ice', interp%DATA2_)
396 ice = interp%DATA1_ + fmonth * (interp%DATA2_ - interp%DATA1_)
399 end subroutine get_amip_ice_
402 function amip_interp_new_1d_ ( lon , lat , mask , use_climo, use_annual, &
403 interp_method )
result (Interp)
404 real(FMS_AMIP_INTERP_KIND_),
intent(in),
dimension(:) :: lon, lat
405 logical,
intent(in),
dimension(:,:) :: mask
406 character(len=*),
intent(in),
optional :: interp_method
407 logical,
intent(in),
optional :: use_climo, use_annual
409 type (amip_interp_type) :: Interp
411 if(.not.module_is_initialized)
call amip_interp_init
413 interp%use_climo = .false.
414 if (
present(use_climo)) interp%use_climo = use_climo
415 interp%use_annual = .false.
416 if (
present(use_annual)) interp%use_annual = use_annual
418 if ( date_out_of_range ==
'fail' .and. interp%use_climo ) &
419 call error_mesg (
'amip_interp_new_1d',
'use_climo mismatch', fatal)
421 if ( date_out_of_range ==
'fail' .and. interp%use_annual ) &
422 call error_mesg (
'amip_interp_new_1d',
'use_annual(climo) mismatch', fatal)
424 interp%Date1 = date_type( -99, -99, -99 )
425 interp%Date2 = date_type( -99, -99, -99 )
430 call horiz_interp_new ( interp%Hintrp, lon_bnd_, lat_bnd_, &
431 lon, lat, interp_method= interp_method )
433 allocate(interp%DATA1_ (
size(lon(:))-1,
size(lat(:))-1))
434 allocate(interp%DATA2_ (
size(lon(:))-1,
size(lat(:))-1))
436 interp%I_am_initialized = .true.
437 end function amip_interp_new_1d_
440 function amip_interp_new_2d_ ( lon , lat , mask , use_climo, use_annual, &
441 interp_method )
result (Interp)
442 real(FMS_AMIP_INTERP_KIND_),
intent(in),
dimension(:,:) :: lon, lat
443 logical,
intent(in),
dimension(:,:) :: mask
444 character(len=*),
intent(in),
optional :: interp_method
445 logical,
intent(in),
optional :: use_climo, use_annual
447 type (amip_interp_type) :: Interp
449 if(.not.module_is_initialized)
call amip_interp_init
451 interp%use_climo = .false.
452 if (
present(use_climo)) interp%use_climo = use_climo
453 interp%use_annual = .false.
454 if (
present(use_annual)) interp%use_annual = use_annual
456 if ( date_out_of_range ==
'fail' .and. interp%use_climo ) &
457 call error_mesg (
'amip_interp_new_2d',
'use_climo mismatch', fatal)
459 if ( date_out_of_range ==
'fail' .and. interp%use_annual ) &
460 call error_mesg (
'amip_interp_new_2d',
'use_annual(climo) mismatch', fatal)
462 interp%Date1 = date_type( -99, -99, -99 )
463 interp%Date2 = date_type( -99, -99, -99 )
468 call horiz_interp_new ( interp%Hintrp, lon_bnd_, lat_bnd_, &
469 lon, lat, interp_method = interp_method)
471 allocate(interp%DATA1_ (
size(lon,1),
size(lat,2)))
472 allocate(interp%DATA2_ (
size(lon,1),
size(lat,2)))
474 interp%I_am_initialized = .true.
475 end function amip_interp_new_2d_
478 subroutine set_sst_grid_edges_daily_ (mobs_sst, nobs_sst)
479 integer :: i, j, mobs_sst, nobs_sst
480 real(FMS_AMIP_INTERP_KIND_) :: hpie, dlon, dlat, wb, sb
481 integer,
parameter :: lkind = fms_amip_interp_kind_
483 if(
allocated(lon_bnd))
deallocate(lon_bnd)
484 if(
allocated(lat_bnd))
deallocate(lat_bnd)
486 allocate(lon_bnd(mobs_sst+1))
487 allocate(lat_bnd(nobs_sst+1))
491 hpie = pi / 2._r8_kind
492 dlon = 4._r8_kind*hpie/real(mobs_sst, r8_kind)
497 lon_bnd(i) = wb + dlon * real(i-1, r8_kind)
499 lon_bnd(mobs_sst+1) = lon_bnd(1) + 4._r8_kind*hpie
501 dlat = 2._r8_kind*hpie/real(nobs_sst, r8_kind)
505 lat_bnd(nobs_sst+1) = hpie
507 lat_bnd(j) = sb + dlat * real(j-1, r8_kind)
509 end subroutine set_sst_grid_edges_daily_
512 subroutine a2a_bilinear_ (nx, ny, dat1, n1, n2, dat2)
513 integer,
intent(in) :: nx, ny
514 integer,
intent(in) :: n1, n2
515 real(FMS_AMIP_INTERP_KIND_),
intent(in) :: dat1(nx,ny)
516 real(FMS_AMIP_INTERP_KIND_),
intent(out) :: dat2(n1,n2)
519 real(FMS_AMIP_INTERP_KIND_) :: lon1(nx), lat1(ny)
520 real(FMS_AMIP_INTERP_KIND_) :: lon2(n1), lat2(n2)
521 real(FMS_AMIP_INTERP_KIND_) :: dx1, dy1, dx2, dy2
522 real(FMS_AMIP_INTERP_KIND_) :: xc, yc
523 real(FMS_AMIP_INTERP_KIND_) :: a1, b1, c1, c2, c3, c4
524 integer :: i1, i2, jc, i0, j0, it, jt
526 integer,
parameter :: lkind = fms_amip_interp_kind_
535 dx1 = 360._lkind/real(nx, fms_amip_interp_kind_)
536 dy1 = 180._lkind/real(ny, fms_amip_interp_kind_)
539 lon1(i) = 0.5_lkind*dx1 + real(i-1, fms_amip_interp_kind_)*dx1
542 lat1(j) = -90._lkind + 0.5_lkind*dy1 + real(j-1, fms_amip_interp_kind_)*dy1
545 dx2 = 360._lkind/real(n1, fms_amip_interp_kind_)
546 dy2 = 180._lkind/real(n2, fms_amip_interp_kind_)
549 lon2(i) = 0.5_lkind*dx2 + real(i-1, fms_amip_interp_kind_)*dx2
552 lat2(j) = -90._lkind + 0.5_lkind*dy2 + real(j-1, fms_amip_interp_kind_)*dy2
559 if ( yc<lat1(1) )
then
562 elseif ( yc>lat1(ny) )
then
567 if ( yc>=lat1(j0) .and. yc<=lat1(j0+1) )
then
570 b1 = (yc-lat1(jc)) / dy1
580 if ( xc>lon1(nx) )
then
582 a1 = (xc-lon1(nx)) / dx1
583 elseif ( xc<lon1(1) )
then
585 a1 = (xc+360._lkind-lon1(nx)) / dx1
588 if ( xc>=lon1(i0) .and. xc<=lon1(i0+1) )
then
591 a1 = (xc-lon1(i1)) / dx1
599 if ( a1<-0.001_lkind .or. a1>1.001_lkind .or. b1<-0.001_lkind .or. b1>1.001_lkind )
then
600 write(*,*) i,j,a1, b1
601 call mpp_error(fatal,
'a2a bilinear interpolation')
604 c1 = (1._lkind-a1) * (1._lkind-b1)
605 c2 = a1 * (1._lkind-b1)
607 c4 = (1._lkind-a1) * b1
610 dat2(i,j) = c1*dat1(i1,jc) + c2*dat1(i2,jc) + c3*dat1(i2,jc+1) + c4*dat1(i1,jc+1)
615 end subroutine a2a_bilinear_
617 subroutine read_record_ (type, Date, Adate, dat)
618 character(len=*),
intent(in) :: type
619 type (date_type),
intent(in) :: Date
620 type (date_type),
intent(inout) :: Adate
621 real(FMS_AMIP_INTERP_KIND_),
intent(out) :: dat(mobs,nobs)
622 real(FMS_AMIP_INTERP_KIND_) :: tmp_dat(360,180)
624 integer(I2_KIND) :: idat(mobs,nobs)
625 integer :: nrecords, yr, mo, dy, ierr, k
626 integer,
dimension(:),
allocatable :: ryr, rmo, rdy
627 character(len=FMS_FILE_LEN) :: ncfilename
628 character(len=NF90_MAX_NAME) :: ncfieldname
629 type(FmsNetcdfFile_t),
pointer :: fileobj
630 integer,
parameter :: lkind = fms_amip_interp_kind_
635 if(
type(1:3) ==
'sst') then
636 ncfilename = trim(file_name_sst)
637 fileobj => fileobj_sst
638 else if(
type(1:3) ==
'ice') then
639 ncfilename = trim(file_name_ice)
640 fileobj => fileobj_ice
641 if (lowercase(trim(data_set)) ==
'amip2' .or. &
642 lowercase(trim(data_set)) ==
'hurrell' .or. &
643 lowercase(trim(data_set)) ==
'daily') ncfieldname =
'ice'
648 if (verbose > 2 .and.
mpp_pe() == 0) &
649 print *,
'looking for date = ', date
652 if (
mpp_pe() == mpp_root_pe())
call mpp_error (
'amip_interp_mod', &
653 'Reading NetCDF formatted input data file: '//trim(ncfilename), note)
655 call fms2_io_read_data (fileobj,
'nrecords', nrecords)
656 if (nrecords < 1)
call mpp_error(
'amip_interp_mod', &
657 'Invalid number of SST records in SST datafile: '//trim(ncfilename), fatal)
658 allocate(ryr(nrecords), rmo(nrecords), rdy(nrecords))
659 call fms2_io_read_data(fileobj,
'yr', ryr)
660 call fms2_io_read_data(fileobj,
'mo', rmo)
661 call fms2_io_read_data(fileobj,
'dy', rdy)
665 yr = ryr(k); mo = rmo(k)
666 adate = date_type( yr, mo, 0)
668 if (verbose > 2 .and.
mpp_pe() == 0) &
669 print *,
'....... checking ', adate
670 if (date == adate) ierr = 0
671 if (yr == 0 .and. mo == date%month) ierr = 0
674 if (ierr .ne. 0)
call mpp_error(
'amip_interp_mod', &
675 'Model time is out of range not in SST data: '//trim(ncfilename), fatal)
676 deallocate(ryr, rmo, rdy)
681 if (yr == 0 .or. mo == 0)
then
683 if (date_out_of_range ==
'fail' ) ierr = 1
684 if (date_out_of_range ==
'initclimo' .and. &
685 date > date_end ) ierr = 1
686 if (ierr /= 0)
call error_mesg &
687 (
'read_record in amip_interp_mod', &
688 'climo data read when NO climo data requested', fatal)
693 if ( interp_oi_sst )
then
694 call fms2_io_read_data(fileobj, ncfieldname, tmp_dat, unlim_dim_level=k)
696 if ( mobs/=360 .or. nobs/=180 )
then
697 call a2a_bilinear_ (360, 180, tmp_dat, mobs, nobs, dat)
699 dat(:,:) = tmp_dat(:,:)
702 call fms2_io_read_data(fileobj, ncfieldname, dat, unlim_dim_level=k)
707 idat = nint(dat*100._lkind, i2_kind)
711 if (
type(1:3) ==
'ice') then
713 if (lowercase(trim(data_set)) /=
'amip2' .and. lowercase(trim(data_set)) /=
'hurrell')
then
714 where ( idat <= ice_crit )
722 else if (
type(1:3) ==
'sst') then
724 if (lowercase(trim(data_set)) /=
'amip2' .and. lowercase(trim(data_set)) /=
'hurrell')
then
725 dat = real(idat, fms_amip_interp_kind_)*0.01_lkind + real(tfreeze, fms_amip_interp_kind_)
730 end subroutine read_record_
732 subroutine clip_data_ (type, dat)
733 character(len=*),
intent(in) :: type
734 real(FMS_AMIP_INTERP_KIND_),
intent(inout) :: dat(:,:)
735 integer,
parameter :: lkind = fms_amip_interp_kind_
737 if (
type(1:3) ==
'ice') then
738 dat = min(max(dat,0.0_lkind), 1.0_lkind)
739 else if (
type(1:3) ==
'sst') then
740 dat = max(real(tice_crit_k, fms_amip_interp_kind_),dat)
742 end subroutine clip_data_
744 subroutine zonal_sst_ (Time, ice, sst)
745 type (time_type),
intent(in) :: Time
746 real(FMS_AMIP_INTERP_KIND_),
intent(out) :: ice(mobs,nobs), sst(mobs,nobs)
747 real(FMS_AMIP_INTERP_KIND_) :: tpi, fdate, eps, ph, sph, sph2, ts
749 integer,
parameter :: lkind = fms_amip_interp_kind_
759 tpi = 2.0_lkind*real(pi, fms_amip_interp_kind_)
761 fdate = fraction_of_year(time)
763 eps = sin( tpi*(fdate-real(tlag, fms_amip_interp_kind_)) ) * real(tann, fms_amip_interp_kind_)
767 ph = 0.5_lkind * real(lat_bnd(j)+lat_bnd(j+1), fms_amip_interp_kind_)
771 ts = real(teq, fms_amip_interp_kind_) - real(tdif, fms_amip_interp_kind_)*sph2 - eps*sph
777 where ( sst < real(tice_crit_k, fms_amip_interp_kind_) )
779 sst = real(tice_crit_k, fms_amip_interp_kind_)
783 end subroutine zonal_sst_
integer function mpp_pe()
Returns processor ID.