source: LMDZ5/trunk/libf/phylmd/limit_netcdf.F90 @ 2293

Last change on this file since 2293 was 2293, checked in by dcugnet, 9 years ago

Initial states creation routines have been reorganized and simplified.
As far as possible, dynamics and physics related routines have been
separated.
Some routines have been converted to fortran 90 and repeated codes sections
have been "factorized".
Array/vector arguments have become implicit in some routines to avoid usage
of "dimensions.h" ; possible for routines with explicit interfaces and if
iim and jjm can be deduced from arguments sizes.

  • dynlonlat_phylonlat/ce0l.F90 calls now phylmd/etat0phys_netcdf.F90 and dyn3d/etat0dyn_netcdf.F90 that replace phylmd/etat0_netcdf.F90. start.nc and startphy.nc creations are now independant.
  • startvar.F90 has been suppressed ; corresponding operations have been simplified and embedded in etat0*_netcdf.F90 routines as internal procedures.
  • Routines converted to fortran 90 and "factorized":
    • dyn3d_common/conf_dat_m.F90 (replaces dyn3d_common/conf_dat2d.F

and dyn3d_common/conf_dat3d.F)

  • dyn3d/dynredem.F90 (replaces dyn3d/dynredem.F)
  • dyn3d/dynetat0.F90 (replaces dyn3d/dynetat0.F)
  • phylmd/grid_noro_m.F90 (replaces dyn3d_common/grid_noro.F)
  • dynlonlat_phylonlat/grid_atob_m.F90 (replaces dyn3d_common/grid_atob.F)
  • dyn3d_common/caldyn0.F90 (replaces dyn3d_common/caldyn0.F)
  • dyn3d_common/covcont.F90 (replaces dyn3d_common/covcont.F)
  • dyn3d_common/pression.F90 (replaces dyn3d_common/pression.F)
  • phylmd/phyredem.F90 and phylmd/limit_netcdf.F90 have been slightly factorized.

TO DO:

  • little fix needed in grid_noro_m.F90 ; untouched yet to ensure results are exactly the same as before. Unsmoothed orography is used to compute "zphi", but smoothed (should be unsmoothed) one is used at poles.
  • add the dyn3dmem versions of dynredem.F90 and dynetat0.F90 (dynredem_loc.F90 and dynetat0_loc.F90, untested yet).
  • test compilation in parallel mode for a single processor.
  • 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: 26.4 KB
