25 USE ioipsl
, ONLY : ioget_year_len
27 USE netcdf
, ONLY : NF90_OPEN, NF90_CREATE, NF90_CLOSE, &
28 nf90_def_dim, nf90_def_var, nf90_put_var, nf90_put_att, &
29 nf90_noerr, nf90_nowrite, nf90_double, nf90_global, &
30 nf90_clobber, nf90_enddef, nf90_unlimited, nf90_float
36 #include "dimensions.h"
39 LOGICAL,
INTENT(IN) :: interbar
40 LOGICAL,
INTENT(IN) :: extrap
41 LOGICAL,
INTENT(IN) :: oldice
42 REAL,
DIMENSION(iip1,jjp1),
INTENT(IN) :: masque
44 CALL
abort_gcm(
'limit_netcdf',
'Earth-specific routine, needs Earth physics',1)
52 #include "indicesol.h"
55 CHARACTER(LEN=25) :: icefile, sstfile, dumstr
56 CHARACTER(LEN=25),
PARAMETER :: famipsst=
'amipbc_sst_1x1.nc ', &
57 famipsic=
'amipbc_sic_1x1.nc ', &
58 fcpldsst=
'cpl_atm_sst.nc ', &
59 fcpldsic=
'cpl_atm_sic.nc ', &
60 fhistsst=
'histmth_sst.nc ', &
61 fhistsic=
'histmth_sic.nc ', &
64 CHARACTER(LEN=10) :: varname
66 REAL,
DIMENSION(klon) :: fi_ice, verif
67 REAL,
DIMENSION(:,:),
POINTER :: phy_rug=>null(), phy_ice=>null()
68 REAL,
DIMENSION(:,:),
POINTER :: phy_sst=>null(), phy_alb=>null()
69 REAL,
DIMENSION(:,:),
ALLOCATABLE :: phy_bil
70 REAL,
DIMENSION(:,:,:),
ALLOCATABLE :: pctsrf_t
74 INTEGER :: ierr, nid, ndim, ntim,
k
75 INTEGER,
DIMENSION(2) :: dims
76 INTEGER :: id_tim, id_sst, id_bils, id_rug, id_alb
77 INTEGER :: id_foce, id_fsic, id_fter, id_flic
78 INTEGER :: nf90_format
83 nf90_format=nf90_double
85 nf90_format=nf90_float
99 ndays=ioget_year_len(anneeref)
104 CALL get_2dfield(frugo,varname,
'RUG',interbar,ndays,phy_rug,mask=masque(1:
iim,:))
111 IF ( nf90_open(trim(famipsic),nf90_nowrite,nid)==nf90_noerr )
THEN
112 icefile=trim(famipsic)
114 ELSE IF( nf90_open(trim(fcpldsic),nf90_nowrite,nid)==nf90_noerr )
THEN
115 icefile=trim(fcpldsic)
117 ELSE IF ( nf90_open(trim(fhistsic),nf90_nowrite,nid)==nf90_noerr )
THEN
118 icefile=trim(fhistsic)
121 WRITE(
lunout,*)
'ERROR! No sea-ice input file was found.'
122 WRITE(
lunout,*)
'One of following files must be availible : ',trim(famipsic),
', ',trim(fcpldsic),
', ',trim(fhistsic)
123 CALL
abort_gcm(
'limit_netcdf',
'No sea-ice file was found',1)
126 IF (
prt_level>=0)
WRITE(
lunout,*)
'Pour la glace de mer a ete choisi le fichier '//trim(icefile)
128 CALL get_2dfield(icefile,varname,
'SIC',interbar,ndays,phy_ice,flag=oldice)
130 ALLOCATE(pctsrf_t(klon,nbsrf,ndays))
133 WHERE(fi_ice>=1.0 ) fi_ice=1.0
134 WHERE(fi_ice<epsfra) fi_ice=0.0
135 pctsrf_t(:,is_ter,
k)=pctsrf(:,is_ter)
136 pctsrf_t(:,is_lic,
k)=pctsrf(:,is_lic)
137 IF (icefile==trim(fcpldsic))
THEN
138 pctsrf_t(:,is_sic,
k)=fi_ice(:)*(1.-pctsrf(:,is_lic)-pctsrf(:,is_ter))
139 ELSE IF (icefile==trim(fhistsic))
THEN
140 pctsrf_t(:,is_sic,
k)=fi_ice(:)
142 pctsrf_t(:,is_sic,
k)=fi_ice-pctsrf_t(:,is_lic,
k)
144 WHERE(pctsrf_t(:,is_sic,
k)<=0) pctsrf_t(:,is_sic,
k)=0.
145 WHERE(1.0-zmasq<epsfra)
146 pctsrf_t(:,is_sic,
k)=0.0
147 pctsrf_t(:,is_oce,
k)=0.0
149 WHERE(pctsrf_t(:,is_sic,
k)>=1.0-zmasq)
150 pctsrf_t(:,is_sic,
k)=1.0-zmasq
151 pctsrf_t(:,is_oce,
k)=0.0
153 pctsrf_t(:,is_oce,
k)=1.0-zmasq-pctsrf_t(:,is_sic,
k)
154 WHERE(pctsrf_t(:,is_oce,
k)<epsfra)
155 pctsrf_t(:,is_oce,
k)=0.0
156 pctsrf_t(:,is_sic,
k)=1.0-zmasq
160 nbad=count(pctsrf_t(:,is_oce,
k)<0.0)
161 IF(nbad>0)
WRITE(
lunout,*)
'pb sous maille pour nb point = ',nbad
162 nbad=count(abs(sum(pctsrf_t(:,:,
k),dim=2)-1.0)>epsfra)
163 IF(nbad>0)
WRITE(
lunout,*)
'pb sous surface pour nb points = ',nbad
172 IF ( nf90_open(trim(famipsst),nf90_nowrite,nid)==nf90_noerr )
THEN
173 sstfile=trim(famipsst)
175 ELSE IF ( nf90_open(trim(fcpldsst),nf90_nowrite,nid)==nf90_noerr )
THEN
176 sstfile=trim(fcpldsst)
178 ELSE IF ( nf90_open(trim(fhistsst),nf90_nowrite,nid)==nf90_noerr )
THEN
179 sstfile=trim(fhistsst)
182 WRITE(
lunout,*)
'ERROR! No sst input file was found.'
183 WRITE(
lunout,*)
'One of following files must be availible : ',trim(famipsst),trim(fcpldsst),trim(fhistsst)
184 CALL
abort_gcm(
'limit_netcdf',
'No sst file was found',1)
187 IF (
prt_level>=0)
WRITE(
lunout,*)
'Pour la temperature de mer a ete choisi un fichier '//trim(sstfile)
189 CALL get_2dfield(sstfile,varname,
'SST',interbar,ndays,phy_sst,flag=extrap)
194 CALL get_2dfield(falbe,varname,
'ALB',interbar,ndays,phy_alb)
197 ALLOCATE(phy_bil(klon,ndays)); phy_bil=0.0
203 ierr=nf90_create(
"limit.nc",nf90_clobber,nid)
204 ierr=nf90_put_att(nid,nf90_global,
"title",
"Fichier conditions aux limites")
207 ierr=nf90_def_dim(nid,
"points_physiques",klon,ndim)
208 ierr=nf90_def_dim(nid,
"time",nf90_unlimited,ntim)
213 ierr=nf90_def_var(nid,
"TEMPS",nf90_format,(/ntim/),id_tim)
214 ierr=nf90_def_var(nid,
"FOCE", nf90_format,dims,id_foce)
215 ierr=nf90_def_var(nid,
"FSIC", nf90_format,dims,id_fsic)
216 ierr=nf90_def_var(nid,
"FTER", nf90_format,dims,id_fter)
217 ierr=nf90_def_var(nid,
"FLIC", nf90_format,dims,id_flic)
218 ierr=nf90_def_var(nid,
"SST", nf90_format,dims,id_sst)
219 ierr=nf90_def_var(nid,
"BILS", nf90_format,dims,id_bils)
220 ierr=nf90_def_var(nid,
"ALB", nf90_format,dims,id_alb)
221 ierr=nf90_def_var(nid,
"RUG", nf90_format,dims,id_rug)
224 ierr=nf90_put_att(nid,id_tim,
"title",
"Jour dans l annee")
225 ierr=nf90_put_att(nid,id_foce,
"title",
"Fraction ocean")
226 ierr=nf90_put_att(nid,id_fsic,
"title",
"Fraction glace de mer")
227 ierr=nf90_put_att(nid,id_fter,
"title",
"Fraction terre")
228 ierr=nf90_put_att(nid,id_flic,
"title",
"Fraction land ice")
229 ierr=nf90_put_att(nid,id_sst ,
"title",
"Temperature superficielle de la mer")
230 ierr=nf90_put_att(nid,id_bils,
"title",
"Reference flux de chaleur au sol")
231 ierr=nf90_put_att(nid,id_alb,
"title",
"Albedo a la surface")
232 ierr=nf90_put_att(nid,id_rug,
"title",
"Rugosite")
234 ierr=nf90_enddef(nid)
237 ierr=nf90_put_var(nid,id_tim,(/(
REAL(k),
k=1,ndays)/))
238 ierr=nf90_put_var(nid,id_foce,pctsrf_t(:,is_oce,:),(/1,1/),(/klon,ndays/))
239 ierr=nf90_put_var(nid,id_fsic,pctsrf_t(:,is_sic,:),(/1,1/),(/klon,ndays/))
240 ierr=nf90_put_var(nid,id_fter,pctsrf_t(:,is_ter,:),(/1,1/),(/klon,ndays/))
241 ierr=nf90_put_var(nid,id_flic,pctsrf_t(:,is_lic,:),(/1,1/),(/klon,ndays/))
242 ierr=nf90_put_var(nid,id_sst ,phy_sst(:,:),(/1,1/),(/klon,ndays/))
243 ierr=nf90_put_var(nid,id_bils,phy_bil(:,:),(/1,1/),(/klon,ndays/))
244 ierr=nf90_put_var(nid,id_alb ,phy_alb(:,:),(/1,1/),(/klon,ndays/))
245 ierr=nf90_put_var(nid,id_rug ,phy_rug(:,:),(/1,1/),(/klon,ndays/))
251 DEALLOCATE(pctsrf_t,phy_sst,phy_bil,phy_alb,phy_rug)
263 SUBROUTINE get_2dfield(fnam, varname, mode, ibar, ndays, champo, flag, mask)
272 USE netcdf
, ONLY: NF90_OPEN, NF90_INQ_VARID, NF90_INQUIRE_VARIABLE, &
273 nf90_close, nf90_inq_dimid, nf90_inquire_dimension, nf90_get_var, &
283 #include "dimensions.h"
285 #include "comgeom2.h"
286 #include "indicesol.h"
287 #include "iniprint.h"
290 CHARACTER(LEN=*),
INTENT(IN) :: fnam
291 CHARACTER(LEN=10),
INTENT(IN) :: varname
292 CHARACTER(LEN=3),
INTENT(IN) :: mode
293 LOGICAL,
INTENT(IN) :: ibar
294 INTEGER,
INTENT(IN) :: ndays
295 REAL,
POINTER,
DIMENSION(:, :) :: champo
296 LOGICAL,
OPTIONAL,
INTENT(IN) :: flag
297 REAL,
OPTIONAL,
DIMENSION(iim, jjp1),
INTENT(IN) :: mask
301 INTEGER :: ncid, varid
302 CHARACTER(LEN=30) :: dnam
304 INTEGER,
DIMENSION(4) :: dids
305 REAL,
ALLOCATABLE,
DIMENSION(:) :: dlon_ini
306 REAL,
ALLOCATABLE,
DIMENSION(:) :: dlat_ini
307 REAL,
POINTER,
DIMENSION(:) :: dlon, dlat
309 INTEGER :: imdep, jmdep, lmdep
310 REAL,
ALLOCATABLE,
DIMENSION(:, :) :: champ
311 REAL,
ALLOCATABLE,
DIMENSION(:) :: yder, timeyear
312 REAL,
DIMENSION(iim, jjp1) :: champint
313 REAL,
ALLOCATABLE,
DIMENSION(:, :, :) :: champtime
314 REAL,
ALLOCATABLE,
DIMENSION(:, :, :) :: champan
316 CHARACTER(LEN=20) :: cal_in
317 CHARACTER(LEN=20) :: unit_sic
320 INTEGER ::
i,
j,
k,
l
321 REAL,
ALLOCATABLE,
DIMENSION(:, :) :: work
322 CHARACTER(LEN=25) ::
title
335 CASE(
'RUG');
title=
'Rugosite'
336 CASE(
'SIC');
title=
'Sea-ice'
337 CASE(
'SST');
title=
'SST'
338 CASE(
'ALB');
title=
'Albedo'
344 IF ( present(flag) )
THEN
345 IF ( flag .AND. mode==
'SST' ) extrp=.true.
346 IF ( flag .AND. mode==
'SIC' ) oldice=.true.
351 ierr=nf90_open(fnam, nf90_nowrite, ncid); CALL ncerr(ierr, fnam)
352 ierr=nf90_inq_varid(ncid, trim(varname), varid); CALL ncerr(ierr, fnam)
353 ierr=nf90_inquire_variable(ncid, varid, dimids=dids); CALL ncerr(ierr, fnam)
356 IF (mode==
'SIC')
THEN
357 ierr=nf90_get_att(ncid, varid,
'units', unit_sic)
358 IF(ierr/=nf90_noerr)
THEN
359 IF (
prt_level>5)
WRITE(
lunout,*)
'No unit was given in sea-ice file. Take percentage as default value'
367 ierr=nf90_inquire_dimension(ncid, dids(1), name=dnam, len=imdep)
368 CALL ncerr(ierr, fnam);
ALLOCATE(dlon_ini(imdep), dlon(imdep))
369 ierr=nf90_inq_varid(ncid, dnam, varid); CALL ncerr(ierr, fnam)
370 ierr=nf90_get_var(ncid, varid, dlon_ini); CALL ncerr(ierr, fnam)
371 IF (
prt_level>5)
WRITE(
lunout, *)
'variable ', dnam,
'dimension ', imdep
374 ierr=nf90_inquire_dimension(ncid, dids(2), name=dnam, len=jmdep)
375 CALL ncerr(ierr, fnam);
ALLOCATE(dlat_ini(jmdep), dlat(jmdep))
376 ierr=nf90_inq_varid(ncid, dnam, varid); CALL ncerr(ierr, fnam)
377 ierr=nf90_get_var(ncid, varid, dlat_ini); CALL ncerr(ierr, fnam)
378 IF (
prt_level>5)
WRITE(
lunout, *)
'variable ', dnam,
'dimension ', jmdep
381 ierr=nf90_inquire_dimension(ncid, dids(3), name=dnam, len=lmdep)
382 CALL ncerr(ierr, fnam);
ALLOCATE(timeyear(lmdep))
383 ierr=nf90_inq_varid(ncid, dnam, varid); CALL ncerr(ierr, fnam)
385 ierr=nf90_get_att(ncid, varid,
'calendar', cal_in)
386 IF(ierr/=nf90_noerr)
THEN
388 CASE(
'RUG',
'ALB'); cal_in=
'360d'
389 CASE(
'SIC',
'SST'); cal_in=
'gregorian'
391 IF (
prt_level>5)
WRITE(
lunout, *)
'ATTENTION: variable "time" sans attribut "calendrier" ' &
392 //
'dans '//trim(fnam)//
'. On choisit la valeur par defaut.'
394 IF (
prt_level>5)
WRITE(
lunout, *)
'variable ', dnam,
'dimension ', lmdep,
'calendrier ', &
400 ndays_in=year_len(anneeref, cal_in)
404 timeyear=mid_months(anneeref, cal_in, lmdep)
405 IF (lmdep /= 12)
WRITE(
lunout,*)
'Note : les fichiers de ', trim(mode), &
406 ' ne comportent pas 12, mais ', lmdep,
' enregistrements.'
409 ALLOCATE(champ(imdep, jmdep), champtime(
iim,
jjp1, lmdep))
410 IF(extrp)
ALLOCATE(work(imdep, jmdep))
413 IF (
prt_level>5)
WRITE(
lunout,*)
'LECTURE ET INTERPOLATION HORIZ. DE ', lmdep,
' CHAMPS.'
414 ierr=nf90_inq_varid(ncid, varname, varid); CALL ncerr(ierr, fnam)
416 ierr=nf90_get_var(ncid, varid, champ, (/1, 1,
l/), (/imdep, jmdep, 1/))
417 CALL ncerr(ierr, fnam)
421 IF (extrp) CALL
extrapol(champ, imdep, jmdep, 999999., .true., .true., 2, &
424 IF(ibar .AND. .NOT.oldice)
THEN
426 WRITE(
lunout, *)
'-------------------------------------------------------------------------'
427 WRITE(
lunout, *)
'Utilisation de l''interpolation barycentrique pour ',trim(
title),
' $$$'
428 WRITE(
lunout, *)
'-------------------------------------------------------------------------'
430 IF(mode==
'RUG') champ=log(champ)
434 champint=exp(champint)
435 WHERE(nint(mask)/=1) champint=0.001
439 CASE(
'RUG'); CALL
rugosite(imdep, jmdep, dlon, dlat, champ, &
441 CASE(
'SIC'); CALL
sea_ice(imdep, jmdep, dlon, dlat, champ, &
443 CASE(
'SST',
'ALB'); CALL
grille_m(imdep, jmdep, dlon, dlat, champ, &
447 champtime(:, :,
l)=champint
449 ierr=nf90_close(ncid); CALL ncerr(ierr, fnam)
451 DEALLOCATE(dlon_ini, dlat_ini, dlon, dlat, champ)
452 IF(extrp)
DEALLOCATE(work)
457 WRITE(
lunout, *)
'INTERPOLATION TEMPORELLE.'
458 WRITE(
lunout, *)
' Vecteur temps en entree: ', timeyear
459 WRITE(
lunout, *)
' Vecteur temps en sortie de 0 a ', ndays
462 ALLOCATE(yder(lmdep), champan(iip1,
jjp1, ndays))
467 yder =
pchsp_95(timeyear, champtime(
i,
j, :), ibeg=2, iend=2, &
468 vc_beg=0., vc_end=0.)
469 CALL
pchfe_95(timeyear, champtime(
i,
j, :), yder, skip, &
470 arth(0.,
real(ndays_in) / ndays, ndays), champan(
i,
j, :), ierr)
472 n_extrap = n_extrap + ierr
475 if (n_extrap /= 0)
then
476 WRITE(
lunout,*)
"get_2Dfield pchfe_95: n_extrap = ", n_extrap
478 champan(iip1, :, :)=champan(1, :, :)
479 DEALLOCATE(yder, champtime, timeyear)
483 CALL
minmax(iip1, champan(1,
j, 10), chmin, chmax)
490 WHERE(champan<271.38) champan=271.38
495 IF (
prt_level>5)
WRITE(
lunout, *)
'Filtrage de la SIC: 0.0 < Sea-ice < 1.0'
497 IF (unit_sic==
'1')
THEN
500 IF (
prt_level>5)
WRITE(
lunout,*)
'Sea-ice field already in fraction of 1'
503 IF (
prt_level>5)
WRITE(
lunout,*)
'Transformt sea-ice field from percentage to fraction of 1.'
504 champan(:, :, :)=champan(:, :, :)/100.
507 champan(iip1, :, :)=champan(1, :, :)
508 WHERE(champan>1.0) champan=1.0
509 WHERE(champan<0.0) champan=0.0
513 ALLOCATE(champo(klon, ndays))
519 END SUBROUTINE get_2dfield
527 FUNCTION year_len(y,cal_in)
530 USE ioipsl
, ONLY : ioget_calendar,ioconf_calendar,lock_calendar,ioget_year_len
535 INTEGER,
INTENT(IN) :: y
536 CHARACTER(LEN=*),
INTENT(IN) :: cal_in
539 CHARACTER(LEN=20) :: cal_out
542 CALL ioget_calendar(cal_out)
545 CALL lock_calendar(.
false.); CALL ioconf_calendar(trim(cal_in))
548 year_len=ioget_year_len(y)
551 CALL lock_calendar(.
false.); CALL ioconf_calendar(trim(cal_out))
553 END FUNCTION year_len
560 FUNCTION mid_months(y,cal_in,nm)
563 USE ioipsl
, ONLY : ioget_calendar,ioconf_calendar,lock_calendar,ioget_mon_len
567 INTEGER,
INTENT(IN) :: y
568 CHARACTER(LEN=*),
INTENT(IN) :: cal_in
569 INTEGER,
INTENT(IN) :: nm
570 REAL,
DIMENSION(nm) :: mid_months
573 CHARACTER(LEN=99) :: mess
574 CHARACTER(LEN=20) :: cal_out
575 INTEGER,
DIMENSION(nm) :: mnth
579 nd=year_len(y,cal_in)
584 CALL ioget_calendar(cal_out)
587 CALL lock_calendar(.
false.); CALL ioconf_calendar(trim(cal_in))
590 DO m=1,nm; mnth(
m)=ioget_mon_len(y,
m);
END DO
593 CALL lock_calendar(.
false.); CALL ioconf_calendar(trim(cal_out))
595 ELSE IF(modulo(nd,nm)/=0)
THEN
596 WRITE(mess,
'(a,i3,a,i3,a)')
'Unconsistent calendar: ',nd,
' days/year, but ',&
597 nm,
' months/year. Months number should divide days number.'
598 CALL
abort_gcm(
'mid_months',trim(mess),1)
601 mnth=(/(
m,
m=1,nm,nd/nm)/)
605 mid_months(1)=0.5*
REAL(mnth(1))
607 mid_months(
k)=mid_months(
k-1)+0.5*
REAL(mnth(
k-1)+mnth(
k))
610 END FUNCTION mid_months
617 SUBROUTINE ncerr(ncres,fnam)
622 USE netcdf
, ONLY : NF90_NOERR, NF90_STRERROR
626 INTEGER,
INTENT(IN) :: ncres
627 CHARACTER(LEN=*),
INTENT(IN) :: fnam
629 #include "iniprint.h"
630 IF(ncres/=nf90_noerr)
THEN
631 WRITE(
lunout,*)
'Problem with file '//trim(fnam)//
' in routine limit_netcdf.'
632 CALL
abort_gcm(
'limit_netcdf',nf90_strerror(ncres),1)