source: LMDZ5/trunk/libf/dynphy_lonlat/phylmd/limit_netcdf.F90 @ 2942

Last change on this file since 2942 was 2942, checked in by dcugnet, 7 years ago

Remove test on sea ice concentration.

The aim of the test was to detect if a sea ice concentration field supposedly in
percents (holding the attribute "units" as correct) was in fact in area fraction.
But in some cases, all the fractions can be lower than one on the globe for
particular months, even if the field is really in percents.

  • Property copyright set to
    Name of program: LMDZ
    Creation date: 1984
    Version: LMDZ5
    License: CeCILL version 2
    Holder: Laboratoire de m\'et\'eorologie dynamique, CNRS, UMR 8539
    See the license file in the root directory
File size: 33.1 KB
RevLine 
[2336]1MODULE limit
[1687]2!
[2336]3!*******************************************************************************
4! Author : L. Fairhead, 27/01/94
[1687]5!-------------------------------------------------------------------------------
[2336]6! Purpose: Boundary conditions files building for new model using climatologies.
7!          Both grids have to be regular.
8!-------------------------------------------------------------------------------
9! Note: This routine is designed to work for Earth
10!-------------------------------------------------------------------------------
11! Modification history:
12!  * 23/03/1994: Z. X. Li
13!  *    09/1999: L. Fairhead (netcdf reading in LMDZ.3.3)
14!  *    07/2001: P. Le Van
15!  *    11/2009: L. Guez     (ozone day & night climatos, see etat0_netcdf.F90)
16!  *    12/2009: D. Cugnet   (f77->f90, calendars, files from coupled runs)
17!-------------------------------------------------------------------------------
18
[2766]19  USE ioipsl,             ONLY: flininfo, flinopen, flinget, flinclo
[2336]20  USE assert_eq_m,        ONLY: assert_eq
[2766]21  USE cal_tools_m,        ONLY: year_len, mid_month
[2336]22  USE conf_dat_m,         ONLY: conf_dat2d, conf_dat3d
23  USE dimphy,             ONLY: klon, zmasq
[2766]24  USE geometry_mod,       ONLY: longitude_deg, latitude_deg
[2399]25  USE phys_state_var_mod, ONLY: pctsrf
[2766]26  USE control_mod,        ONLY: anneeref
[2336]27  USE init_ssrf_m,        ONLY: start_init_subsurf
28
29  CHARACTER(LEN=20), PARAMETER :: &
[2889]30  fsst(5)=['amipbc_sst_1x1.nc   ','amip_sst_1x1.nc     ','cpl_atm_sst.nc      '&
31          ,'histmth_sst.nc      ','sstk.nc             ']
[2336]32  CHARACTER(LEN=20), PARAMETER :: &
[2889]33  fsic(5)=['amipbc_sic_1x1.nc   ','amip_sic_1x1.nc     ','cpl_atm_sic.nc      '&
34          ,'histmth_sic.nc      ','ci.nc               ']
[2336]35  CHARACTER(LEN=10), PARAMETER :: &
[2889]36  vsst(5)=['tosbcs    ','tos       ','SISUTESW  ','tsol_oce  ','sstk      '],  &
37  vsic(5)=['sicbcs    ','sic       ','SIICECOV  ','pourc_sic ','ci        ']
[2336]38  CHARACTER(LEN=10), PARAMETER :: &
39  frugo='Rugos.nc  ', falbe='Albedo.nc ', frelf='Relief.nc ',    &
40   vrug='RUGOS     ',  valb='ALBEDO    ',  vrel='RELIEF    '
41
42CONTAINS
43
44!-------------------------------------------------------------------------------
45!
46SUBROUTINE limit_netcdf(masque, phis, extrap)
47!
48!-------------------------------------------------------------------------------
[1687]49! Author : L. Fairhead, 27/01/94
50!-------------------------------------------------------------------------------
51! Purpose: Boundary conditions files building for new model using climatologies.
52!          Both grids have to be regular.
53!-------------------------------------------------------------------------------
54! Note: This routine is designed to work for Earth
55!-------------------------------------------------------------------------------
56! Modification history:
57!  * 23/03/1994: Z. X. Li
58!  *    09/1999: L. Fairhead (netcdf reading in LMDZ.3.3)
59!  *    07/2001: P. Le Van
60!  *    11/2009: L. Guez     (ozone day & night climatos, see etat0_netcdf.F90)
61!  *    12/2009: D. Cugnet   (f77->f90, calendars, files from coupled runs)
[2540]62!  *    04/2016: D. Cugnet   (12/14 recs SST/SIC files: cyclic/interannual runs)
[2889]63!  *    05/2017: D. Cugnet   (linear time interpolation for BCS files)
[1687]64!-------------------------------------------------------------------------------
[2293]65#ifndef CPP_1D
[1785]66  USE indice_sol_mod
[2336]67  USE netcdf,             ONLY: NF90_OPEN,    NF90_CREATE,  NF90_CLOSE,        &
68                  NF90_DEF_DIM, NF90_DEF_VAR, NF90_PUT_VAR, NF90_PUT_ATT,      &
69                  NF90_NOERR,   NF90_NOWRITE, NF90_DOUBLE,  NF90_GLOBAL,       &
[2603]70                  NF90_CLOBBER, NF90_ENDDEF,  NF90_UNLIMITED, NF90_FLOAT
[2336]71  USE inter_barxy_m,      ONLY: inter_barxy
72  USE netcdf95,           ONLY: nf95_def_var, nf95_put_att, nf95_put_var
[2597]73  USE comconst_mod, ONLY: pi
[2665]74  USE phys_cal_mod, ONLY: calend
[1687]75  IMPLICIT NONE
76!-------------------------------------------------------------------------------
77! Arguments:
[2336]78  include "iniprint.h"
[2293]79  include "dimensions.h"
80  include "paramet.h"
[2336]81  REAL, DIMENSION(iip1,jjp1), INTENT(INOUT) :: masque ! land mask
82  REAL, DIMENSION(iip1,jjp1), INTENT(INOUT) :: phis   ! ground geopotential
83  LOGICAL,                    INTENT(IN)    :: extrap ! SST extrapolation flag
[1687]84!-------------------------------------------------------------------------------
85! Local variables:
[2293]86  include "comgeom2.h"
[1687]87
88!--- INPUT NETCDF FILES NAMES --------------------------------------------------
[2293]89  CHARACTER(LEN=20) :: icefile, sstfile, dumstr, fnam
[1687]90  CHARACTER(LEN=10) :: varname
[2336]91
[1687]92!--- OUTPUT VARIABLES FOR NETCDF FILE ------------------------------------------
[2293]93  REAL               :: fi_ice(klon), verif(klon)
94  REAL, POINTER      :: phy_rug(:,:)=>NULL(), phy_ice(:,:)=>NULL()
95  REAL, POINTER      :: phy_sst(:,:)=>NULL(), phy_alb(:,:)=>NULL()
96  REAL, ALLOCATABLE  :: phy_bil(:,:), pctsrf_t(:,:,:)
97  INTEGER            :: nbad
[1687]98
99!--- VARIABLES FOR OUTPUT FILE WRITING -----------------------------------------
[2293]100  INTEGER :: ierr, nid, ndim, ntim, k, dims(2), ix_sic, ix_sst
[1687]101  INTEGER :: id_tim,  id_SST,  id_BILS, id_RUG, id_ALB
[2128]102  INTEGER :: id_FOCE, id_FSIC, id_FTER, id_FLIC, varid_longitude, varid_latitude
[1687]103  INTEGER :: NF90_FORMAT
104  INTEGER :: ndays                   !--- Depending on the output calendar
[2889]105  CHARACTER(LEN=256) :: str
[1687]106
107!--- INITIALIZATIONS -----------------------------------------------------------
108#ifdef NC_DOUBLE
109  NF90_FORMAT=NF90_DOUBLE
110#else
111  NF90_FORMAT=NF90_FLOAT
112#endif
113  CALL inigeom
114
[2336]115!--- MASK, GROUND GEOPOT. & SUBSURFACES COMPUTATION (IN CASE ok_etat0==.FALSE.)
116   IF(ALL(masque==-99999.)) THEN
117    CALL start_init_orog0(rlonv,rlatu,phis,masque)
118    CALL gr_dyn_fi(1,iip1,jjp1,klon,masque,zmasq)          !--- To physical grid
[2399]119    ALLOCATE(pctsrf(klon,nbsrf))
[2336]120    CALL start_init_subsurf(.FALSE.)
[2576]121  !--- TO MATCH EXACTLY WHAT WOULD BE DONE IN etat0phys_netcdf
122    WHERE(   masque(:,:)<EPSFRA) masque(:,:)=0.
123    WHERE(1.-masque(:,:)<EPSFRA) masque(:,:)=1.
[2336]124  END IF
125
[1687]126!--- Beware: anneeref (from gcm.def) is used to determine output time sampling
[2766]127  ndays=year_len(anneeref)
[1687]128
129!--- RUGOSITY TREATMENT --------------------------------------------------------
[2293]130  CALL msg(1,'Traitement de la rugosite')
[2336]131  CALL get_2Dfield(frugo,vrug,'RUG',ndays,phy_rug,mask=masque(1:iim,:))
[1687]132
133!--- OCEAN TREATMENT -----------------------------------------------------------
[2293]134  CALL msg(1,'Traitement de la glace oceanique')
[1687]135
136! Input SIC file selection
137! Open file only to test if available
[2293]138  DO ix_sic=1,SIZE(fsic)
139     IF ( NF90_OPEN(TRIM(fsic(ix_sic)),NF90_NOWRITE,nid)==NF90_NOERR ) THEN
140        icefile=fsic(ix_sic); varname=vsic(ix_sic); EXIT
141     END IF
142  END DO
143  IF(ix_sic==SIZE(fsic)+1) THEN
[1687]144     WRITE(lunout,*) 'ERROR! No sea-ice input file was found.'
[2293]145     WRITE(lunout,*) 'One of following files must be available : '
146     DO k=1,SIZE(fsic); WRITE(lunout,*) TRIM(fsic(k)); END DO
[2311]147     CALL abort_physic('limit_netcdf','No sea-ice file was found',1)
[1687]148  END IF
[2293]149  CALL ncerr(NF90_CLOSE(nid),icefile)
150  CALL msg(-1,'Fichier choisi pour la glace de mer:'//TRIM(icefile))
[1687]151
[2336]152  CALL get_2Dfield(icefile,varname, 'SIC',ndays,phy_ice)
[1687]153
154  ALLOCATE(pctsrf_t(klon,nbsrf,ndays))
155  DO k=1,ndays
156     fi_ice=phy_ice(:,k)
157     WHERE(fi_ice>=1.0  ) fi_ice=1.0
158     WHERE(fi_ice<EPSFRA) fi_ice=0.0
159     pctsrf_t(:,is_ter,k)=pctsrf(:,is_ter)       ! land soil
160     pctsrf_t(:,is_lic,k)=pctsrf(:,is_lic)       ! land ice
[2293]161     SELECT CASE(ix_sic)
[2889]162        CASE(3)                                   ! SIC=pICE*(1-LIC-TER) (CPL)
[1687]163        pctsrf_t(:,is_sic,k)=fi_ice(:)*(1.-pctsrf(:,is_lic)-pctsrf(:,is_ter))
[2889]164        CASE(4)                                   ! SIC=pICE            (HIST)
[1687]165        pctsrf_t(:,is_sic,k)=fi_ice(:)
[2293]166        CASE DEFAULT                              ! SIC=pICE-LIC   (AMIP,ERAI)
[1687]167        pctsrf_t(:,is_sic,k)=fi_ice-pctsrf_t(:,is_lic,k)
[2293]168     END SELECT
[1687]169     WHERE(pctsrf_t(:,is_sic,k)<=0) pctsrf_t(:,is_sic,k)=0.
170     WHERE(1.0-zmasq<EPSFRA)
171        pctsrf_t(:,is_sic,k)=0.0
172        pctsrf_t(:,is_oce,k)=0.0
173     ELSEWHERE
174        WHERE(pctsrf_t(:,is_sic,k)>=1.0-zmasq)
175           pctsrf_t(:,is_sic,k)=1.0-zmasq
176           pctsrf_t(:,is_oce,k)=0.0
177        ELSEWHERE
178           pctsrf_t(:,is_oce,k)=1.0-zmasq-pctsrf_t(:,is_sic,k)
179           WHERE(pctsrf_t(:,is_oce,k)<EPSFRA)
180              pctsrf_t(:,is_oce,k)=0.0
181              pctsrf_t(:,is_sic,k)=1.0-zmasq
182           END WHERE
183        END WHERE
184     END WHERE
185     nbad=COUNT(pctsrf_t(:,is_oce,k)<0.0)
[2293]186     IF(nbad>0) WRITE(lunout,*) 'pb sous maille pour nb points = ',nbad
187     nbad=COUNT(ABS(SUM(pctsrf_t(:,:,k),DIM=2)-1.0)>EPSFRA)
[1687]188     IF(nbad>0) WRITE(lunout,*) 'pb sous surface pour nb points = ',nbad
189  END DO
190  DEALLOCATE(phy_ice)
191
192!--- SST TREATMENT -------------------------------------------------------------
[2293]193  CALL msg(1,'Traitement de la sst')
[1687]194
195! Input SST file selection
196! Open file only to test if available
[2293]197  DO ix_sst=1,SIZE(fsst)
198     IF ( NF90_OPEN(TRIM(fsst(ix_sst)),NF90_NOWRITE,nid)==NF90_NOERR ) THEN
199       sstfile=fsst(ix_sst); varname=vsst(ix_sst); EXIT
200     END IF
201  END DO
202  IF(ix_sst==SIZE(fsst)+1) THEN
[1687]203     WRITE(lunout,*) 'ERROR! No sst input file was found.'
[2293]204     WRITE(lunout,*) 'One of following files must be available : '
205     DO k=1,SIZE(fsst); WRITE(lunout,*) TRIM(fsst(k)); END DO
[2311]206     CALL abort_physic('limit_netcdf','No sst file was found',1)
[1687]207  END IF
[2293]208  CALL ncerr(NF90_CLOSE(nid),sstfile)
209  CALL msg(-1,'Fichier choisi pour la temperature de mer: '//TRIM(sstfile))
[1687]210
[2336]211  CALL get_2Dfield(sstfile,varname,'SST',ndays,phy_sst,flag=extrap)
[1687]212
213!--- ALBEDO TREATMENT ----------------------------------------------------------
[2293]214  CALL msg(1,'Traitement de l albedo')
[2336]215  CALL get_2Dfield(falbe,valb,'ALB',ndays,phy_alb)
[1687]216
217!--- REFERENCE GROUND HEAT FLUX TREATMENT --------------------------------------
218  ALLOCATE(phy_bil(klon,ndays)); phy_bil=0.0
219
220!--- OUTPUT FILE WRITING -------------------------------------------------------
[2293]221  CALL msg(5,'Ecriture du fichier limit : debut')
222  fnam="limit.nc"
[1687]223
224  !--- File creation
[2293]225  CALL ncerr(NF90_CREATE(fnam,NF90_CLOBBER,nid),fnam)
226  CALL ncerr(NF90_PUT_ATT(nid,NF90_GLOBAL,"title","Fichier conditions aux limites"),fnam)
[2889]227  str='File produced using ce0l executable.'
228  str=TRIM(str)//NEW_LINE(' ')//'Sea Ice Concentration built from'
229  SELECT CASE(ix_sic)
230    CASE(1); str=TRIM(str)//' Amip mid-month boundary condition (BCS).'
231    CASE(2); str=TRIM(str)//' Amip monthly mean observations.'
232    CASE(3); str=TRIM(str)//' IPSL coupled model outputs.'
233    CASE(4); str=TRIM(str)//' LMDZ model outputs.'
234    CASE(5); str=TRIM(str)//' ci.nc file.'
235  END SELECT
236  str=TRIM(str)//NEW_LINE(' ')//'Sea Surface Temperature built from'
237  SELECT CASE(ix_sst)
238    CASE(1); str=TRIM(str)//' Amip mid-month boundary condition (BCS).'
239    CASE(2); str=TRIM(str)//' Amip monthly mean observations.'
240    CASE(3); str=TRIM(str)//' IPSL coupled model outputs.'
241    CASE(4); str=TRIM(str)//' LMDZ model outputs.'
242    CASE(5); str=TRIM(str)//' sstk.nc file.'
243  END SELECT
244  CALL ncerr(NF90_PUT_ATT(nid,NF90_GLOBAL,"history",TRIM(str)),fnam)
[1687]245
246  !--- Dimensions creation
[2293]247  CALL ncerr(NF90_DEF_DIM(nid,"points_physiques",klon,ndim),fnam)
248  CALL ncerr(NF90_DEF_DIM(nid,"time",NF90_UNLIMITED,ntim),fnam)
[1687]249
[2293]250  dims=[ndim,ntim]
[1687]251
252  !--- Variables creation
[2293]253  CALL ncerr(NF90_DEF_VAR(nid,"TEMPS",NF90_FORMAT,[ntim],id_tim),fnam)
254  CALL ncerr(NF90_DEF_VAR(nid,"FOCE", NF90_FORMAT,dims,id_FOCE),fnam)
255  CALL ncerr(NF90_DEF_VAR(nid,"FSIC", NF90_FORMAT,dims,id_FSIC),fnam)
256  CALL ncerr(NF90_DEF_VAR(nid,"FTER", NF90_FORMAT,dims,id_FTER),fnam)
257  CALL ncerr(NF90_DEF_VAR(nid,"FLIC", NF90_FORMAT,dims,id_FLIC),fnam)
258  CALL ncerr(NF90_DEF_VAR(nid,"SST",  NF90_FORMAT,dims,id_SST),fnam)
259  CALL ncerr(NF90_DEF_VAR(nid,"BILS", NF90_FORMAT,dims,id_BILS),fnam)
260  CALL ncerr(NF90_DEF_VAR(nid,"ALB",  NF90_FORMAT,dims,id_ALB),fnam)
261  CALL ncerr(NF90_DEF_VAR(nid,"RUG",  NF90_FORMAT,dims,id_RUG),fnam)
[2128]262  call nf95_def_var(nid, "longitude", NF90_FLOAT, ndim, varid_longitude)
[2293]263  call nf95_def_var(nid, "latitude",  NF90_FLOAT, ndim, varid_latitude)
[1687]264
265  !--- Attributes creation
[2293]266  CALL ncerr(NF90_PUT_ATT(nid,id_tim, "title","Jour dans l annee"),fnam)
[2665]267  CALL ncerr(NF90_PUT_ATT(nid,id_tim, "calendar",calend),fnam)
[2293]268  CALL ncerr(NF90_PUT_ATT(nid,id_FOCE,"title","Fraction ocean"),fnam)
269  CALL ncerr(NF90_PUT_ATT(nid,id_FSIC,"title","Fraction glace de mer"),fnam)
270  CALL ncerr(NF90_PUT_ATT(nid,id_FTER,"title","Fraction terre"),fnam)
271  CALL ncerr(NF90_PUT_ATT(nid,id_FLIC,"title","Fraction land ice"),fnam)
272  CALL ncerr(NF90_PUT_ATT(nid,id_SST ,"title","Temperature superficielle de la mer"),fnam)
273  CALL ncerr(NF90_PUT_ATT(nid,id_BILS,"title","Reference flux de chaleur au sol"),fnam)
274  CALL ncerr(NF90_PUT_ATT(nid,id_ALB, "title","Albedo a la surface"),fnam)
275  CALL ncerr(NF90_PUT_ATT(nid,id_RUG, "title","Rugosite"),fnam)
[1687]276
[2128]277  call nf95_put_att(nid, varid_longitude, "standard_name", "longitude")
278  call nf95_put_att(nid, varid_longitude, "units", "degrees_east")
279
280  call nf95_put_att(nid, varid_latitude, "standard_name", "latitude")
281  call nf95_put_att(nid, varid_latitude, "units", "degrees_north")
282
[2293]283  CALL ncerr(NF90_ENDDEF(nid),fnam)
[1687]284
285  !--- Variables saving
[2293]286  CALL ncerr(NF90_PUT_VAR(nid,id_tim,[(REAL(k),k=1,ndays)]),fnam)
287  CALL ncerr(NF90_PUT_VAR(nid,id_FOCE,pctsrf_t(:,is_oce,:),[1,1],[klon,ndays]),fnam)
288  CALL ncerr(NF90_PUT_VAR(nid,id_FSIC,pctsrf_t(:,is_sic,:),[1,1],[klon,ndays]),fnam)
289  CALL ncerr(NF90_PUT_VAR(nid,id_FTER,pctsrf_t(:,is_ter,:),[1,1],[klon,ndays]),fnam)
290  CALL ncerr(NF90_PUT_VAR(nid,id_FLIC,pctsrf_t(:,is_lic,:),[1,1],[klon,ndays]),fnam)
291  CALL ncerr(NF90_PUT_VAR(nid,id_SST ,phy_sst(:,:),[1,1],[klon,ndays]),fnam)
292  CALL ncerr(NF90_PUT_VAR(nid,id_BILS,phy_bil(:,:),[1,1],[klon,ndays]),fnam)
293  CALL ncerr(NF90_PUT_VAR(nid,id_ALB ,phy_alb(:,:),[1,1],[klon,ndays]),fnam)
294  CALL ncerr(NF90_PUT_VAR(nid,id_RUG ,phy_rug(:,:),[1,1],[klon,ndays]),fnam)
[2399]295  call nf95_put_var(nid, varid_longitude, longitude_deg)
296  call nf95_put_var(nid, varid_latitude, latitude_deg)
[1687]297
[2293]298  CALL ncerr(NF90_CLOSE(nid),fnam)
[1687]299
[2293]300  CALL msg(6,'Ecriture du fichier limit : fin')
[1687]301
302  DEALLOCATE(pctsrf_t,phy_sst,phy_bil,phy_alb,phy_rug)
303
304
305!===============================================================================
306!
307  CONTAINS
308!
309!===============================================================================
310
311
312!-------------------------------------------------------------------------------
313!
[2336]314SUBROUTINE get_2Dfield(fnam, varname, mode, ndays, champo, flag, mask)
[1687]315!
316!-----------------------------------------------------------------------------
317! Comments:
318!   There are two assumptions concerning the NetCDF files, that are satisfied
319!   with files that are conforming NC convention:
320!     1) The last dimension of the variables used is the time record.
321!     2) Dimensional variables have the same names as corresponding dimensions.
322!-----------------------------------------------------------------------------
323  USE netcdf, ONLY: NF90_OPEN, NF90_INQ_VARID, NF90_INQUIRE_VARIABLE, &
324       NF90_CLOSE, NF90_INQ_DIMID, NF90_INQUIRE_DIMENSION, NF90_GET_VAR, &
325       NF90_GET_ATT
[1785]326  USE pchsp_95_m, only: pchsp_95
327  USE pchfe_95_m, only: pchfe_95
328  USE arth_m, only: arth
329  USE indice_sol_mod
[1687]330
331  IMPLICIT NONE
[2293]332  include "dimensions.h"
333  include "paramet.h"
334  include "comgeom2.h"
[1687]335!-----------------------------------------------------------------------------
336! Arguments:
337  CHARACTER(LEN=*),  INTENT(IN)     :: fnam     ! NetCDF file name
338  CHARACTER(LEN=10), INTENT(IN)     :: varname  ! NetCDF variable name
339  CHARACTER(LEN=3),  INTENT(IN)     :: mode     ! RUG, SIC, SST or ALB
340  INTEGER,           INTENT(IN)     :: ndays    ! current year number of days
341  REAL,    POINTER,  DIMENSION(:, :) :: champo  ! output field = f(t)
342  LOGICAL, OPTIONAL, INTENT(IN)     :: flag     ! extrapol. (SST) old ice (SIC)
343  REAL,    OPTIONAL, DIMENSION(iim, jjp1), INTENT(IN) :: mask
344!------------------------------------------------------------------------------
345! Local variables:
346!--- NetCDF
[2293]347  INTEGER           :: ncid, varid        ! NetCDF identifiers
348  CHARACTER(LEN=30) :: dnam               ! dimension name
[1687]349!--- dimensions
[2293]350  INTEGER           :: dids(4)            ! NetCDF dimensions identifiers
351  REAL, ALLOCATABLE :: dlon_ini(:)        ! initial longitudes vector
352  REAL, ALLOCATABLE :: dlat_ini(:)        ! initial latitudes  vector
353  REAL, POINTER     :: dlon(:), dlat(:)   ! reordered lon/lat  vectors
[1687]354!--- fields
[2293]355  INTEGER :: imdep, jmdep, lmdep          ! dimensions of 'champ'
356  REAL, ALLOCATABLE :: champ(:,:)         ! wanted field on initial grid
357  REAL, ALLOCATABLE :: yder(:), timeyear(:)
358  REAL              :: champint(iim,jjp1) ! interpolated field
359  REAL, ALLOCATABLE :: champtime(:,:,:)
360  REAL, ALLOCATABLE :: champan(:,:,:)
[1687]361!--- input files
[2576]362  CHARACTER(LEN=20) :: fnam_m, fnam_p     ! previous/next files names
[2293]363  CHARACTER(LEN=20) :: cal_in             ! calendar
364  CHARACTER(LEN=20) :: unit_sic           ! attribute unit in sea-ice file
365  INTEGER           :: ndays_in           ! number of days
[1687]366!--- misc
[2540]367  INTEGER           :: i, j, k, l, ll     ! loop counters
[2293]368  REAL, ALLOCATABLE :: work(:,:)          ! used for extrapolation
[2540]369  CHARACTER(LEN=128):: title, mess        ! for messages
[2889]370  LOGICAL           :: is_bcs             ! flag for BCS data
[2293]371  LOGICAL           :: extrp              ! flag for extrapolation
[2889]372  REAL              :: chmin, chmax, timeday, al
[2576]373  INTEGER ierr, idx
[1687]374  integer n_extrap ! number of extrapolated points
375  logical skip
376
377!------------------------------------------------------------------------------
378!---Variables depending on keyword 'mode' -------------------------------------
379  NULLIFY(champo)
380
381  SELECT CASE(mode)
382  CASE('RUG'); title='Rugosite'
383  CASE('SIC'); title='Sea-ice'
384  CASE('SST'); title='SST'
385  CASE('ALB'); title='Albedo'
386  END SELECT
[2336]387  extrp=.FALSE.; IF(PRESENT(flag).AND.mode=='SST') extrp=flag
[2889]388  is_bcs=(mode=='SIC'.AND.ix_sic==1).OR.(mode=='SST'.AND.ix_sst==1)
[2576]389  idx=INDEX(fnam,'.nc')-1
[1687]390
391!--- GETTING SOME DIMENSIONAL VARIABLES FROM FILE -----------------------------
[2293]392  CALL msg(5,' Now reading file : '//TRIM(fnam))
393  CALL ncerr(NF90_OPEN(fnam, NF90_NOWRITE, ncid),fnam)
394  CALL ncerr(NF90_INQ_VARID(ncid, trim(varname), varid),fnam)
395  CALL ncerr(NF90_INQUIRE_VARIABLE(ncid, varid, dimids=dids),fnam)
[1687]396
397!--- Read unit for sea-ice variable only
398  IF (mode=='SIC') THEN
[2766]399    ierr=NF90_GET_ATT(ncid, varid, 'units', unit_sic); CALL strclean(unit_sic)
400    IF(ierr/=NF90_NOERR) THEN
[2293]401      CALL msg(5,'No unit in sea-ice file. Take percentage as default value')
402      unit_sic='X'
[2766]403    ELSE IF(ANY(["%  ","1.0","1  "]==unit_sic)) THEN
404      CALL msg(5,'Sea-ice cover has unit='//TRIM(unit_sic))
[2293]405    ELSE
[2766]406      CALL abort_physic('SIC','Unrecognized unit for sea-ice file: '&
407        //TRIM(unit_sic),1)
[2293]408    END IF
[1687]409  END IF
410
411!--- Longitude
[2293]412  CALL ncerr(NF90_INQUIRE_DIMENSION(ncid, dids(1), name=dnam, len=imdep),fnam)
413  ALLOCATE(dlon_ini(imdep), dlon(imdep))
414  CALL ncerr(NF90_INQ_VARID(ncid, dnam, varid), fnam)
415  CALL ncerr(NF90_GET_VAR(ncid, varid, dlon_ini), fnam)
416  CALL msg(5,'variable '//TRIM(dnam)//' dimension ', imdep)
[1687]417
418!--- Latitude
[2293]419  CALL ncerr(NF90_INQUIRE_DIMENSION(ncid, dids(2), name=dnam, len=jmdep),fnam)
420  ALLOCATE(dlat_ini(jmdep), dlat(jmdep))
421  CALL ncerr(NF90_INQ_VARID(ncid, dnam, varid), fnam)
422  CALL ncerr(NF90_GET_VAR(ncid, varid, dlat_ini), fnam)
423  CALL msg(5,'variable '//TRIM(dnam)//' dimension ', jmdep)
[1687]424
425!--- Time (variable is not needed - it is rebuilt - but calendar is)
[2293]426  CALL ncerr(NF90_INQUIRE_DIMENSION(ncid, dids(3), name=dnam, len=lmdep), fnam)
[2576]427  ALLOCATE(timeyear(lmdep+2))
[2293]428  CALL ncerr(NF90_INQ_VARID(ncid, dnam, varid), fnam)
[1687]429  cal_in=' '
[2293]430  IF(NF90_GET_ATT(ncid, varid, 'calendar', cal_in)/=NF90_NOERR) THEN
[1687]431    SELECT CASE(mode)
432      CASE('RUG', 'ALB'); cal_in='360d'
433      CASE('SIC', 'SST'); cal_in='gregorian'
434    END SELECT
[2665]435    CALL msg(5,'WARNING: missing "calendar" attribute for "time" in '&
[2293]436     &//TRIM(fnam)//'. Choosing default value.')
[1687]437  END IF
[2665]438  CALL strclean(cal_in)                     !--- REMOVE (WEIRD) NULL CHARACTERS
[2293]439  CALL msg(5,'var, calendar, dim: '//TRIM(dnam)//' '//TRIM(cal_in), lmdep)
[1687]440 
[2540]441!--- Determining input file number of days, depending on calendar
[1687]442  ndays_in=year_len(anneeref, cal_in)
443
[2540]444!--- Rebuilding input time vector (field from input file might be unreliable)
445  IF(lmdep==12) THEN
[2766]446    timeyear=mid_month(anneeref, cal_in)
[2576]447    CALL msg(0,'Monthly input file(s) for '//TRIM(title)//'.')
[2540]448  ELSE IF(lmdep==ndays_in) THEN
[2576]449    timeyear=[(REAL(k)-0.5,k=0,ndays_in+1)]
[2540]450    CALL msg(0,'Daily input file (no time interpolation).')
451  ELSE
452    WRITE(mess,'(a,i3,a,i3,a)')'Mismatching input file: found',lmdep,        &
[2576]453      ' records, 12/',ndays_in,' (monthly/daily needed).'
[2766]454    CALL abort_physic('mid_month',TRIM(mess),1)
[2540]455  END IF
[1687]456
457!--- GETTING THE FIELD AND INTERPOLATING IT ----------------------------------
[2576]458  ALLOCATE(champ(imdep, jmdep), champtime(iim, jjp1, lmdep+2))
[1687]459  IF(extrp) ALLOCATE(work(imdep, jmdep))
[2293]460  CALL msg(5,'')
[2766]461  CALL msg(5,'READ AND INTERPOLATE HORIZONTALLY ', lmdep, ' FIELDS.')
[2293]462  CALL ncerr(NF90_INQ_VARID(ncid, varname, varid), fnam)
[1687]463  DO l=1, lmdep
[2293]464    CALL ncerr(NF90_GET_VAR(ncid,varid,champ,[1,1,l],[imdep,jmdep,1]),fnam)
[2766]465    !--- Check whether values are acceptable for SIC, depending on unit.
[2889]466    !--- Dropped for mid-month boundary conditions datasets (BCS, ix_sic==1)
467    IF(mode=='SIC'.AND.ix_sic/=1) THEN
[2766]468      IF(TRIM(unit_sic)=="1".OR.TRIM(unit_sic)=="1.0") THEN
469        IF(ANY(champ>1.0+EPSFRA)) &
470          CALL abort_physic('SIC','Found sea-ice fractions greater than 1.')
471      ELSE IF(TRIM(unit_sic)=="X".OR.TRIM(unit_sic)=="%") THEN
[2889]472        IF(ANY(champ>100.0+EPSFRA)) &
473          CALL abort_physic('SIC','Found sea-ice percentages greater than 100.')
[2942]474!        IF(MAXVAL(champ)< 1.01) &
475!          CALL abort_physic('SIC','All sea-ice percentages lower than 1.')
[2766]476      END IF
477    END IF
[2336]478    CALL conf_dat2d(title, dlon_ini, dlat_ini, dlon, dlat, champ, .TRUE.)
[2293]479    IF(extrp) CALL extrapol(champ,imdep,jmdep,999999.,.TRUE.,.TRUE.,2,work)
[2336]480    IF(l==1) THEN
[2293]481      CALL msg(5,"----------------------------------------------------------")
[2766]482      CALL msg(5,"$$$ Barycentrique interpolation for "//TRIM(title)//" $$$")
[2293]483      CALL msg(5,"----------------------------------------------------------")
[1687]484    END IF
[2336]485    IF(mode=='RUG') champ=LOG(champ)
486    CALL inter_barxy(dlon,dlat(:jmdep-1),champ,rlonu(:iim),rlatv,champint)
487    IF(mode=='RUG') THEN
488      champint=EXP(champint)
489      WHERE(NINT(mask)/=1) champint=0.001
490    END IF
[2576]491    champtime(:, :, l+1)=champint
[1687]492  END DO
[2293]493  CALL ncerr(NF90_CLOSE(ncid), fnam)
[1687]494
[2576]495!--- FIRST RECORD: LAST ONE OF PREVIOUS YEAR (CURRENT YEAR IF UNAVAILABLE)
496  fnam_m=fnam(1:idx)//'_m.nc'
497  IF(NF90_OPEN(fnam_m,NF90_NOWRITE,ncid)==NF90_NOERR) THEN
498    CALL msg(0,'Reading previous year file ("'//TRIM(fnam_m)//'") last record for '//TRIM(title))
499    CALL ncerr(NF90_INQ_VARID(ncid, varname, varid),fnam_m)
500    CALL ncerr(NF90_INQUIRE_VARIABLE(ncid, varid, dimids=dids),fnam_m)
501    CALL ncerr(NF90_INQUIRE_DIMENSION(ncid, dids(3), len=l), fnam_m)
502    CALL ncerr(NF90_GET_VAR(ncid,varid,champ,[1,1,l],[imdep,jmdep,1]),fnam_m)
503    CALL ncerr(NF90_CLOSE(ncid), fnam_m)
504    CALL conf_dat2d(title, dlon_ini, dlat_ini, dlon, dlat, champ, .TRUE.)
505    IF(extrp) CALL extrapol(champ,imdep,jmdep,999999.,.TRUE.,.TRUE.,2,work)
506    IF(mode=='RUG') champ=LOG(champ)
507    CALL inter_barxy(dlon,dlat(:jmdep-1),champ,rlonu(:iim),rlatv,champint)
508    IF(mode=='RUG') THEN
509      champint=EXP(champint)
510      WHERE(NINT(mask)/=1) champint=0.001
511    END IF
512    champtime(:, :, 1)=champint
513  ELSE
514    CALL msg(0,'Using current year file ("'//TRIM(fnam)//'") last record for '//TRIM(title))
515    champtime(:, :, 1)=champtime(:, :, lmdep+1)
516  END IF
517
518!--- LAST RECORD: FIRST ONE OF NEXT YEAR (CURRENT YEAR IF UNAVAILABLE)
519  fnam_p=fnam(1:idx)//'_p.nc'
520  IF(NF90_OPEN(fnam_p,NF90_NOWRITE,ncid)==NF90_NOERR) THEN
[2665]521    CALL msg(0,'Reading next year file ("'//TRIM(fnam_p)//'") first record for '//TRIM(title))
[2576]522    CALL ncerr(NF90_INQ_VARID(ncid, varname, varid),fnam_p)
523    CALL ncerr(NF90_GET_VAR(ncid,varid,champ,[1,1,1],[imdep,jmdep,1]),fnam_p)
524    CALL ncerr(NF90_CLOSE(ncid), fnam_p)
525    CALL conf_dat2d(title, dlon_ini, dlat_ini, dlon, dlat, champ, .TRUE.)
526    IF(extrp) CALL extrapol(champ,imdep,jmdep,999999.,.TRUE.,.TRUE.,2,work)
527    IF(mode=='RUG') champ=LOG(champ)
528    CALL inter_barxy(dlon,dlat(:jmdep-1),champ,rlonu(:iim),rlatv,champint)
529    IF(mode=='RUG') THEN
530      champint=EXP(champint)
531      WHERE(NINT(mask)/=1) champint=0.001
532    END IF
533    champtime(:, :, lmdep+2)=champint
534  ELSE
535    CALL msg(0,'Using current year file ("'//TRIM(fnam)//'") first record for '//TRIM(title))
536    champtime(:, :, lmdep+2)=champtime(:, :, 2)
537  END IF
[1687]538  DEALLOCATE(dlon_ini, dlat_ini, dlon, dlat, champ)
539  IF(extrp) DEALLOCATE(work)
540
541!--- TIME INTERPOLATION ------------------------------------------------------
[2540]542  IF(prt_level>0) THEN
543     IF(ndays/=ndays_in) THEN
544        WRITE(lunout, *)
[2766]545        WRITE(lunout,*)'DIFFERENT YEAR LENGTHS:'
546        WRITE(lunout,*)' In the input file: ',ndays_in
547        WRITE(lunout,*)' In the output file: ',ndays
[2540]548     END IF
549     IF(lmdep==ndays_in) THEN
550        WRITE(lunout, *)
[2766]551        WRITE(lunout, *)'NO TIME INTERPOLATION.'
552        WRITE(lunout, *)' Daily input file.'
[2540]553     ELSE
[2889]554        IF(     is_bcs) WRITE(lunout, *)'LINEAR TIME INTERPOLATION.'
555        IF(.NOT.is_bcs) WRITE(lunout, *)'SPLINES TIME INTERPOLATION.'
[2766]556        WRITE(lunout, *)' Input time vector: ', timeyear
557        WRITE(lunout, *)' Output time vector from 0 to ', ndays-1
[2540]558     END IF
[1687]559  END IF
[2889]560  ALLOCATE(champan(iip1, jjp1, ndays))
561
562  IF(lmdep==ndays_in) THEN  !--- DAILY DATA: NO     TIME INTERPOLATION
[2540]563     champan(1:iim,:,:)=champtime
[2889]564  ELSE IF(is_bcs) THEN      !--- BCS   DATA: LINEAR TIME INTERPOLATION
565    l=1
566    DO k=1, ndays
[2893]567      timeday = (REAL(k)-0.5)*REAL(ndays_in)/ndays
[2889]568      IF(timeyear(l+1)<timeday) l=l+1
569      al=(timeday-timeyear(l))/(timeyear(l+1)-timeyear(l))
570      DO j=1, jjp1
571        DO i=1, iim
572          champan(i,j,k) = champtime(i,j,l)+al*(champtime(i,j,l+1)-champtime(i,j,l))
573        END DO
574      END DO
575    END DO
576  ELSE                      !--- AVE   DATA: SPLINE TIME INTERPOLATION
[2540]577     skip = .false.
578     n_extrap = 0
[2889]579     ALLOCATE(yder(lmdep+2))
[2540]580     DO j=1, jjp1
581       DO i=1, iim
582         yder = pchsp_95(timeyear, champtime(i, j, :), ibeg=2, iend=2, &
583              vc_beg=0., vc_end=0.)
584         CALL pchfe_95(timeyear, champtime(i, j, :), yder, skip, &
[2893]585              arth(0.5, real(ndays_in) / ndays, ndays), champan(i, j, :), ierr)
[2540]586         if (ierr < 0) stop 1
587         n_extrap = n_extrap + ierr
588       END DO
589     END DO
590     IF(n_extrap /= 0) WRITE(lunout,*) "get_2Dfield pchfe_95: n_extrap = ", n_extrap
[2889]591     DEALLOCATE(yder)
[2540]592  END IF
[1687]593  champan(iip1, :, :)=champan(1, :, :)
[2889]594  DEALLOCATE(champtime, timeyear)
[1687]595
596!--- Checking the result
597  DO j=1, jjp1
598    CALL minmax(iip1, champan(1, j, 10), chmin, chmax)
[2766]599    IF (prt_level>5) WRITE(lunout, *)' ',TRIM(title),' at time 10 ', chmin, chmax, j
[1687]600  END DO
601
602!--- SPECIAL FILTER FOR SST: SST>271.38 --------------------------------------
603  IF(mode=='SST') THEN
[2766]604    CALL msg(0,'Filtering SST: SST >= 271.38')
[1687]605    WHERE(champan<271.38) champan=271.38
606  END IF
607
608!--- SPECIAL FILTER FOR SIC: 0.0<SIC<1.0 -------------------------------------
609  IF(mode=='SIC') THEN
[2766]610    CALL msg(0,'Filtering SIC: 0.0 < Sea-ice < 1.0')
611    IF(TRIM(unit_sic)=="1".OR.TRIM(unit_sic)=="1.0") THEN
[1687]612       ! Nothing to be done for sea-ice field is already in fraction of 1
613       ! This is the case for sea-ice in file cpl_atm_sic.nc
[2766]614       CALL msg(0,'Sea-ice field already in fraction of 1')
[1687]615    ELSE
616       ! Convert sea ice from percentage to fraction of 1
[2766]617       CALL msg(0,'Sea-ice field converted from percentage to fraction of 1.')
[1687]618       champan(:, :, :)=champan(:, :, :)/100.
619    END IF
620    champan(iip1, :, :)=champan(1, :, :)
621    WHERE(champan>1.0) champan=1.0
622    WHERE(champan<0.0) champan=0.0
623 END IF
624
625!--- DYNAMICAL TO PHYSICAL GRID ----------------------------------------------
626  ALLOCATE(champo(klon, ndays))
627  DO k=1, ndays
628    CALL gr_dyn_fi(1, iip1, jjp1, klon, champan(1, 1, k), champo(1, k))
629  END DO
630  DEALLOCATE(champan)
631
632END SUBROUTINE get_2Dfield
633!
634!-------------------------------------------------------------------------------
635
636
637!-------------------------------------------------------------------------------
638!
[2336]639SUBROUTINE start_init_orog0(lon_in,lat_in,phis,masque)
640!
641!-------------------------------------------------------------------------------
[2576]642  USE grid_noro_m, ONLY: grid_noro0
[2336]643  IMPLICIT NONE
644!===============================================================================
645! Purpose:  Compute "phis" just like it would be in start_init_orog.
646!===============================================================================
647! Arguments:
648  REAL,             INTENT(IN)    :: lon_in(:), lat_in(:)   ! dim (iml) (jml)
649  REAL,             INTENT(INOUT) :: phis(:,:), masque(:,:) ! dim (iml,jml)
650!-------------------------------------------------------------------------------
651! Local variables:
652  CHARACTER(LEN=256) :: modname="start_init_orog0"
653  INTEGER            :: fid, llm_tmp,ttm_tmp, iml,jml, iml_rel,jml_rel, itau(1)
654  REAL               :: lev(1), date, dt, deg2rad
655  REAL, ALLOCATABLE  :: lon_rad(:), lon_ini(:), lon_rel(:,:), relief_hi(:,:)
656  REAL, ALLOCATABLE  :: lat_rad(:), lat_ini(:), lat_rel(:,:)
657!-------------------------------------------------------------------------------
658  iml=assert_eq(SIZE(lon_in),SIZE(phis,1),SIZE(masque,1),TRIM(modname)//" iml")
659  jml=assert_eq(SIZE(lat_in),SIZE(phis,2),SIZE(masque,2),TRIM(modname)//" jml")
660  IF(iml/=iip1) CALL abort_gcm(TRIM(modname),'iml/=iip1',1)
661  IF(jml/=jjp1) CALL abort_gcm(TRIM(modname),'jml/=jjp1',1)
662  pi=2.0*ASIN(1.0); deg2rad=pi/180.0
663  IF(ANY(phis/=-99999.)) RETURN                  !--- phis ALREADY KNOWN
664
665!--- HIGH RESOLUTION OROGRAPHY
666  CALL flininfo(frelf, iml_rel, jml_rel, llm_tmp, ttm_tmp, fid)
667
668  ALLOCATE(lat_rel(iml_rel,jml_rel),lon_rel(iml_rel,jml_rel))
669  CALL flinopen(frelf, .FALSE., iml_rel, jml_rel, llm_tmp, lon_rel, lat_rel,   &
670                lev, ttm_tmp, itau, date, dt, fid)
671  ALLOCATE(relief_hi(iml_rel,jml_rel))
672  CALL flinget(fid, vrel, iml_rel, jml_rel, llm_tmp, ttm_tmp, 1, 1, relief_hi)
673  CALL flinclo(fid)
674
675!--- IF ANGLES ARE IN DEGREES, THEY ARE CONVERTED INTO RADIANS
676  ALLOCATE(lon_ini(iml_rel),lat_ini(jml_rel))
677  lon_ini(:)=lon_rel(:,1); IF(MAXVAL(lon_rel)>pi) lon_ini=lon_ini*deg2rad
678  lat_ini(:)=lat_rel(1,:); IF(MAXVAL(lat_rel)>pi) lat_ini=lat_ini*deg2rad
679
680!--- FIELDS ARE PROCESSED TO BE ON STANDARD ANGULAR DOMAINS
681  ALLOCATE(lon_rad(iml_rel),lat_rad(jml_rel))
682  CALL conf_dat2d(vrel, lon_ini, lat_ini, lon_rad, lat_rad, relief_hi, .FALSE.)
683  DEALLOCATE(lon_ini,lat_ini)
684
685!--- COMPUTING SURFACE GEOPOTENTIAL USING ROUTINE grid_noro0
686  WRITE(lunout,*)
687  WRITE(lunout,*)'*** Compute surface geopotential ***'
688
689!--- CALL OROGRAPHY MODULE (REDUCED VERSION) TO COMPUTE FIELDS
690  CALL grid_noro0(lon_rad, lat_rad, relief_hi, lon_in, lat_in, phis, masque)
691  phis = phis * 9.81
692  phis(iml,:) = phis(1,:)
693  DEALLOCATE(relief_hi,lon_rad,lat_rad)
694
695END SUBROUTINE start_init_orog0
696!
697!-------------------------------------------------------------------------------
698
699
700!-------------------------------------------------------------------------------
701!
[2293]702SUBROUTINE msg(lev,str1,i,str2)
703!
704!-------------------------------------------------------------------------------
705! Arguments:
706  INTEGER,                    INTENT(IN) :: lev
707  CHARACTER(LEN=*),           INTENT(IN) :: str1
708  INTEGER,          OPTIONAL, INTENT(IN) :: i
709  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: str2
710!-------------------------------------------------------------------------------
711  IF(prt_level>lev) THEN
712    IF(PRESENT(str2)) THEN
713      WRITE(lunout,*) TRIM(str1), i, TRIM(str2)
714    ELSE IF(PRESENT(i)) THEN
715      WRITE(lunout,*) TRIM(str1), i
716    ELSE
717      WRITE(lunout,*) TRIM(str1)
718    END IF
719  END IF
720
721END SUBROUTINE msg
722!
723!-------------------------------------------------------------------------------
724
725
726!-------------------------------------------------------------------------------
727!
[1687]728SUBROUTINE ncerr(ncres,fnam)
729!
730!-------------------------------------------------------------------------------
731! Purpose: NetCDF errors handling.
732!-------------------------------------------------------------------------------
733  USE netcdf, ONLY : NF90_NOERR, NF90_STRERROR
734  IMPLICIT NONE
735!-------------------------------------------------------------------------------
736! Arguments:
737  INTEGER,          INTENT(IN) :: ncres
738  CHARACTER(LEN=*), INTENT(IN) :: fnam
739!-------------------------------------------------------------------------------
740  IF(ncres/=NF90_NOERR) THEN
741    WRITE(lunout,*)'Problem with file '//TRIM(fnam)//' in routine limit_netcdf.'
[2311]742    CALL abort_physic('limit_netcdf',NF90_STRERROR(ncres),1)
[1687]743  END IF
744
745END SUBROUTINE ncerr
746!
747!-------------------------------------------------------------------------------
748
[2665]749
750!-------------------------------------------------------------------------------
751!
752SUBROUTINE strclean(s)
753!
754!-------------------------------------------------------------------------------
755  IMPLICIT NONE
756!-------------------------------------------------------------------------------
757! Purpose: Remove tail null characters from the input string.
758!-------------------------------------------------------------------------------
759! Parameters:
760  CHARACTER(LEN=*), INTENT(INOUT) :: s
761!-------------------------------------------------------------------------------
762! Local variable:
763  INTEGER :: k
764!-------------------------------------------------------------------------------
765  k=LEN_TRIM(s); DO WHILE(ICHAR(s(k:k))==0); s(k:k)=' '; k=LEN_TRIM(s); END DO
766
767END SUBROUTINE strclean
768!
769!-------------------------------------------------------------------------------
770
[1687]771#endif
[2239]772! of #ifndef CPP_1D
[1687]773END SUBROUTINE limit_netcdf
[2336]774
775END MODULE limit
776!
777!*******************************************************************************
[2540]778
Note: See TracBrowser for help on using the repository browser.