Line 
1SUBROUTINE limit_netcdf(interbar, extrap, oldice, masque)
2!
3!-------------------------------------------------------------------------------
4! Author : L. Fairhead, 27/01/94
5!-------------------------------------------------------------------------------
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#ifndef CPP_1D
19  USE control_mod
20  USE indice_sol_mod
21#ifdef CPP_EARTH
22  USE dimphy
23  USE ioipsl,             ONLY : ioget_year_len
24  USE phys_state_var_mod, ONLY : pctsrf, rlon, rlat
25  USE netcdf,             ONLY : NF90_OPEN,    NF90_CREATE,  NF90_CLOSE,       &
26                   NF90_DEF_DIM, NF90_DEF_VAR, NF90_PUT_VAR, NF90_PUT_ATT,     &
27                   NF90_NOERR,   NF90_NOWRITE, NF90_DOUBLE,  NF90_GLOBAL,      &
28                   NF90_CLOBBER, NF90_ENDDEF,  NF90_UNLIMITED, NF90_FLOAT
29  USE inter_barxy_m, only: inter_barxy
30  USE netcdf95,    ONLY: nf95_def_var, nf95_put_att, nf95_put_var
31  USE grid_atob_m, ONLY: grille_m, rugosite, sea_ice
32#endif
33  IMPLICIT NONE
34!-------------------------------------------------------------------------------
35! Arguments:
36  include "dimensions.h"
37  include "paramet.h"
38  include "iniprint.h"
39  LOGICAL,                    INTENT(IN) :: interbar ! barycentric interpolation
40  LOGICAL,                    INTENT(IN) :: extrap   ! SST extrapolation flag
41  LOGICAL,                    INTENT(IN) :: oldice   ! old way ice computation
42  REAL, DIMENSION(iip1,jjp1), INTENT(IN) :: masque   ! land mask
43#ifndef CPP_EARTH
44  CALL abort_gcm('limit_netcdf','Earth-specific routine, needs Earth physics',1)
45#else
46!-------------------------------------------------------------------------------
47! Local variables:
48  include "logic.h"
49  include "comvert.h"
50  include "comgeom2.h"
51  include "comconst.h"
52
53!--- INPUT NETCDF FILES NAMES --------------------------------------------------
54  CHARACTER(LEN=20) :: icefile, sstfile, dumstr, fnam
55  CHARACTER(LEN=20), PARAMETER :: &
56  fsst(4)=['amipbc_sst_1x1.nc   ','cpl_atm_sst.nc      ','histmth_sst.nc      '&
57          ,'sstk.nc             ']
58  CHARACTER(LEN=20), PARAMETER :: &
59  fsic(4)=['amipbc_sic_1x1.nc   ','cpl_atm_sic.nc      ','histmth_sic.nc      '&
60          ,'ci.nc               ']
61  CHARACTER(LEN=10), PARAMETER :: &
62  vsst(4)=['tosbcs    ','SISUTESW  ','tsol_oce  ','sstk      '], &
63  vsic(4)=['sicbcs    ','SIICECOV  ','pourc_sic ','ci        ']
64  CHARACTER(LEN=20), PARAMETER :: frugo='Rugos.nc            ',                &
65                                  falbe='Albedo.nc           '
66  CHARACTER(LEN=10), PARAMETER :: vrug='RUGOS     ', valb='ALBEDO    '
67  CHARACTER(LEN=10) :: varname
68!--- OUTPUT VARIABLES FOR NETCDF FILE ------------------------------------------
69  REAL               :: fi_ice(klon), verif(klon)
70  REAL, POINTER      :: phy_rug(:,:)=>NULL(), phy_ice(:,:)=>NULL()
71  REAL, POINTER      :: phy_sst(:,:)=>NULL(), phy_alb(:,:)=>NULL()
72  REAL, ALLOCATABLE  :: phy_bil(:,:), pctsrf_t(:,:,:)
73  INTEGER            :: nbad
74
75!--- VARIABLES FOR OUTPUT FILE WRITING -----------------------------------------
76  INTEGER :: ierr, nid, ndim, ntim, k, dims(2), ix_sic, ix_sst
77  INTEGER :: id_tim,  id_SST,  id_BILS, id_RUG, id_ALB
78  INTEGER :: id_FOCE, id_FSIC, id_FTER, id_FLIC, varid_longitude, varid_latitude
79  INTEGER :: NF90_FORMAT
80  INTEGER :: ndays                   !--- Depending on the output calendar
81
82!--- INITIALIZATIONS -----------------------------------------------------------
83#ifdef NC_DOUBLE
84  NF90_FORMAT=NF90_DOUBLE
85#else
86  NF90_FORMAT=NF90_FLOAT
87#endif
88  CALL inigeom
89
90!--- Beware: anneeref (from gcm.def) is used to determine output time sampling
91  ndays=ioget_year_len(anneeref)
92
93!--- RUGOSITY TREATMENT --------------------------------------------------------
94  CALL msg(1,'Traitement de la rugosite')
95  CALL get_2Dfield(frugo,vrug,'RUG',interbar,ndays,phy_rug,mask=masque(1:iim,:))
96
97!--- OCEAN TREATMENT -----------------------------------------------------------
98  CALL msg(1,'Traitement de la glace oceanique')
99
100! Input SIC file selection
101! Open file only to test if available
102  DO ix_sic=1,SIZE(fsic)
103     IF ( NF90_OPEN(TRIM(fsic(ix_sic)),NF90_NOWRITE,nid)==NF90_NOERR ) THEN
104        icefile=fsic(ix_sic); varname=vsic(ix_sic); EXIT
105     END IF
106  END DO
107  IF(ix_sic==SIZE(fsic)+1) THEN
108     WRITE(lunout,*) 'ERROR! No sea-ice input file was found.'
109     WRITE(lunout,*) 'One of following files must be available : '
110     DO k=1,SIZE(fsic); WRITE(lunout,*) TRIM(fsic(k)); END DO
111     CALL abort_gcm('limit_netcdf','No sea-ice file was found',1)
112  END IF
113  CALL ncerr(NF90_CLOSE(nid),icefile)
114  CALL msg(-1,'Fichier choisi pour la glace de mer:'//TRIM(icefile))
115
116  CALL get_2Dfield(icefile,varname, 'SIC',interbar,ndays,phy_ice,flag=oldice)
117
118  ALLOCATE(pctsrf_t(klon,nbsrf,ndays))
119  DO k=1,ndays
120     fi_ice=phy_ice(:,k)
121     WHERE(fi_ice>=1.0  ) fi_ice=1.0
122     WHERE(fi_ice<EPSFRA) fi_ice=0.0
123     pctsrf_t(:,is_ter,k)=pctsrf(:,is_ter)       ! land soil
124     pctsrf_t(:,is_lic,k)=pctsrf(:,is_lic)       ! land ice
125     SELECT CASE(ix_sic)
126        CASE(2)                                   ! SIC=pICE*(1-LIC-TER) (CPL)
127        pctsrf_t(:,is_sic,k)=fi_ice(:)*(1.-pctsrf(:,is_lic)-pctsrf(:,is_ter))
128        CASE(3)                                   ! SIC=pICE            (HIST)
129        pctsrf_t(:,is_sic,k)=fi_ice(:)
130        CASE DEFAULT                              ! SIC=pICE-LIC   (AMIP,ERAI)
131        pctsrf_t(:,is_sic,k)=fi_ice-pctsrf_t(:,is_lic,k)
132     END SELECT
133     WHERE(pctsrf_t(:,is_sic,k)<=0) pctsrf_t(:,is_sic,k)=0.
134     WHERE(1.0-zmasq<EPSFRA)
135        pctsrf_t(:,is_sic,k)=0.0
136        pctsrf_t(:,is_oce,k)=0.0
137     ELSEWHERE
138        WHERE(pctsrf_t(:,is_sic,k)>=1.0-zmasq)
139           pctsrf_t(:,is_sic,k)=1.0-zmasq
140           pctsrf_t(:,is_oce,k)=0.0
141        ELSEWHERE
142           pctsrf_t(:,is_oce,k)=1.0-zmasq-pctsrf_t(:,is_sic,k)
143           WHERE(pctsrf_t(:,is_oce,k)<EPSFRA)
144              pctsrf_t(:,is_oce,k)=0.0
145              pctsrf_t(:,is_sic,k)=1.0-zmasq
146           END WHERE
147        END WHERE
148     END WHERE
149     nbad=COUNT(pctsrf_t(:,is_oce,k)<0.0)
150     IF(nbad>0) WRITE(lunout,*) 'pb sous maille pour nb points = ',nbad
151     nbad=COUNT(ABS(SUM(pctsrf_t(:,:,k),DIM=2)-1.0)>EPSFRA)
152     IF(nbad>0) WRITE(lunout,*) 'pb sous surface pour nb points = ',nbad
153  END DO
154  DEALLOCATE(phy_ice)
155
156!--- SST TREATMENT -------------------------------------------------------------
157  CALL msg(1,'Traitement de la sst')
158
159! Input SST file selection
160! Open file only to test if available
161  DO ix_sst=1,SIZE(fsst)
162     IF ( NF90_OPEN(TRIM(fsst(ix_sst)),NF90_NOWRITE,nid)==NF90_NOERR ) THEN
163       sstfile=fsst(ix_sst); varname=vsst(ix_sst); EXIT
164     END IF
165  END DO
166  IF(ix_sst==SIZE(fsst)+1) THEN
167     WRITE(lunout,*) 'ERROR! No sst input file was found.'
168     WRITE(lunout,*) 'One of following files must be available : '
169     DO k=1,SIZE(fsst); WRITE(lunout,*) TRIM(fsst(k)); END DO
170     CALL abort_gcm('limit_netcdf','No sst file was found',1)
171  END IF
172  CALL ncerr(NF90_CLOSE(nid),sstfile)
173  CALL msg(-1,'Fichier choisi pour la temperature de mer: '//TRIM(sstfile))
174
175  CALL get_2Dfield(sstfile,varname,'SST',interbar,ndays,phy_sst,flag=extrap)
176
177!--- ALBEDO TREATMENT ----------------------------------------------------------
178  CALL msg(1,'Traitement de l albedo')
179  CALL get_2Dfield(falbe,valb,'ALB',interbar,ndays,phy_alb)
180
181!--- REFERENCE GROUND HEAT FLUX TREATMENT --------------------------------------
182  ALLOCATE(phy_bil(klon,ndays)); phy_bil=0.0
183
184!--- OUTPUT FILE WRITING -------------------------------------------------------
185  CALL msg(5,'Ecriture du fichier limit : debut')
186  fnam="limit.nc"
187
188  !--- File creation
189  CALL ncerr(NF90_CREATE(fnam,NF90_CLOBBER,nid),fnam)
190  CALL ncerr(NF90_PUT_ATT(nid,NF90_GLOBAL,"title","Fichier conditions aux limites"),fnam)
191
192  !--- Dimensions creation
193  CALL ncerr(NF90_DEF_DIM(nid,"points_physiques",klon,ndim),fnam)
194  CALL ncerr(NF90_DEF_DIM(nid,"time",NF90_UNLIMITED,ntim),fnam)
195
196  dims=[ndim,ntim]
197
198  !--- Variables creation
199  CALL ncerr(NF90_DEF_VAR(nid,"TEMPS",NF90_FORMAT,[ntim],id_tim),fnam)
200  CALL ncerr(NF90_DEF_VAR(nid,"FOCE", NF90_FORMAT,dims,id_FOCE),fnam)
201  CALL ncerr(NF90_DEF_VAR(nid,"FSIC", NF90_FORMAT,dims,id_FSIC),fnam)
202  CALL ncerr(NF90_DEF_VAR(nid,"FTER", NF90_FORMAT,dims,id_FTER),fnam)
203  CALL ncerr(NF90_DEF_VAR(nid,"FLIC", NF90_FORMAT,dims,id_FLIC),fnam)
204  CALL ncerr(NF90_DEF_VAR(nid,"SST",  NF90_FORMAT,dims,id_SST),fnam)
205  CALL ncerr(NF90_DEF_VAR(nid,"BILS", NF90_FORMAT,dims,id_BILS),fnam)
206  CALL ncerr(NF90_DEF_VAR(nid,"ALB",  NF90_FORMAT,dims,id_ALB),fnam)
207  CALL ncerr(NF90_DEF_VAR(nid,"RUG",  NF90_FORMAT,dims,id_RUG),fnam)
208  call nf95_def_var(nid, "longitude", NF90_FLOAT, ndim, varid_longitude)
209  call nf95_def_var(nid, "latitude",  NF90_FLOAT, ndim, varid_latitude)
210
211  !--- Attributes creation
212  CALL ncerr(NF90_PUT_ATT(nid,id_tim, "title","Jour dans l annee"),fnam)
213  CALL ncerr(NF90_PUT_ATT(nid,id_FOCE,"title","Fraction ocean"),fnam)
214  CALL ncerr(NF90_PUT_ATT(nid,id_FSIC,"title","Fraction glace de mer"),fnam)
215  CALL ncerr(NF90_PUT_ATT(nid,id_FTER,"title","Fraction terre"),fnam)
216  CALL ncerr(NF90_PUT_ATT(nid,id_FLIC,"title","Fraction land ice"),fnam)
217  CALL ncerr(NF90_PUT_ATT(nid,id_SST ,"title","Temperature superficielle de la mer"),fnam)
218  CALL ncerr(NF90_PUT_ATT(nid,id_BILS,"title","Reference flux de chaleur au sol"),fnam)
219  CALL ncerr(NF90_PUT_ATT(nid,id_ALB, "title","Albedo a la surface"),fnam)
220  CALL ncerr(NF90_PUT_ATT(nid,id_RUG, "title","Rugosite"),fnam)
221
222  call nf95_put_att(nid, varid_longitude, "standard_name", "longitude")
223  call nf95_put_att(nid, varid_longitude, "units", "degrees_east")
224
225  call nf95_put_att(nid, varid_latitude, "standard_name", "latitude")
226  call nf95_put_att(nid, varid_latitude, "units", "degrees_north")
227
228  CALL ncerr(NF90_ENDDEF(nid),fnam)
229
230  !--- Variables saving
231  CALL ncerr(NF90_PUT_VAR(nid,id_tim,[(REAL(k),k=1,ndays)]),fnam)
232  CALL ncerr(NF90_PUT_VAR(nid,id_FOCE,pctsrf_t(:,is_oce,:),[1,1],[klon,ndays]),fnam)
233  CALL ncerr(NF90_PUT_VAR(nid,id_FSIC,pctsrf_t(:,is_sic,:),[1,1],[klon,ndays]),fnam)
234  CALL ncerr(NF90_PUT_VAR(nid,id_FTER,pctsrf_t(:,is_ter,:),[1,1],[klon,ndays]),fnam)
235  CALL ncerr(NF90_PUT_VAR(nid,id_FLIC,pctsrf_t(:,is_lic,:),[1,1],[klon,ndays]),fnam)
236  CALL ncerr(NF90_PUT_VAR(nid,id_SST ,phy_sst(:,:),[1,1],[klon,ndays]),fnam)
237  CALL ncerr(NF90_PUT_VAR(nid,id_BILS,phy_bil(:,:),[1,1],[klon,ndays]),fnam)
238  CALL ncerr(NF90_PUT_VAR(nid,id_ALB ,phy_alb(:,:),[1,1],[klon,ndays]),fnam)
239  CALL ncerr(NF90_PUT_VAR(nid,id_RUG ,phy_rug(:,:),[1,1],[klon,ndays]),fnam)
240  call nf95_put_var(nid, varid_longitude, rlon)
241  call nf95_put_var(nid, varid_latitude, rlat)
242
243  CALL ncerr(NF90_CLOSE(nid),fnam)
244
245  CALL msg(6,'Ecriture du fichier limit : fin')
246
247  DEALLOCATE(pctsrf_t,phy_sst,phy_bil,phy_alb,phy_rug)
248
249
250!===============================================================================
251!
252  CONTAINS
253!
254!===============================================================================
255
256
257!-------------------------------------------------------------------------------
258!
259SUBROUTINE get_2Dfield(fnam, varname, mode, ibar, ndays, champo, flag, mask)
260!
261!-----------------------------------------------------------------------------
262! Comments:
263!   There are two assumptions concerning the NetCDF files, that are satisfied
264!   with files that are conforming NC convention:
265!     1) The last dimension of the variables used is the time record.
266!     2) Dimensional variables have the same names as corresponding dimensions.
267!-----------------------------------------------------------------------------
268  USE netcdf, ONLY: NF90_OPEN, NF90_INQ_VARID, NF90_INQUIRE_VARIABLE, &
269       NF90_CLOSE, NF90_INQ_DIMID, NF90_INQUIRE_DIMENSION, NF90_GET_VAR, &
270       NF90_GET_ATT
271  USE dimphy, ONLY : klon
272  USE phys_state_var_mod, ONLY : pctsrf
273  USE conf_dat_m, ONLY: conf_dat2d
274  USE control_mod
275  USE pchsp_95_m, only: pchsp_95
276  USE pchfe_95_m, only: pchfe_95
277  USE arth_m, only: arth
278  USE indice_sol_mod
279
280  IMPLICIT NONE
281  include "dimensions.h"
282  include "paramet.h"
283  include "comgeom2.h"
284  include "iniprint.h"
285!-----------------------------------------------------------------------------
286! Arguments:
287  CHARACTER(LEN=*),  INTENT(IN)     :: fnam     ! NetCDF file name
288  CHARACTER(LEN=10), INTENT(IN)     :: varname  ! NetCDF variable name
289  CHARACTER(LEN=3),  INTENT(IN)     :: mode     ! RUG, SIC, SST or ALB
290  LOGICAL,           INTENT(IN)     :: ibar     ! interp on pressure levels
291  INTEGER,           INTENT(IN)     :: ndays    ! current year number of days
292  REAL,    POINTER,  DIMENSION(:, :) :: champo  ! output field = f(t)
293  LOGICAL, OPTIONAL, INTENT(IN)     :: flag     ! extrapol. (SST) old ice (SIC)
294  REAL,    OPTIONAL, DIMENSION(iim, jjp1), INTENT(IN) :: mask
295!------------------------------------------------------------------------------
296! Local variables:
297!--- NetCDF
298  INTEGER           :: ncid, varid        ! NetCDF identifiers
299  CHARACTER(LEN=30) :: dnam               ! dimension name
300!--- dimensions
301  INTEGER           :: dids(4)            ! NetCDF dimensions identifiers
302  REAL, ALLOCATABLE :: dlon_ini(:)        ! initial longitudes vector
303  REAL, ALLOCATABLE :: dlat_ini(:)        ! initial latitudes  vector
304  REAL, POINTER     :: dlon(:), dlat(:)   ! reordered lon/lat  vectors
305!--- fields
306  INTEGER :: imdep, jmdep, lmdep          ! dimensions of 'champ'
307  REAL, ALLOCATABLE :: champ(:,:)         ! wanted field on initial grid
308  REAL, ALLOCATABLE :: yder(:), timeyear(:)
309  REAL              :: champint(iim,jjp1) ! interpolated field
310  REAL, ALLOCATABLE :: champtime(:,:,:)
311  REAL, ALLOCATABLE :: champan(:,:,:)
312!--- input files
313  CHARACTER(LEN=20) :: cal_in             ! calendar
314  CHARACTER(LEN=20) :: unit_sic           ! attribute unit in sea-ice file
315  INTEGER           :: ndays_in           ! number of days
316!--- misc
317  INTEGER           :: i, j, k, l         ! loop counters
318  REAL, ALLOCATABLE :: work(:,:)          ! used for extrapolation
319  CHARACTER(LEN=25) :: title              ! for messages
320  LOGICAL           :: extrp              ! flag for extrapolation
321  LOGICAL           :: oldice             ! flag for old way ice computation
322  REAL              :: chmin, chmax
323  INTEGER ierr
324  integer n_extrap ! number of extrapolated points
325  logical skip
326
327!------------------------------------------------------------------------------
328!---Variables depending on keyword 'mode' -------------------------------------
329  NULLIFY(champo)
330
331  SELECT CASE(mode)
332  CASE('RUG'); title='Rugosite'
333  CASE('SIC'); title='Sea-ice'
334  CASE('SST'); title='SST'
335  CASE('ALB'); title='Albedo'
336  END SELECT
337 
338
339  extrp=.FALSE.
340  oldice=.FALSE.
341  IF ( PRESENT(flag) ) THEN
342    IF ( flag .AND. mode=='SST' ) extrp=.TRUE.
343    IF ( flag .AND. mode=='SIC' ) oldice=.TRUE.
344  END IF
345
346!--- GETTING SOME DIMENSIONAL VARIABLES FROM FILE -----------------------------
347  CALL msg(5,' Now reading file : '//TRIM(fnam))
348  CALL ncerr(NF90_OPEN(fnam, NF90_NOWRITE, ncid),fnam)
349  CALL ncerr(NF90_INQ_VARID(ncid, trim(varname), varid),fnam)
350  CALL ncerr(NF90_INQUIRE_VARIABLE(ncid, varid, dimids=dids),fnam)
351
352!--- Read unit for sea-ice variable only
353  IF (mode=='SIC') THEN
354    IF(NF90_GET_ATT(ncid, varid, 'units', unit_sic)/=NF90_NOERR) THEN
355      CALL msg(5,'No unit in sea-ice file. Take percentage as default value')
356      unit_sic='X'
357    ELSE
358      CALL msg(5,'Sea-ice cover has unit='//TRIM(unit_sic))
359    END IF
360  END IF
361
362!--- Longitude
363  CALL ncerr(NF90_INQUIRE_DIMENSION(ncid, dids(1), name=dnam, len=imdep),fnam)
364  ALLOCATE(dlon_ini(imdep), dlon(imdep))
365  CALL ncerr(NF90_INQ_VARID(ncid, dnam, varid), fnam)
366  CALL ncerr(NF90_GET_VAR(ncid, varid, dlon_ini), fnam)
367  CALL msg(5,'variable '//TRIM(dnam)//' dimension ', imdep)
368
369!--- Latitude
370  CALL ncerr(NF90_INQUIRE_DIMENSION(ncid, dids(2), name=dnam, len=jmdep),fnam)
371  ALLOCATE(dlat_ini(jmdep), dlat(jmdep))
372  CALL ncerr(NF90_INQ_VARID(ncid, dnam, varid), fnam)
373  CALL ncerr(NF90_GET_VAR(ncid, varid, dlat_ini), fnam)
374  CALL msg(5,'variable '//TRIM(dnam)//' dimension ', jmdep)
375
376!--- Time (variable is not needed - it is rebuilt - but calendar is)
377  CALL ncerr(NF90_INQUIRE_DIMENSION(ncid, dids(3), name=dnam, len=lmdep), fnam)
378  ALLOCATE(timeyear(lmdep))
379  CALL ncerr(NF90_INQ_VARID(ncid, dnam, varid), fnam)
380  cal_in=' '
381  IF(NF90_GET_ATT(ncid, varid, 'calendar', cal_in)/=NF90_NOERR) THEN
382    SELECT CASE(mode)
383      CASE('RUG', 'ALB'); cal_in='360d'
384      CASE('SIC', 'SST'); cal_in='gregorian'
385    END SELECT
386  CALL msg(5,'WARNING: missing "calendar" attribute for "time" in '&
387     &//TRIM(fnam)//'. Choosing default value.')
388  END IF
389  CALL msg(5,'var, calendar, dim: '//TRIM(dnam)//' '//TRIM(cal_in), lmdep)
390 
391!--- CONSTRUCTING THE INPUT TIME VECTOR FOR INTERPOLATION --------------------
392  !--- Determining input file number of days, depending on calendar
393  ndays_in=year_len(anneeref, cal_in)
394
395!--- Time vector reconstruction (time vector from file is not trusted)
396!--- If input records are not monthly, time sampling has to be constant !
397  timeyear=mid_months(anneeref, cal_in, lmdep)
398  IF (lmdep /= 12) WRITE(lunout,*) 'Note : les fichiers de ', TRIM(mode), &
399       ' ne comportent pas 12, mais ', lmdep, ' enregistrements.'
400
401!--- GETTING THE FIELD AND INTERPOLATING IT ----------------------------------
402  ALLOCATE(champ(imdep, jmdep), champtime(iim, jjp1, lmdep))
403  IF(extrp) ALLOCATE(work(imdep, jmdep))
404  CALL msg(5,'')
405  CALL msg(5,'LECTURE ET INTERPOLATION HORIZ. DE ', lmdep, ' CHAMPS.')
406  CALL ncerr(NF90_INQ_VARID(ncid, varname, varid), fnam)
407  DO l=1, lmdep
408    CALL ncerr(NF90_GET_VAR(ncid,varid,champ,[1,1,l],[imdep,jmdep,1]),fnam)
409    CALL conf_dat2d(title, dlon_ini, dlat_ini, dlon, dlat, champ, ibar)
410    IF(extrp) CALL extrapol(champ,imdep,jmdep,999999.,.TRUE.,.TRUE.,2,work)
411
412    IF(ibar .AND. .NOT.oldice) THEN
413      IF(l==1) THEN
414      CALL msg(5,"----------------------------------------------------------")
415      CALL msg(5,"$$$ Interpolation barycentrique pour "//TRIM(title)//" $$$")
416      CALL msg(5,"----------------------------------------------------------")
417      END IF
418      IF(mode=='RUG') champ=LOG(champ)
419      CALL inter_barxy(dlon,dlat(:jmdep-1),champ,rlonu(:iim),rlatv,champint)
420      IF(mode=='RUG') THEN
421        champint=EXP(champint)
422        WHERE(NINT(mask)/=1) champint=0.001
423      END IF
424    ELSE
425      SELECT CASE(mode)
426        CASE('RUG');       CALL rugosite(dlon,dlat,champ,rlonv,rlatu,champint,mask)
427        CASE('SIC');       CALL sea_ice (dlon,dlat,champ,rlonv,rlatu,champint)
428        CASE('SST','ALB'); CALL grille_m(dlon,dlat,champ,rlonv,rlatu,champint)
429      END SELECT
430    END IF
431    champtime(:, :, l)=champint
432  END DO
433  CALL ncerr(NF90_CLOSE(ncid), fnam)
434
435  DEALLOCATE(dlon_ini, dlat_ini, dlon, dlat, champ)
436  IF(extrp) DEALLOCATE(work)
437
438!--- TIME INTERPOLATION ------------------------------------------------------
439  IF(prt_level>5) THEN
440     WRITE(lunout, *)
441     WRITE(lunout, *)'INTERPOLATION TEMPORELLE.'
442     WRITE(lunout, *)' Vecteur temps en entree: ', timeyear
443     WRITE(lunout, *)' Vecteur temps en sortie de 0 a ', ndays
444  END IF
445
446  ALLOCATE(yder(lmdep), champan(iip1, jjp1, ndays))
447  skip = .false.
448  n_extrap = 0
449  DO j=1, jjp1
450    DO i=1, iim
451      yder = pchsp_95(timeyear, champtime(i, j, :), ibeg=2, iend=2, &
452           vc_beg=0., vc_end=0.)
453      CALL pchfe_95(timeyear, champtime(i, j, :), yder, skip, &
454           arth(0., real(ndays_in) / ndays, ndays), champan(i, j, :), ierr)
455      if (ierr < 0) stop 1
456      n_extrap = n_extrap + ierr
457    END DO
458  END DO
459  if (n_extrap /= 0) then
460     WRITE(lunout,*) "get_2Dfield pchfe_95: n_extrap = ", n_extrap
461  end if
462  champan(iip1, :, :)=champan(1, :, :)
463  DEALLOCATE(yder, champtime, timeyear)
464
465!--- Checking the result
466  DO j=1, jjp1
467    CALL minmax(iip1, champan(1, j, 10), chmin, chmax)
468    IF (prt_level>5) WRITE(lunout, *)' ',TRIM(title),' au temps 10 ', chmin, chmax, j
469  END DO
470
471!--- SPECIAL FILTER FOR SST: SST>271.38 --------------------------------------
472  IF(mode=='SST') THEN
473    CALL msg(5,'Filtrage de la SST: SST >= 271.38')
474    WHERE(champan<271.38) champan=271.38
475  END IF
476
477!--- SPECIAL FILTER FOR SIC: 0.0<SIC<1.0 -------------------------------------
478  IF(mode=='SIC') THEN
479    CALL msg(5,'Filtrage de la SIC: 0.0 < Sea-ice < 1.0')
480
481    IF (unit_sic=='1') THEN
482       ! Nothing to be done for sea-ice field is already in fraction of 1
483       ! This is the case for sea-ice in file cpl_atm_sic.nc
484       CALL msg(5,'Sea-ice field already in fraction of 1')
485    ELSE
486       ! Convert sea ice from percentage to fraction of 1
487       CALL msg(5,'Transformt sea-ice field from percentage to fraction of 1.')
488       champan(:, :, :)=champan(:, :, :)/100.
489    END IF
490
491    champan(iip1, :, :)=champan(1, :, :)
492    WHERE(champan>1.0) champan=1.0
493    WHERE(champan<0.0) champan=0.0
494 END IF
495
496!--- DYNAMICAL TO PHYSICAL GRID ----------------------------------------------
497  ALLOCATE(champo(klon, ndays))
498  DO k=1, ndays
499    CALL gr_dyn_fi(1, iip1, jjp1, klon, champan(1, 1, k), champo(1, k))
500  END DO
501  DEALLOCATE(champan)
502
503END SUBROUTINE get_2Dfield
504!
505!-------------------------------------------------------------------------------
506
507
508!-------------------------------------------------------------------------------
509!
510FUNCTION year_len(y,cal_in)
511!
512!-------------------------------------------------------------------------------
513  USE ioipsl, ONLY : ioget_calendar,ioconf_calendar,lock_calendar,ioget_year_len
514  IMPLICIT NONE
515!-------------------------------------------------------------------------------
516! Arguments:
517  INTEGER                       :: year_len
518  INTEGER,           INTENT(IN) :: y
519  CHARACTER(LEN=*),  INTENT(IN) :: cal_in
520!-------------------------------------------------------------------------------
521! Local variables:
522  CHARACTER(LEN=20)             :: cal_out              ! calendar (for outputs)
523!-------------------------------------------------------------------------------
524!--- Getting the input calendar to reset at the end of the function
525  CALL ioget_calendar(cal_out)
526
527!--- Unlocking calendar and setting it to wanted one
528  CALL lock_calendar(.FALSE.); CALL ioconf_calendar(TRIM(cal_in))
529
530!--- Getting the number of days in this year
531  year_len=ioget_year_len(y)
532
533!--- Back to original calendar
534  CALL lock_calendar(.FALSE.); CALL ioconf_calendar(TRIM(cal_out))
535
536END FUNCTION year_len
537!
538!-------------------------------------------------------------------------------
539
540
541!-------------------------------------------------------------------------------
542!
543FUNCTION mid_months(y,cal_in,nm)
544!
545!-------------------------------------------------------------------------------
546  USE ioipsl, ONLY : ioget_calendar,ioconf_calendar,lock_calendar,ioget_mon_len
547  IMPLICIT NONE
548!-------------------------------------------------------------------------------
549! Arguments:
550  INTEGER,                INTENT(IN) :: y               ! year
551  CHARACTER(LEN=*),       INTENT(IN) :: cal_in          ! calendar
552  INTEGER,                INTENT(IN) :: nm              ! months/year number
553  REAL,    DIMENSION(nm)             :: mid_months      ! mid-month times
554!-------------------------------------------------------------------------------
555! Local variables:
556  CHARACTER(LEN=99)                  :: mess            ! error message
557  CHARACTER(LEN=20)                  :: cal_out         ! calendar (for outputs)
558  INTEGER, DIMENSION(nm)             :: mnth            ! months lengths (days)
559  INTEGER                            :: m               ! months counter
560  INTEGER                            :: nd              ! number of days
561!-------------------------------------------------------------------------------
562  nd=year_len(y,cal_in)
563
564  IF(nm==12) THEN
565
566  !--- Getting the input calendar to reset at the end of the function
567    CALL ioget_calendar(cal_out)
568
569  !--- Unlocking calendar and setting it to wanted one
570    CALL lock_calendar(.FALSE.); CALL ioconf_calendar(TRIM(cal_in))
571
572  !--- Getting the length of each month
573    DO m=1,nm; mnth(m)=ioget_mon_len(y,m); END DO
574
575  !--- Back to original calendar
576    CALL lock_calendar(.FALSE.); CALL ioconf_calendar(TRIM(cal_out))
577
578  ELSE IF(MODULO(nd,nm)/=0) THEN
579    WRITE(mess,'(a,i3,a,i3,a)')'Unconsistent calendar: ',nd,' days/year, but ',&
580      nm,' months/year. Months number should divide days number.'
581    CALL abort_gcm('mid_months',TRIM(mess),1)
582
583  ELSE
584    mnth=[(m,m=1,nm,nd/nm)]
585  END IF
586
587!--- Mid-months times
588  mid_months(1)=0.5*REAL(mnth(1))
589  DO k=2,nm
590    mid_months(k)=mid_months(k-1)+0.5*REAL(mnth(k-1)+mnth(k))
591  END DO
592
593END FUNCTION mid_months
594!
595!-------------------------------------------------------------------------------
596
597
598
599!-------------------------------------------------------------------------------
600!
601SUBROUTINE msg(lev,str1,i,str2)
602!
603!-------------------------------------------------------------------------------
604! Arguments:
605  INTEGER,                    INTENT(IN) :: lev
606  CHARACTER(LEN=*),           INTENT(IN) :: str1
607  INTEGER,          OPTIONAL, INTENT(IN) :: i
608  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: str2
609!-------------------------------------------------------------------------------
610  IF(prt_level>lev) THEN
611    IF(PRESENT(str2)) THEN
612      WRITE(lunout,*) TRIM(str1), i, TRIM(str2)
613    ELSE IF(PRESENT(i)) THEN
614      WRITE(lunout,*) TRIM(str1), i
615    ELSE
616      WRITE(lunout,*) TRIM(str1)
617    END IF
618  END IF
619
620END SUBROUTINE msg
621!
622!-------------------------------------------------------------------------------
623
624
625!-------------------------------------------------------------------------------
626!
627SUBROUTINE ncerr(ncres,fnam)
628!
629!-------------------------------------------------------------------------------
630! Purpose: NetCDF errors handling.
631!-------------------------------------------------------------------------------
632  USE netcdf, ONLY : NF90_NOERR, NF90_STRERROR
633  IMPLICIT NONE
634!-------------------------------------------------------------------------------
635! Arguments:
636  INTEGER,          INTENT(IN) :: ncres
637  CHARACTER(LEN=*), INTENT(IN) :: fnam
638!-------------------------------------------------------------------------------
639#include "iniprint.h"
640  IF(ncres/=NF90_NOERR) THEN
641    WRITE(lunout,*)'Problem with file '//TRIM(fnam)//' in routine limit_netcdf.'
642    CALL abort_gcm('limit_netcdf',NF90_STRERROR(ncres),1)
643  END IF
644
645END SUBROUTINE ncerr
646!
647!-------------------------------------------------------------------------------
648
649#endif
650! of #ifdef CPP_EARTH
651
652#endif
653! of #ifndef CPP_1D
654END SUBROUTINE limit_netcdf
Note: See TracBrowser for help on using the repository browser.