source: LMDZ4/trunk/libf/dyn3d/limit_netcdf.F90 @ 2358

Last change on this file since 2358 was 1425, checked in by lguez, 14 years ago

Replaced Numerical Recipes procedures for spline interpolation (not in
the public domain) by procedures from the Pchip package in the Slatec
library. This only affects the program "ce0l", not the program
"gcm". Tested on Brodie SX8 with "-debug" and "-prod", "-parallel
none" and "-parallel mpi". "start.nc" and "limit.nc" are
changed. "startphy.nc" is not changed. The relative change is of order
1e-7 or less. The revision makes the program faster (tested on Brodie
with "-prod -d 144x142x39", CPU time is 38 s, instead of 54
s). Procedures from Slatec are untouched, except for
"i1mach.F". Created procedures "pchfe_95" and "pchsp_95" which are
wrappers for "pchfe" and "pchsp" from Slatec. "pchfe_95" and
"pchsp_95" have a safer and simpler interface.

Replaced "make" by "sxgmake" in "arch-SX8_BRODIE.fcm". Added files for
compilation by FCM with "g95".

In "arch-linux-32bit.fcm", replaced "pgf90" by "pgf95". There was no
difference between "dev" and "debug" so added "-O1" to "dev". Added
debugging options. Removed "-Wl,-Bstatic
-L/usr/lib/gcc-lib/i386-linux/2.95.2", which usually produces an error
at link-time.

Bash is now ubiquitous while KornShell? is not so use Bash instead of
KornShell? in FCM.

Replaced some statements "write(6,*)" by "write(lunout,*)". Replaced
"stop" by "stop 1" in the case where "abort_gcm" is called with "ierr
/= 0". Removed "stop" statements at the end of procedures
"limit_netcdf" and main program "ce0l" (why not let the program end
normally?).

Made some arrays automatic instead of allocatable in "start_inter_3d".

Zeroed "wake_pe", "fm_therm", "entr_therm" and "detr_therm" in
"dyn3dpar/etat0_netcdf.F90". The parallel and sequential results of
"ce0l" are thus identical.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.0 KB
RevLine 
[524]1!
[1279]2! $Id: limit_netcdf.F90 1425 2010-09-02 13:45:23Z emillour $
[1319]3!-------------------------------------------------------------------------------
[524]4!
[1319]5SUBROUTINE limit_netcdf(interbar, extrap, oldice, masque)
6!
7!-------------------------------------------------------------------------------
8! Author : L. Fairhead, 27/01/94
9!-------------------------------------------------------------------------------
10! Purpose: Boundary conditions files building for new model using climatologies.
11!          Both grids have to be regular.
12!-------------------------------------------------------------------------------
13! Note: This routine is designed to work for Earth
14!-------------------------------------------------------------------------------
15! Modification history:
16!  * 23/03/1994: Z. X. Li
17!  *    09/1999: L. Fairhead (netcdf reading in LMDZ.3.3)
18!  *    07/2001: P. Le Van
19!  *    11/2009: L. Guez     (ozone day & night climatos, see etat0_netcdf.F90)
20!  *    12/2009: D. Cugnet   (f77->f90, calendars, files from coupled runs)
21!-------------------------------------------------------------------------------
[1403]22  USE control_mod
[1279]23#ifdef CPP_EARTH
[1319]24  USE dimphy
25  USE ioipsl,             ONLY : ioget_year_len
26  USE phys_state_var_mod, ONLY : pctsrf
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,      &
[1403]30                   NF90_CLOBBER, NF90_ENDDEF,  NF90_UNLIMITED, NF90_FLOAT
[1323]31  USE inter_barxy_m, only: inter_barxy
[1319]32#endif
33  IMPLICIT NONE
34!-------------------------------------------------------------------------------
35! Arguments:
[524]36#include "dimensions.h"
37#include "paramet.h"
[1319]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  WRITE(lunout,*)'limit_netcdf: Earth-specific routine, needs Earth physics'
45#else
46!-------------------------------------------------------------------------------
47! Local variables:
[524]48#include "logic.h"
49#include "comvert.h"
50#include "comgeom2.h"
51#include "comconst.h"
52#include "indicesol.h"
53
[1319]54!--- For fractionary sub-cell use (old coding used soil index: 0,1,2,3) --------
55  LOGICAL, PARAMETER :: fracterre=.TRUE.
[989]56
[1319]57!--- INPUT NETCDF FILES NAMES --------------------------------------------------
58  CHARACTER(LEN=25) :: icefile, sstfile, dumstr
59  CHARACTER(LEN=25), PARAMETER :: famipsst='amipbc_sst_1x1.nc        ',        &
60                                  famipsic='amipbc_sic_1x1.nc        ',        &
61                                  fclimsst='amipbc_sst_1x1_clim.nc   ',        &
62                                  fclimsic='amipbc_sic_1x1_clim.nc   ',        &
63                                  fcpldsst='cpl_atm_sst.nc           ',        &
64                                  fcpldsic='cpl_atm_sic.nc           ',        &
65                                  frugo   ='Rugos.nc                 ',        &
66                                  falbe   ='Albedo.nc                '
[524]67
[1319]68!--- OUTPUT VARIABLES FOR NETCDF FILE ------------------------------------------
69  REAL,   DIMENSION(klon)                :: fi_ice, verif
70  REAL,   DIMENSION(:,:),   POINTER      :: phy_rug=>NULL(), phy_ice=>NULL()
71  REAL,   DIMENSION(:,:),   POINTER      :: phy_sst=>NULL(), phy_alb=>NULL()
72  REAL,   DIMENSION(:,:),   ALLOCATABLE  :: phy_bil
73  REAL,   DIMENSION(:,:,:), ALLOCATABLE  :: pctsrf_t
74  INTEGER                                :: nbad
[524]75
[1319]76!--- VARIABLES FOR OUTPUT FILE WRITING -----------------------------------------
77  INTEGER :: ierr, nid, ndim, ntim, k
78  INTEGER, DIMENSION(2) :: dims
79  INTEGER :: id_tim,  id_SST,  id_BILS, id_RUG, id_ALB
80  INTEGER :: id_FOCE, id_FSIC, id_FTER, id_FLIC
81  INTEGER :: NF90_FORMAT
82  LOGICAL :: lCPL                    !--- T: IPCC-IPSL cpl model output files
[1328]83  INTEGER :: ndays                   !--- Depending on the output calendar
[524]84
[1319]85!--- INITIALIZATIONS -----------------------------------------------------------
86#ifdef NC_DOUBLE
87  NF90_FORMAT=NF90_DOUBLE
88#else
89  NF90_FORMAT=NF90_FLOAT
90#endif
[524]91
[1319]92  pi    = 4.*ATAN(1.)
93  rad   = 6371229.
94  daysec= 86400.
95  omeg  = 2.*pi/daysec
96  g     = 9.8
97  kappa = 0.2857143
98  cpp   = 1004.70885
99  dtvr  = daysec/FLOAT(day_step)
100  CALL inigeom
[524]101
[1319]102!--- Beware: anneeref (from gcm.def) is used to determine output time sampling
103  ndays=ioget_year_len(anneeref)
[524]104
[1319]105!--- RUGOSITY TREATMENT --------------------------------------------------------
106  WRITE(lunout,*) 'Traitement de la rugosite'
107  CALL get_2Dfield(frugo,'RUG',interbar,ndays,phy_rug,mask=masque(1:iim,:))
[524]108
[1319]109!--- OCEAN TREATMENT -----------------------------------------------------------
110  PRINT*, 'Traitement de la glace oceanique' ; icefile=''; lCPL=.FALSE.
[524]111
[1319]112! Input SIC file selection
113  icefile='fake'
114  IF(NF90_OPEN(famipsic,NF90_NOWRITE,nid)==NF90_NOERR) icefile=TRIM(famipsic)
115  IF(NF90_OPEN(fclimsic,NF90_NOWRITE,nid)==NF90_NOERR) icefile=TRIM(fclimsic)
116  IF(NF90_OPEN(fcpldsic,NF90_NOWRITE,nid)==NF90_NOERR) icefile=TRIM(fcpldsic)
117  SELECT CASE(icefile)
118    CASE(famipsic); dumstr='Amip.'
119    CASE(fclimsic); dumstr='Amip climatologique.'
120    CASE(fcpldsic); dumstr='de sortie du modele couplé IPSL/IPCC.';lCPL=.TRUE.
121    CASE('fake');   CALL abort_gcm('limit_netcdf','Fichier SIC non reconnu.',1)
122  END SELECT
123  ierr=NF90_CLOSE(nid)
124  WRITE(lunout,*)'Pour la glace de mer a ete choisi un fichier '//TRIM(dumstr)
[524]125
[1328]126  CALL get_2Dfield(icefile,'SIC',interbar,ndays,phy_ice,flag=oldice,lCPL=lCPL)
[524]127
[1319]128  ALLOCATE(pctsrf_t(klon,nbsrf,ndays))
129  DO k=1,ndays
130    fi_ice=phy_ice(:,k)
131    WHERE(fi_ice>=1.0  ) fi_ice=1.0
132    WHERE(fi_ice<EPSFRA) fi_ice=0.0
133    IF(fracterre) THEN
134      pctsrf_t(:,is_ter,k)=pctsrf(:,is_ter)       ! land soil
135      pctsrf_t(:,is_lic,k)=pctsrf(:,is_lic)       ! land ice
[1328]136      IF(lCPL) THEN                               ! SIC=pICE*(1-LIC-TER)
[1319]137        pctsrf_t(:,is_sic,k)=fi_ice*(1-pctsrf(:,is_lic)-pctsrf(:,is_ter))
138      ELSE                                        ! SIC=pICE-LIC
139        pctsrf_t(:,is_sic,k)=fi_ice-pctsrf_t(:,is_lic,k)
140      END IF
141      WHERE(pctsrf_t(:,is_sic,k)<=0) pctsrf_t(:,is_sic,k)=0.
142      WHERE(1.0-zmasq<EPSFRA)
143        pctsrf_t(:,is_sic,k)=0.0
144        pctsrf_t(:,is_oce,k)=0.0
145      ELSEWHERE
146        WHERE(pctsrf_t(:,is_sic,k)>=1.0-zmasq)
147          pctsrf_t(:,is_sic,k)=1.0-zmasq
148          pctsrf_t(:,is_oce,k)=0.0
149        ELSEWHERE
150          pctsrf_t(:,is_oce,k)=1.0-zmasq-pctsrf_t(:,is_sic,k)
151          WHERE(pctsrf_t(:,is_oce,k)<EPSFRA)
152            pctsrf_t(:,is_oce,k)=0.0
153            pctsrf_t(:,is_sic,k)=1.0-zmasq
154          END WHERE
155        END WHERE
156      END WHERE
157      nbad=COUNT(pctsrf_t(:,is_oce,k)<0.0)
158      IF(nbad>0) WRITE(lunout,*) 'pb sous maille pour nb point = ',nbad
159      nbad=COUNT(abs(sum(pctsrf_t(:,:,k),dim=2)-1.0)>EPSFRA)
160      IF(nbad>0) WRITE(lunout,*) 'pb sous surface pour nb points = ',nbad
161    ELSE
162      pctsrf_t(:,is_ter,k)=pctsrf(:,is_ter)
163      WHERE(NINT(pctsrf(:,is_ter))==1)
164        pctsrf_t(:,is_sic,k)=0.
165        pctsrf_t(:,is_oce,k)=0.                 
166        WHERE(fi_ice>=1.e-5)
167          pctsrf_t(:,is_lic,k)=fi_ice
168          pctsrf_t(:,is_ter,k)=pctsrf_t(:,is_ter,k)-pctsrf_t(:,is_lic,k)
169        ELSEWHERE
170          pctsrf_t(:,is_lic,k)=0.0
171        END WHERE
172      ELSEWHERE
173        pctsrf_t(:,is_lic,k) = 0.0
174        WHERE(fi_ice>=1.e-5)
175          pctsrf_t(:,is_ter,k)=0.0
176          pctsrf_t(:,is_sic,k)=fi_ice
177          pctsrf_t(:,is_oce,k)=1.0-pctsrf_t(:,is_sic,k)
178        ELSEWHERE
179          pctsrf_t(:,is_sic,k)=0.0
180          pctsrf_t(:,is_oce,k)=1.0
181        END WHERE
182      END WHERE
183      verif=sum(pctsrf_t(:,:,k),dim=2)
184      nbad=COUNT(verif<1.0-1.e-5.OR.verif>1.0+1.e-5)
185      IF(nbad>0) WRITE(lunout,*) 'pb sous maille pour nb point = ',nbad
186    END IF
187  END DO
188  DEALLOCATE(phy_ice)
[524]189
[1319]190!--- SST TREATMENT -------------------------------------------------------------
191  WRITE(lunout,*) 'Traitement de la sst' ; sstfile=''; lCPL=.FALSE.
[524]192
[1319]193! Input SST file selection
194  sstfile='fake'
195  IF(NF90_OPEN(famipsst,NF90_NOWRITE,nid)==NF90_NOERR) sstfile=TRIM(famipsst)
196  IF(NF90_OPEN(fclimsst,NF90_NOWRITE,nid)==NF90_NOERR) sstfile=TRIM(fclimsst)
197  IF(NF90_OPEN(fcpldsst,NF90_NOWRITE,nid)==NF90_NOERR) sstfile=TRIM(fcpldsst)
198  SELECT CASE(icefile)
199    CASE(famipsic); dumstr='Amip.'
200    CASE(fclimsic); dumstr='Amip climatologique.'
201    CASE(fcpldsic); dumstr='de sortie du modele couplé IPSL/IPCC.';lCPL=.TRUE.
202    CASE('fake');   CALL abort_gcm('limit_netcdf','Fichier SST non reconnu',1)
203  END SELECT
204  ierr=NF90_CLOSE(nid)
205  WRITE(lunout,*)'Pour la temperature de mer a ete choisi un fichier '//TRIM(dumstr)
[524]206
[1319]207  CALL get_2Dfield(trim(sstfile),'SST',interbar,ndays,phy_sst,flag=extrap)
[524]208
[1319]209!--- ALBEDO TREATMENT ----------------------------------------------------------
210  WRITE(lunout,*) 'Traitement de l albedo'
211  CALL get_2Dfield(falbe,'ALB',interbar,ndays,phy_alb)
[524]212
[1319]213!--- REFERENCE GROUND HEAT FLUX TREATMENT --------------------------------------
214  ALLOCATE(phy_bil(klon,ndays)); phy_bil=0.0
[524]215
[1319]216!--- OUTPUT FILE WRITING -------------------------------------------------------
217  WRITE(lunout,*) 'Ecriture du fichier limit'
[524]218
[1319]219  !--- File creation
220  ierr=NF90_CREATE("limit.nc",NF90_CLOBBER,nid)
221  ierr=NF90_PUT_ATT(nid,NF90_GLOBAL,"title","Fichier conditions aux limites")
[524]222
[1319]223  !--- Dimensions creation
224  ierr=NF90_DEF_DIM(nid,"points_physiques",klon,ndim)
225  ierr=NF90_DEF_DIM(nid,"time",NF90_UNLIMITED,ntim)
[524]226
[1319]227  dims=(/ndim,ntim/)
[524]228
[1319]229  !--- Variables creation
[1328]230  ierr=NF90_DEF_VAR(nid,"TEMPS",NF90_FORMAT,(/ntim/),id_tim)
[1319]231  ierr=NF90_DEF_VAR(nid,"FOCE", NF90_FORMAT,dims,id_FOCE)
232  ierr=NF90_DEF_VAR(nid,"FSIC", NF90_FORMAT,dims,id_FSIC)
233  ierr=NF90_DEF_VAR(nid,"FTER", NF90_FORMAT,dims,id_FTER)
234  ierr=NF90_DEF_VAR(nid,"FLIC", NF90_FORMAT,dims,id_FLIC)
235  ierr=NF90_DEF_VAR(nid,"SST",  NF90_FORMAT,dims,id_SST)
236  ierr=NF90_DEF_VAR(nid,"BILS", NF90_FORMAT,dims,id_BILS)
237  ierr=NF90_DEF_VAR(nid,"ALB",  NF90_FORMAT,dims,id_ALB)
238  ierr=NF90_DEF_VAR(nid,"RUG",  NF90_FORMAT,dims,id_RUG)
[524]239
[1319]240  !--- Attributes creation
241  ierr=NF90_PUT_ATT(nid,id_tim, "title","Jour dans l annee")
242  ierr=NF90_PUT_ATT(nid,id_FOCE,"title","Fraction ocean")
243  ierr=NF90_PUT_ATT(nid,id_FSIC,"title","Fraction glace de mer")
244  ierr=NF90_PUT_ATT(nid,id_FTER,"title","Fraction terre")
245  ierr=NF90_PUT_ATT(nid,id_FLIC,"title","Fraction land ice")
246  ierr=NF90_PUT_ATT(nid,id_SST ,"title","Temperature superficielle de la mer")
247  ierr=NF90_PUT_ATT(nid,id_BILS,"title","Reference flux de chaleur au sol")
248  ierr=NF90_PUT_ATT(nid,id_ALB, "title","Albedo a la surface")
249  ierr=NF90_PUT_ATT(nid,id_RUG, "title","Rugosite")
[524]250
[1319]251  ierr=NF90_ENDDEF(nid)
252
253  !--- Variables saving
[1328]254  ierr=NF90_PUT_VAR(nid,id_tim,(/(REAL(k),k=1,ndays)/))
[1319]255  ierr=NF90_PUT_VAR(nid,id_FOCE,pctsrf_t(:,is_oce,:),(/1,1/),(/klon,ndays/))
256  ierr=NF90_PUT_VAR(nid,id_FSIC,pctsrf_t(:,is_sic,:),(/1,1/),(/klon,ndays/))
257  ierr=NF90_PUT_VAR(nid,id_FTER,pctsrf_t(:,is_ter,:),(/1,1/),(/klon,ndays/))
258  ierr=NF90_PUT_VAR(nid,id_FLIC,pctsrf_t(:,is_lic,:),(/1,1/),(/klon,ndays/))
259  ierr=NF90_PUT_VAR(nid,id_SST ,phy_sst(:,:),(/1,1/),(/klon,ndays/))
260  ierr=NF90_PUT_VAR(nid,id_BILS,phy_bil(:,:),(/1,1/),(/klon,ndays/))
261  ierr=NF90_PUT_VAR(nid,id_ALB ,phy_alb(:,:),(/1,1/),(/klon,ndays/))
262  ierr=NF90_PUT_VAR(nid,id_RUG ,phy_rug(:,:),(/1,1/),(/klon,ndays/))
263
264  ierr=NF90_CLOSE(nid)
265
266  DEALLOCATE(pctsrf_t,phy_sst,phy_bil,phy_alb,phy_rug)
[524]267#endif
[1319]268! of #ifdef CPP_EARTH
[524]269
270
[1319]271!===============================================================================
272!
273  CONTAINS
274!
275!===============================================================================
[524]276
277
[1319]278!-------------------------------------------------------------------------------
279!
[1328]280SUBROUTINE get_2Dfield(fnam, mode, ibar, ndays, champo, flag, mask, lCPL)
[1319]281!
[1425]282!-----------------------------------------------------------------------------
[1319]283! Comments:
284!   There are two assumptions concerning the NetCDF files, that are satisfied
285!   with files that are conforming NC convention:
286!     1) The last dimension of the variables used is the time record.
287!     2) Dimensional variables have the same names as corresponding dimensions.
[1425]288!-----------------------------------------------------------------------------
289  USE netcdf, ONLY: NF90_OPEN, NF90_INQ_VARID, NF90_INQUIRE_VARIABLE, &
290       NF90_CLOSE, NF90_INQ_DIMID, NF90_INQUIRE_DIMENSION, NF90_GET_VAR, &
291       NF90_GET_ATT
[1319]292  USE dimphy, ONLY : klon
293  USE phys_state_var_mod, ONLY : pctsrf
[1403]294  USE control_mod
[1425]295  use pchsp_95_m, only: pchsp_95
296  use pchfe_95_m, only: pchfe_95
297  use arth_m, only: arth
298
[1319]299  IMPLICIT NONE
300#include "dimensions.h"
301#include "paramet.h"
302#include "comgeom2.h"
303#include "indicesol.h"
304#include "iniprint.h"
[1425]305!-----------------------------------------------------------------------------
[1319]306! Arguments:
307  CHARACTER(LEN=*),  INTENT(IN)     :: fnam     ! NetCDF file name
308  CHARACTER(LEN=3),  INTENT(IN)     :: mode     ! RUG, SIC, SST or ALB
309  LOGICAL,           INTENT(IN)     :: ibar     ! interp on pressure levels
310  INTEGER,           INTENT(IN)     :: ndays    ! current year number of days
[1425]311  REAL,    POINTER,  DIMENSION(:, :) :: champo   ! output field = f(t)
312  LOGICAL, OPTIONAL, INTENT(IN)     :: flag     ! extrapol. (SST) old ice (SIC)
313  REAL,    OPTIONAL, DIMENSION(iim, jjp1), INTENT(IN) :: mask
[1328]314  LOGICAL, OPTIONAL, INTENT(IN)     :: lCPL     ! Coupled model flag (for ICE)
[1425]315!------------------------------------------------------------------------------
[1319]316! Local variables:
317!--- NetCDF
[1425]318  INTEGER :: ncid, varid                  ! NetCDF identifiers
[1319]319  CHARACTER(LEN=30)               :: dnam       ! dimension name
320  CHARACTER(LEN=80)               :: varname    ! NetCDF variable name
321!--- dimensions
322  INTEGER,           DIMENSION(4) :: dids       ! NetCDF dimensions identifiers
323  REAL, ALLOCATABLE, DIMENSION(:) :: dlon_ini   ! initial longitudes vector
324  REAL, ALLOCATABLE, DIMENSION(:) :: dlat_ini   ! initial latitudes  vector
325  REAL, POINTER,     DIMENSION(:) :: dlon, dlat ! reordered lon/lat  vectors
326!--- fields
327  INTEGER :: imdep, jmdep, lmdep                ! dimensions of 'champ'
[1425]328  REAL, ALLOCATABLE, DIMENSION(:, :) :: champ   ! wanted field on initial grid
[1319]329  REAL, ALLOCATABLE, DIMENSION(:) :: yder, timeyear
[1425]330  REAL,              DIMENSION(iim, jjp1) :: champint   ! interpolated field
331  REAL, ALLOCATABLE, DIMENSION(:, :, :)    :: champtime
332  REAL, ALLOCATABLE, DIMENSION(:, :, :)    :: champan
[1319]333!--- input files
334  CHARACTER(LEN=20)                 :: cal_in   ! calendar
335  INTEGER                           :: ndays_in ! number of days
336!--- misc
337  INTEGER :: i, j, k, l                         ! loop counters
[1425]338  REAL, ALLOCATABLE, DIMENSION(:, :) :: work     ! used for extrapolation
[1319]339  CHARACTER(LEN=25)                 :: title    ! for messages
340  LOGICAL                           :: extrp    ! flag for extrapolation
341  REAL                              :: chmin, chmax
[1425]342  INTEGER ierr
343  integer n_extrap ! number of extrapolated points
344  logical skip
345!------------------------------------------------------------------------------
346!---Variables depending on keyword 'mode' -------------------------------------
[1319]347  NULLIFY(champo)
348  SELECT CASE(mode)
349    CASE('RUG'); varname='RUGOS';  title='Rugosite'
350    CASE('SIC'); varname='sicbcs'; title='Sea-ice'
351    CASE('SST'); varname='tosbcs'; title='SST'
352    CASE('ALB'); varname='ALBEDO'; title='Albedo'
353  END SELECT
[1404]354  extrp=.FALSE.
355  IF ( PRESENT(flag) ) THEN
356    IF ( flag .AND. mode=='SST' ) extrp=.TRUE.
357  END IF
[524]358
[1425]359!--- GETTING SOME DIMENSIONAL VARIABLES FROM FILE -----------------------------
360  ierr=NF90_OPEN(fnam, NF90_NOWRITE, ncid);             CALL ncerr(ierr, fnam)
361  ierr=NF90_INQ_VARID(ncid, varname, varid);            CALL ncerr(ierr, fnam)
362  ierr=NF90_INQUIRE_VARIABLE(ncid, varid, dimids=dids); CALL ncerr(ierr, fnam)
[524]363
[1319]364!--- Longitude
[1425]365  ierr=NF90_INQUIRE_DIMENSION(ncid, dids(1), name=dnam, len=imdep)
366  CALL ncerr(ierr, fnam); ALLOCATE(dlon_ini(imdep), dlon(imdep))
367  ierr=NF90_INQ_VARID(ncid, dnam, varid);                CALL ncerr(ierr, fnam)
368  ierr=NF90_GET_VAR(ncid, varid, dlon_ini);              CALL ncerr(ierr, fnam)
369  WRITE(lunout, *) 'variable ', dnam, 'dimension ', imdep
[524]370
[1319]371!--- Latitude
[1425]372  ierr=NF90_INQUIRE_DIMENSION(ncid, dids(2), name=dnam, len=jmdep)
373  CALL ncerr(ierr, fnam); ALLOCATE(dlat_ini(jmdep), dlat(jmdep))
374  ierr=NF90_INQ_VARID(ncid, dnam, varid);                CALL ncerr(ierr, fnam)
375  ierr=NF90_GET_VAR(ncid, varid, dlat_ini);              CALL ncerr(ierr, fnam)
376  WRITE(lunout, *) 'variable ', dnam, 'dimension ', jmdep
[524]377
[1319]378!--- Time (variable is not needed - it is rebuilt - but calendar is)
[1425]379  ierr=NF90_INQUIRE_DIMENSION(ncid, dids(3), name=dnam, len=lmdep)
380  CALL ncerr(ierr, fnam); ALLOCATE(timeyear(lmdep))
381  ierr=NF90_INQ_VARID(ncid, dnam, varid);                CALL ncerr(ierr, fnam)
[1319]382  cal_in=' '
[1425]383  ierr=NF90_GET_ATT(ncid, varid, 'calendar', cal_in)
[1319]384  IF(ierr/=NF90_NOERR) THEN
385    SELECT CASE(mode)
[1425]386      CASE('RUG', 'ALB'); cal_in='360d'
387      CASE('SIC', 'SST'); cal_in='gregorian'
[1319]388    END SELECT
[1425]389    WRITE(lunout, *)'ATTENTION: variable "time" sans attribut "calendrier" ' &
390         // 'dans '//TRIM(fnam)//'. On choisit la valeur par defaut.'
[1319]391  END IF
[1425]392  WRITE(lunout, *) 'variable ', dnam, 'dimension ', lmdep, 'calendrier ', &
393       cal_in
[524]394
[1425]395!--- CONSTRUCTING THE INPUT TIME VECTOR FOR INTERPOLATION --------------------
[1319]396  !--- Determining input file number of days, depending on calendar
[1425]397  ndays_in=year_len(anneeref, cal_in)
[524]398
[1319]399!--- Time vector reconstruction (time vector from file is not trusted)
400!--- If input records are not monthly, time sampling has to be constant !
[1425]401  timeyear=mid_months(anneeref, cal_in, lmdep)
402  IF (lmdep /= 12) WRITE(lunout, '(a, i3, a)') 'Note : les fichiers de ' &
403       // TRIM(mode) // ' ne comportent pas 12, mais ', lmdep, &
404       ' enregistrements.'
[524]405
[1425]406!--- GETTING THE FIELD AND INTERPOLATING IT ----------------------------------
407  ALLOCATE(champ(imdep, jmdep), champtime(iim, jjp1, lmdep))
408  IF(extrp) ALLOCATE(work(imdep, jmdep))
[524]409
[1425]410  WRITE(lunout, *)
411  WRITE(lunout, '(a, i3, a)')'LECTURE ET INTERPOLATION HORIZ. DE ', lmdep, &
412       ' CHAMPS.'
413  ierr=NF90_INQ_VARID(ncid, varname, varid);             CALL ncerr(ierr, fnam)
414  DO l=1, lmdep
415    ierr=NF90_GET_VAR(ncid, varid, champ, (/1, 1, l/), (/imdep, jmdep, 1/))
416    CALL ncerr(ierr, fnam)
417    CALL conf_dat2d(title, imdep, jmdep, dlon_ini, dlat_ini, dlon, dlat, &
418         champ, ibar)
[524]419
[1425]420    IF (extrp) CALL extrapol(champ, imdep, jmdep, 999999., .TRUE., .TRUE., 2, &
421         work)
[524]422
[1319]423    IF(ibar.AND..NOT.(mode=='SIC'.AND.flag)) THEN
424      IF(l==1) THEN
[1425]425        WRITE(lunout, *)                                                      &
[1319]426  '-------------------------------------------------------------------------'
[1425]427        WRITE(lunout, *)                                                     &
428  'Utilisation de l''interpolation barycentrique pour '//TRIM(title)//' $$$'
429        WRITE(lunout, *)                                                      &
[1319]430  '-------------------------------------------------------------------------'
431      END IF
432      IF(mode=='RUG') champ=LOG(champ)
[1323]433      CALL inter_barxy(dlon, dlat(:jmdep-1), champ, rlonu(:iim),     &
434                         rlatv, champint)
[1319]435      IF(mode=='RUG') THEN
436        champint=EXP(champint)
437        WHERE(NINT(mask)/=1) champint=0.001
438      END IF
439    ELSE
440      SELECT CASE(mode)
[1323]441        CASE('RUG');       CALL rugosite(imdep, jmdep, dlon, dlat, champ,    &
[1319]442                                    iim, jjp1, rlonv, rlatu, champint, mask)
[1323]443        CASE('SIC');       CALL sea_ice (imdep, jmdep, dlon, dlat, champ,    &
[1319]444                                    iim, jjp1, rlonv, rlatu, champint)
[1425]445        CASE('SST', 'ALB'); CALL grille_m(imdep, jmdep, dlon, dlat, champ,    &
[1319]446                                    iim, jjp1, rlonv, rlatu, champint)
447      END SELECT
448    END IF
[1425]449    champtime(:, :, l)=champint
[1319]450  END DO
[1425]451  ierr=NF90_CLOSE(ncid);                                 CALL ncerr(ierr, fnam)
[524]452
[1425]453  DEALLOCATE(dlon_ini, dlat_ini, dlon, dlat, champ)
[1319]454  IF(extrp) DEALLOCATE(work)
[524]455
[1425]456!--- TIME INTERPOLATION ------------------------------------------------------
457  WRITE(lunout, *)
458  WRITE(lunout, *)'INTERPOLATION TEMPORELLE.'
459  WRITE(lunout, "(2x, ' Vecteur temps en entree: ', 10f6.1)") timeyear
460  WRITE(lunout, "(2x, ' Vecteur temps en sortie de 0 a ', i3)") ndays
461  ALLOCATE(yder(lmdep), champan(iip1, jjp1, ndays))
462  skip = .false.
463  n_extrap = 0
464  DO j=1, jjp1
465    DO i=1, iim
466      yder = pchsp_95(timeyear, champtime(i, j, :), ibeg=2, iend=2, &
467           vc_beg=0., vc_end=0.)
468      CALL pchfe_95(timeyear, champtime(i, j, :), yder, skip, &
469           arth(0., real(ndays_in) / ndays, ndays), champan(i, j, :), ierr)
470      if (ierr < 0) stop 1
471      n_extrap = n_extrap + ierr
[1319]472    END DO
473  END DO
[1425]474  if (n_extrap /= 0) then
475     print *, "get_2Dfield pchfe_95: n_extrap = ", n_extrap
476  end if
477  champan(iip1, :, :)=champan(1, :, :)
478  DEALLOCATE(yder, champtime, timeyear)
[524]479
[1319]480!--- Checking the result
[1425]481  DO j=1, jjp1
482    CALL minmax(iip1, champan(1, j, 10), chmin, chmax)
483    WRITE(lunout, *)' '//TRIM(title)//' au temps 10 ', chmin, chmax, j
[1319]484  END DO
[524]485
[1425]486!--- SPECIAL FILTER FOR SST: SST>271.38 --------------------------------------
[1319]487  IF(mode=='SST') THEN
[1425]488    WRITE(lunout, *) 'Filtrage de la SST: SST >= 271.38'
[1319]489    WHERE(champan<271.38) champan=271.38
490  END IF
[524]491
[1425]492!--- SPECIAL FILTER FOR SIC: 0.0<SIC<1.0 -------------------------------------
[1319]493  IF(mode=='SIC') THEN
[1425]494    WRITE(lunout, *) 'Filtrage de la SIC: 0.0 < Sea-ice < 1.0'
495    IF(.NOT.lCPL) champan(:, :, :)=champan(:, :, :)/100.
496    champan(iip1, :, :)=champan(1, :, :)
[1319]497    WHERE(champan>1.0) champan=1.0
498    WHERE(champan<0.0) champan=0.0
499  END IF
[524]500
[1425]501!--- DYNAMICAL TO PHYSICAL GRID ----------------------------------------------
502  ALLOCATE(champo(klon, ndays))
503  DO k=1, ndays
504    CALL gr_dyn_fi(1, iip1, jjp1, klon, champan(1, 1, k), champo(1, k))
[1319]505  END DO
506  DEALLOCATE(champan)
[1328]507
[1319]508END SUBROUTINE get_2Dfield
509!
510!-------------------------------------------------------------------------------
[524]511
512
513
[1319]514!-------------------------------------------------------------------------------
515!
516FUNCTION year_len(y,cal_in)
517!
518!-------------------------------------------------------------------------------
519  USE ioipsl, ONLY : ioget_calendar,ioconf_calendar,lock_calendar,ioget_year_len
520  IMPLICIT NONE
521!-------------------------------------------------------------------------------
522! Arguments:
523  INTEGER                       :: year_len
524  INTEGER,           INTENT(IN) :: y
525  CHARACTER(LEN=*),  INTENT(IN) :: cal_in
526!-------------------------------------------------------------------------------
527! Local variables:
528  CHARACTER(LEN=20)             :: cal_out              ! calendar (for outputs)
529!-------------------------------------------------------------------------------
530!--- Getting the input calendar to reset at the end of the function
531  CALL ioget_calendar(cal_out)
[524]532
[1319]533!--- Unlocking calendar and setting it to wanted one
534  CALL lock_calendar(.FALSE.); CALL ioconf_calendar(TRIM(cal_in))
[524]535
[1319]536!--- Getting the number of days in this year
537  year_len=ioget_year_len(y)
[524]538
[1319]539!--- Back to original calendar
540  CALL lock_calendar(.FALSE.); CALL ioconf_calendar(TRIM(cal_out))
[524]541
[1319]542END FUNCTION year_len
543!
544!-------------------------------------------------------------------------------
[524]545
546
[1319]547!-------------------------------------------------------------------------------
548!
549FUNCTION mid_months(y,cal_in,nm)
550!
551!-------------------------------------------------------------------------------
552  USE ioipsl, ONLY : ioget_calendar,ioconf_calendar,lock_calendar,ioget_mon_len
553  IMPLICIT NONE
554!-------------------------------------------------------------------------------
555! Arguments:
556  INTEGER,                INTENT(IN) :: y               ! year
557  CHARACTER(LEN=*),       INTENT(IN) :: cal_in          ! calendar
558  INTEGER,                INTENT(IN) :: nm              ! months/year number
559  REAL,    DIMENSION(nm)             :: mid_months      ! mid-month times
560!-------------------------------------------------------------------------------
561! Local variables:
562  CHARACTER(LEN=99)                  :: mess            ! error message
563  CHARACTER(LEN=20)                  :: cal_out         ! calendar (for outputs)
564  INTEGER, DIMENSION(nm)             :: mnth            ! months lengths (days)
565  INTEGER                            :: m               ! months counter
566  INTEGER                            :: nd              ! number of days
567!-------------------------------------------------------------------------------
568  nd=year_len(y,cal_in)
[524]569
[1319]570  IF(nm==12) THEN
[524]571
[1319]572  !--- Getting the input calendar to reset at the end of the function
573    CALL ioget_calendar(cal_out)
[524]574
[1319]575  !--- Unlocking calendar and setting it to wanted one
576    CALL lock_calendar(.FALSE.); CALL ioconf_calendar(TRIM(cal_in))
[524]577
[1319]578  !--- Getting the length of each month
579    DO m=1,nm; mnth(m)=ioget_mon_len(y,m); END DO
[524]580
[1319]581  !--- Back to original calendar
582    CALL lock_calendar(.FALSE.); CALL ioconf_calendar(TRIM(cal_out))
[524]583
[1319]584  ELSE IF(MODULO(nd,nm)/=0) THEN
585    WRITE(mess,'(a,i3,a,i3,a)')'Unconsistent calendar: ',nd,' days/year, but ',&
586      nm,' months/year. Months number should divide days number.'
587    CALL abort_gcm('mid_months',TRIM(mess),1)
[524]588
[1319]589  ELSE
590    mnth=(/(m,m=1,nm,nd/nm)/)
591  END IF
[524]592
[1319]593!--- Mid-months times
594  mid_months(1)=0.5*FLOAT(mnth(1))
595  DO k=2,nm
596    mid_months(k)=mid_months(k-1)+0.5*FLOAT(mnth(k-1)+mnth(k))
597  END DO
[524]598
[1319]599END FUNCTION mid_months
600!
601!-------------------------------------------------------------------------------
[524]602
603
[1319]604!-------------------------------------------------------------------------------
605!
606SUBROUTINE ncerr(ncres,fnam)
607!
608!-------------------------------------------------------------------------------
609! Purpose: NetCDF errors handling.
610!-------------------------------------------------------------------------------
611  USE netcdf, ONLY : NF90_NOERR, NF90_STRERROR
612  IMPLICIT NONE
613!-------------------------------------------------------------------------------
614! Arguments:
615  INTEGER,          INTENT(IN) :: ncres
616  CHARACTER(LEN=*), INTENT(IN) :: fnam
617!-------------------------------------------------------------------------------
618#include "iniprint.h"
619  IF(ncres/=NF90_NOERR) THEN
620    WRITE(lunout,*)'Problem with file '//TRIM(fnam)//' in routine limit_netcdf.'
621    CALL abort_gcm('limit_netcdf',NF90_STRERROR(ncres),1)
622  END IF
[524]623
[1319]624END SUBROUTINE ncerr
625!
626!-------------------------------------------------------------------------------
627
628
629END SUBROUTINE limit_netcdf
Note: See TracBrowser for help on using the repository browser.