source: IOIPSL/trunk/src/histcom.f90 @ 1314

Last change on this file since 1314 was 1028, checked in by bellier, 14 years ago

The positive direction of a vertical axis must be "up" or "down".
If the optional argument pdirect of histvert is not given or is invalid,
the attribute will not be written in the Netcdf file.

  • Property svn:keywords set to Id
File size: 78.7 KB
RevLine 
[4]1MODULE histcom
2!-
[11]3!$Id$
[4]4!-
[386]5! This software is governed by the CeCILL license
6! See IOIPSL/IOIPSL_License_CeCILL.txt
7!-
[4]8  USE netcdf
9!-
[362]10  USE stringop, ONLY : nocomma,cmpblank,findpos,find_str,strlowercase
[440]11  USE mathelp,  ONLY : mathop,moycum,buildop
[362]12  USE fliocom,  ONLY : flio_dom_file,flio_dom_att
[4]13  USE calendar
[429]14  USE errioipsl, ONLY : ipslerr,ipsldbg
[4]15!-
16  IMPLICIT NONE
17!-
18  PRIVATE
[362]19  PUBLIC :: histbeg,histdef,histhori,histvert,histend, &
20 &          histwrite,histclo,histsync,ioconf_modname
[4]21!---------------------------------------------------------------------
22!- Some confusing vocabulary in this code !
23!- =========================================
24!-
25!- A REGULAR grid is a grid which is i,j indexes
26!- and thus it is stored in a 2D matrix.
27!- This is opposed to a IRREGULAR grid which is only in a vector
28!- and where we do not know which neighbors we have.
29!- As a consequence we need the bounds for each grid-cell.
30!-
31!- A RECTILINEAR grid is a special case of a regular grid
32!- in which all longitudes for i constant are equal
33!- and all latitudes for j constant.
34!- In other words we do not need the full 2D matrix
35!- to describe the grid, just two vectors.
36!---------------------------------------------------------------------
[760]37!-
38  INTERFACE histbeg
[962]39    MODULE PROCEDURE histb_reg1d,histb_reg2d,histb_irreg
[760]40  END INTERFACE
41!-
42  INTERFACE histhori
[962]43    MODULE PROCEDURE histh_reg1d,histh_reg2d,histh_irreg
[760]44  END INTERFACE
45!-
[4]46  INTERFACE histwrite
47!---------------------------------------------------------------------
48!- The "histwrite" routines will give the data to the I/O system.
49!- It will trigger the operations to be performed,
50!- and the writting to the file if needed
51!-
52!- We test for the work to be done at this time here so that at a
53!- later stage we can call different operation and write subroutine
54!- for the REAL and INTEGER interfaces
55!-
56!- INPUT
[856]57!- idf      : The ID of the file on which this variable is to be,
[4]58!-            written. The variable should have been defined in
59!-            this file before.
60!- pvarname : The short name of the variable
61!- pitau    : Current timestep
62!- pdata    : The variable, I mean the real data !
63!- nbindex  : The number of indexes provided. If it is equal to
64!-            the size of the full field as provided in histdef
65!-            then nothing is done.
66!- nindex   : The indices used to expand the variable (pdata)
67!-            onto the full field.
68!---------------------------------------------------------------------
69!- histwrite - we have to prepare different type of fields :
70!-             real and integer, 1,2 or 3D
71    MODULE PROCEDURE histwrite_r1d,histwrite_r2d,histwrite_r3d
72  END INTERFACE
73!-
74! Fixed parameter
75!-
[362]76  INTEGER,PARAMETER :: nb_files_max=20,nb_var_max=400, &
77 &                     nb_hax_max=5,nb_zax_max=10,nbopp_max=10
[75]78  REAL,PARAMETER :: missing_val=nf90_fill_real
[752]79  INTEGER,PARAMETER,PUBLIC :: &
80 &  hist_r4=nf90_real4, hist_r8=nf90_real8
[4]81!-
[760]82! Variable derived type
[4]83!-
[760]84TYPE T_D_V
85  INTEGER :: ncvid
86  INTEGER :: nbopp
[1005]87  CHARACTER(LEN=20)  :: v_name,unit_name
88  CHARACTER(LEN=256) :: title,std_name
89  CHARACTER(LEN=80)  :: fullop
90  CHARACTER(LEN=7)   :: topp
[845]91  CHARACTER(LEN=7),DIMENSION(nbopp_max) :: sopp
[760]92  REAL,DIMENSION(nbopp_max) :: scal
93!-External type (for R4/R8)
94  INTEGER :: v_typ
95!-Sizes of the associated grid and zommed area
96  INTEGER,DIMENSION(3) :: scsize,zorig,zsize
97!-Sizes for the data as it goes through the various math operations
98  INTEGER,DIMENSION(3) :: datasz_in = -1
99  INTEGER :: datasz_max = -1
[4]100!-
[760]101  INTEGER :: h_axid,z_axid,t_axid
[4]102!-
[760]103  REAL,DIMENSION(2) :: hist_minmax
104  LOGICAL :: hist_calc_rng=.FALSE.,hist_wrt_rng=.FALSE.
105!-Book keeping of the axes
[1023]106  INTEGER :: tdimid,tbndid=-1,tax_last
107  LOGICAL :: l_bnd
[760]108  CHARACTER(LEN=40) :: tax_name
[4]109!-
[760]110  REAL :: freq_opp,freq_wrt
111  INTEGER :: &
[856]112 &  last_opp,last_wrt,last_opp_chk,last_wrt_chk,nb_opp,nb_wrt
[760]113!- For future optimization
[881]114  REAL,POINTER,DIMENSION(:) :: t_bf
[760]115!#  REAL,ALLOCATABLE,DIMENSION(:) :: V_1_D
116!#  REAL,ALLOCATABLE,DIMENSION(:,:) :: V_2_D
117!#  REAL,ALLOCATABLE,DIMENSION(:,:,:) :: V_3_D
118END TYPE T_D_V
[4]119!-
[760]120! File derived type
[240]121!-
[760]122TYPE :: T_D_F
123!-NETCDF IDs for file
[957]124  INTEGER :: ncfid=-1
[760]125!-Time variables
126  INTEGER :: itau0=0
127  REAL :: date0,deltat
128!-Counter of elements (variables, time-horizontal-vertical axis
129  INTEGER :: n_var=0,n_tax=0,n_hax=0,n_zax=0
[1023]130!-NETCDF dimension IDs for time-[time_bounds]-longitude-latitude
131  INTEGER :: tid,bid,xid,yid
[760]132!-General definitions in the NETCDF file
[962]133  INTEGER,DIMENSION(2) :: full_size=0,slab_ori,slab_siz
[760]134!-The horizontal axes
135  CHARACTER(LEN=25),DIMENSION(nb_hax_max,2) :: hax_name
136!-The vertical axes
137  INTEGER,DIMENSION(nb_zax_max) :: zax_size,zax_ids
138  CHARACTER(LEN=20),DIMENSION(nb_zax_max) :: zax_name
[240]139!-
[760]140  LOGICAL :: regular=.TRUE.
141!-DOMAIN ID
142  INTEGER :: dom_id_svg=-1
[4]143!-
[760]144  TYPE(T_D_V),DIMENSION(nb_var_max) :: W_V
145END TYPE T_D_F
[4]146!-
[760]147TYPE(T_D_F),DIMENSION(nb_files_max),SAVE :: W_F
[4]148!-
149! A list of functions which require special action
150! (Needs to be updated when functions are added
151!  but they are well located here)
152!-
[760]153  CHARACTER(LEN=30),SAVE :: fuchnbout = 'scatter, fill'
[4]154!- Some configurable variables with locks
155  CHARACTER(LEN=80),SAVE :: model_name='An IPSL model'
156  LOGICAL,SAVE :: lock_modname=.FALSE.
157!-
158!===
159CONTAINS
160!===
161!-
[962]162SUBROUTINE histb_reg1d                 &
163 & (pfilename,pim,plon,pjm,plat,       &
164 &  par_orix,par_szx,par_oriy,par_szy, &
165 &  pitau0,pdate0,pdeltat,phoriid,idf,domain_id,mode)
[4]166!---------------------------------------------------------------------
[962]167!- histbeg for 1D regular horizontal coordinates (see histb_all)
[4]168!---------------------------------------------------------------------
169  IMPLICIT NONE
170!-
171  CHARACTER(LEN=*) :: pfilename
172  INTEGER,INTENT(IN) :: pim,pjm
173  REAL,DIMENSION(pim),INTENT(IN) :: plon
174  REAL,DIMENSION(pjm),INTENT(IN) :: plat
175  INTEGER,INTENT(IN):: par_orix,par_szx,par_oriy,par_szy
176  INTEGER,INTENT(IN) :: pitau0
177  REAL,INTENT(IN) :: pdate0,pdeltat
[856]178  INTEGER,INTENT(OUT) :: idf,phoriid
[962]179  INTEGER,INTENT(IN),OPTIONAL :: domain_id
180  CHARACTER(LEN=*),OPTIONAL,INTENT(IN) :: mode
181!---------------------------------------------------------------------
182  CALL histb_all &
183 & (1,pfilename,pim,pjm,pitau0,pdate0,pdeltat,phoriid,idf, &
184 &  x_1d=plon,y_1d=plat, &
185 &  k_orx=par_orix,k_szx=par_szx,k_ory=par_oriy,k_szy=par_szy, &
186 &  domain_id=domain_id,mode=mode)
187!-------------------------
188END SUBROUTINE histb_reg1d
189!===
190SUBROUTINE histb_reg2d &
191 & (pfilename,pim,plon,pjm,plat,       &
192 &  par_orix,par_szx,par_oriy,par_szy, &
193 &  pitau0,pdate0,pdeltat,phoriid,idf,domain_id,mode)
194!---------------------------------------------------------------------
195!- histbeg for 2D regular horizontal coordinates (see histb_all)
196!---------------------------------------------------------------------
197  IMPLICIT NONE
[4]198!-
[962]199  CHARACTER(LEN=*) :: pfilename
200  INTEGER,INTENT(IN) :: pim,pjm
201  REAL,DIMENSION(pim,pjm),INTENT(IN) :: plon,plat
202  INTEGER,INTENT(IN):: par_orix,par_szx,par_oriy,par_szy
203  INTEGER,INTENT(IN) :: pitau0
204  REAL,INTENT(IN) :: pdate0,pdeltat
205  INTEGER,INTENT(OUT) :: idf,phoriid
206  INTEGER,INTENT(IN),OPTIONAL :: domain_id
207  CHARACTER(LEN=*),OPTIONAL,INTENT(IN) :: mode
[4]208!---------------------------------------------------------------------
[962]209  CALL histb_all &
210 & (2,pfilename,pim,pjm,pitau0,pdate0,pdeltat,phoriid,idf,  &
211 &  x_2d=plon,y_2d=plat, &
212 &  k_orx=par_orix,k_szx=par_szx,k_ory=par_oriy,k_szy=par_szy,    &
213 &  domain_id=domain_id,mode=mode)
214!-------------------------
215END SUBROUTINE histb_reg2d
216!===
217SUBROUTINE histb_irreg &
218 &  (pfilename,pim,plon,plon_bounds,plat,plat_bounds, &
219 &   pitau0,pdate0,pdeltat,phoriid,idf,domain_id,mode)
220!---------------------------------------------------------------------
221!- histbeg for irregular horizontal coordinates (see histb_all)
222!---------------------------------------------------------------------
223  IMPLICIT NONE
[4]224!-
[962]225  CHARACTER(LEN=*) :: pfilename
226  INTEGER,INTENT(IN) :: pim
227  REAL,DIMENSION(pim),INTENT(IN) :: plon,plat
228  REAL,DIMENSION(:,:),INTENT(IN) :: plon_bounds,plat_bounds
229  INTEGER,INTENT(IN) :: pitau0
230  REAL,INTENT(IN) :: pdate0,pdeltat
231  INTEGER,INTENT(OUT) :: idf,phoriid
232  INTEGER,INTENT(IN),OPTIONAL :: domain_id
233  CHARACTER(LEN=*),OPTIONAL,INTENT(IN) :: mode
234!---------------------------------------------------------------------
235  CALL histb_all &
236 & (3,pfilename,pim,pim,pitau0,pdate0,pdeltat,phoriid,idf,  &
237 &  x_1d=plon,y_1d=plat,x_bnds=plon_bounds,y_bnds=plat_bounds, &
238 &  domain_id=domain_id,mode=mode)
239!-------------------------
240END SUBROUTINE histb_irreg
[4]241!===
[962]242SUBROUTINE histb_all &
243 & (k_typ,nc_name,pim,pjm,pitau0,pdate0,pdeltat,phoriid,idf, &
244 &  x_1d,y_1d,x_2d,y_2d,k_orx,k_szx,k_ory,k_szy, &
245 &  x_bnds,y_bnds,domain_id,mode)
[4]246!---------------------------------------------------------------------
[962]247!- General interface for horizontal grids.
[4]248!- This subroutine initializes a netcdf file and returns the ID.
249!- It will set up the geographical space on which the data will be
250!- stored and offers the possibility of seting a zoom.
[962]251!- In the case of irregular grids, all the data comes in as vectors
252!- and for the grid we have the coordinates of the 4 corners.
[4]253!- It also gets the global parameters into the I/O subsystem.
254!-
255!- INPUT
256!-
[962]257!- k_typ    : Type of the grid (1 rectilinear, 2 regular, 3 irregular)
258!- nc_name  : Name of the netcdf file to be created
259!- pim      : Size of arrays in longitude direction
260!- pjm      : Size of arrays in latitude direction (pjm=pim for type 3)
[4]261!-
[962]262!- pitau0   : time step at which the history tape starts
263!- pdate0   : The Julian date at which the itau was equal to 0
264!- pdeltat  : Time step, in seconds, of the counter itau
265!-            used in histwrite for instance
[4]266!-
267!- OUTPUT
268!-
[962]269!- phoriid  : Identifier of the horizontal grid
270!- idf      : Identifier of the file
[4]271!-
272!- Optional INPUT arguments
273!-
[962]274!- For rectilinear or irregular grid
275!- x_1d  : The longitudes
276!- y_1d  : The latitudes
277!- For regular grid
278!- x_2d  : The longitudes
279!- y_2d  : The latitudes
280!- One pair (x_1d,y_1d) or (x_2d,y_2d) must be supplied.
[4]281!-
[964]282!- For regular grid (reg1d or reg2d),
[962]283!- the next 4 arguments allow to define a horizontal zoom
284!- for this file. It is assumed that all variables to come
285!- have the same index space. This can not be assumed for
286!- the z axis and thus we define the zoom in histdef.
287!- k_orx  : Origin of the slab of data within the X axis (pim)
288!- k_szx  : Size of the slab of data in X
289!- k_ory  : Origin of the slab of data within the Y axis (pjm)
290!- k_szy  : Size of the slab of data in Y
[4]291!-
[962]292!- For irregular grid.
293!- x_bnds : The boundaries of the grid in longitude
294!- y_bnds : The boundaries of the grid in latitude
[4]295!-
[962]296!- For all grids.
[4]297!-
[962]298!- domain_id  : Domain identifier
299!-
300!- mode       : String of (case insensitive) blank-separated words
301!-              defining the mode used to create the file.
302!-              Supported keywords : 32, 64
303!-              "32/64" defines the offset mode.
304!-              The default offset mode is 64 bits.
305!-              Keywords "NETCDF4" and "CLASSIC" are reserved
306!-              for future use.
[4]307!---------------------------------------------------------------------
308  IMPLICIT NONE
309!-
[962]310  INTEGER,INTENT(IN) :: k_typ
311  CHARACTER(LEN=*),INTENT(IN) :: nc_name
[4]312  INTEGER,INTENT(IN) :: pim,pjm
313  INTEGER,INTENT(IN) :: pitau0
[358]314  REAL,INTENT(IN) :: pdate0,pdeltat
[856]315  INTEGER,INTENT(OUT) :: idf,phoriid
[962]316  REAL,DIMENSION(:),INTENT(IN),OPTIONAL :: x_1d,y_1d
317  REAL,DIMENSION(:,:),INTENT(IN),OPTIONAL :: x_2d,y_2d
318  INTEGER,INTENT(IN),OPTIONAL :: k_orx,k_szx,k_ory,k_szy
319  REAL,DIMENSION(:,:),INTENT(IN),OPTIONAL :: x_bnds,y_bnds
320  INTEGER,INTENT(IN),OPTIONAL :: domain_id
321  CHARACTER(LEN=*),OPTIONAL,INTENT(IN) :: mode
[4]322!-
[760]323  INTEGER :: nfid,iret,m_c
[4]324  CHARACTER(LEN=120) :: file
325  CHARACTER(LEN=30) :: timenow
[962]326  CHARACTER(LEN=11) :: c_nam
[429]327  LOGICAL :: l_dbg
328!---------------------------------------------------------------------
329  CALL ipsldbg (old_status=l_dbg)
[4]330!-
[962]331  IF     (k_typ == 1) THEN
332    c_nam = 'histb_reg1d'
333  ELSEIF (k_typ == 2) THEN
334    c_nam = 'histb_reg2d'
335  ELSEIF (k_typ == 3) THEN
336    c_nam = 'histb_irreg'
337  ELSE
338    CALL ipslerr (3,"histbeg", &
339 &    'Illegal value of k_typ argument','in internal interface','?')
340  ENDIF
[760]341!-
[962]342  IF (l_dbg) WRITE(*,*) c_nam//" 0.0"
343!-
344! Search for a free index
345!-
346  idf = -1
347  DO nfid=1,nb_files_max
348    IF (W_F(nfid)%ncfid < 0) THEN
349      idf = nfid; EXIT;
350    ENDIF
351  ENDDO
352  IF (idf < 0) THEN
[760]353    CALL ipslerr (3,"histbeg", &
354   &  'Table of files too small. You should increase nb_files_max', &
355   &  'in histcom.f90 in order to accomodate all these files',' ')
356  ENDIF
[4]357!-
358! 1.0 Transfering into the common for future use
359!-
[962]360  IF (l_dbg) WRITE(*,*) c_nam//" 1.0"
[4]361!-
[856]362  W_F(idf)%itau0  = pitau0
363  W_F(idf)%date0  = pdate0
364  W_F(idf)%deltat = pdeltat
[4]365!-
366! 2.0 Initializes all variables for this file
367!-
[962]368  IF (l_dbg) WRITE(*,*) c_nam//" 2.0"
[4]369!-
[856]370  W_F(idf)%n_var = 0
371  W_F(idf)%n_tax = 0
372  W_F(idf)%n_hax = 0
373  W_F(idf)%n_zax = 0
[4]374!-
[962]375  IF ( (k_typ == 1).OR.(k_typ == 2) ) THEN
376    W_F(idf)%slab_ori(1:2) = (/ k_orx,k_ory /)
377    W_F(idf)%slab_siz(1:2)  = (/ k_szx,k_szy /)
378  ELSE
379    W_F(idf)%slab_ori(1:2) = (/ 1,1 /)
380    W_F(idf)%slab_siz(1:2) = (/ pim,1 /)
381  ENDIF
[4]382!-
383! 3.0 Opening netcdf file and defining dimensions
384!-
[962]385  IF (l_dbg) WRITE(*,*) c_nam//" 3.0"
[4]386!-
387! Add DOMAIN number and ".nc" suffix in file name if needed
388!-
[962]389  file = nc_name
[4]390  CALL flio_dom_file (file,domain_id)
391!-
[760]392! Check the mode
[962]393!? See fliocom for HDF4 ????????????????????????????????????????????????
394!-
395  IF (PRESENT(mode)) THEN
396    SELECT CASE (TRIM(mode))
397    CASE('32')
[760]398      m_c = NF90_CLOBBER
[962]399    CASE('64')
[760]400      m_c = IOR(NF90_CLOBBER,NF90_64BIT_OFFSET)
401    CASE DEFAULT
402      CALL ipslerr (3,"histbeg", &
[962]403 &      'Invalid argument mode for file :',TRIM(file), &
[760]404 &      'Supported values are 32 or 64')
405    END SELECT
406  ELSE
407    m_c = IOR(NF90_CLOBBER,NF90_64BIT_OFFSET)
408  ENDIF
[4]409!-
[760]410! Create file
411!-
[962]412  iret = NF90_CREATE(file,m_c,nfid)
413!-
414  IF     (k_typ == 1) THEN
415    iret = NF90_DEF_DIM(nfid,'lon',k_szx,W_F(idf)%xid)
416    iret = NF90_DEF_DIM(nfid,'lat',k_szy,W_F(idf)%yid)
417  ELSEIF (k_typ == 2) THEN
418    iret = NF90_DEF_DIM(nfid,'x',k_szx,W_F(idf)%xid)
419    iret = NF90_DEF_DIM(nfid,'y',k_szy,W_F(idf)%yid)
420  ELSEIF (k_typ == 3) THEN
421    iret = NF90_DEF_DIM(nfid,'x',pim,W_F(idf)%xid)
422    W_F(idf)%yid = W_F(idf)%xid
[4]423  ENDIF
424!-
425! 4.0 Declaring the geographical coordinates and other attributes
426!-
[962]427  IF (l_dbg) WRITE(*,*) c_nam//" 4.0"
[4]428!-
[962]429  iret = NF90_PUT_ATT(nfid,NF90_GLOBAL,'Conventions','CF-1.1')
430  iret = NF90_PUT_ATT(nfid,NF90_GLOBAL,'file_name',TRIM(file))
431  iret = NF90_PUT_ATT(nfid,NF90_GLOBAL,'production',TRIM(model_name))
[4]432  lock_modname = .TRUE.
433  CALL ioget_timestamp (timenow)
[962]434  iret = NF90_PUT_ATT(nfid,NF90_GLOBAL,'TimeStamp',TRIM(timenow))
[4]435!-
436! 5.0 Saving some important information on this file in the common
437!-
[962]438  IF (l_dbg) WRITE(*,*) c_nam//" 5.0"
[4]439!-
[240]440  IF (PRESENT(domain_id)) THEN
[856]441    W_F(idf)%dom_id_svg = domain_id
[240]442  ENDIF
[856]443  W_F(idf)%ncfid = nfid
[962]444  IF ( (k_typ == 1).OR.(k_typ == 2) ) THEN
445    W_F(idf)%full_size(1:2) = (/ pim,pjm /)
446    W_F(idf)%regular=.TRUE.
447  ELSEIF (k_typ == 3) THEN
448    W_F(idf)%full_size(1:2) = (/ pim,1 /)
449    W_F(idf)%regular=.FALSE.
450  ENDIF
[4]451!-
452! 6.0 storing the geographical coordinates
453!-
[962]454  IF     (k_typ == 1) THEN
455    CALL histh_all &
456 &   (k_typ,idf,pim,pjm,' ','Default grid',phoriid, &
457 &    x_1d=x_1d,y_1d=y_1d)
458  ELSEIF (k_typ == 2) THEN
459    CALL histh_all &
460 &   (k_typ,idf,pim,pjm,' ','Default grid',phoriid, &
461 &    x_2d=x_2d,y_2d=y_2d)
462  ELSEIF (k_typ == 3) THEN
463    CALL histh_all &
464 &   (k_typ,idf,pim,pim,' ','Default grid',phoriid, &
465 &    x_1d=x_1d,y_1d=y_1d,x_bnds=x_bnds,y_bnds=y_bnds)
466  ENDIF
467!-----------------------
468END SUBROUTINE histb_all
469!===
470SUBROUTINE histh_reg1d &
471 &  (idf,pim,plon,pjm,plat,phname,phtitle,phid)
472!---------------------------------------------------------------------
473!- histhori for 1d regular grid (see histh_all)
474!---------------------------------------------------------------------
475  IMPLICIT NONE
[4]476!-
[962]477  INTEGER,INTENT(IN) :: idf,pim,pjm
478  REAL,INTENT(IN),DIMENSION(:) :: plon,plat
479  CHARACTER(LEN=*),INTENT(IN) :: phname,phtitle
480  INTEGER,INTENT(OUT) :: phid
481!---------------------------------------------------------------------
482  CALL histh_all &
483 & (1,idf,pim,pjm,phname,phtitle,phid,x_1d=plon,y_1d=plat)
484!-------------------------
485END SUBROUTINE histh_reg1d
[4]486!===
[962]487SUBROUTINE histh_reg2d &
488 & (idf,pim,plon,pjm,plat,phname,phtitle,phid)
[4]489!---------------------------------------------------------------------
[962]490!- histhori for 2d regular grid (see histh_all)
491!---------------------------------------------------------------------
492  IMPLICIT NONE
[4]493!-
[962]494  INTEGER,INTENT(IN) :: idf,pim,pjm
495  REAL,INTENT(IN),DIMENSION(:,:) :: plon,plat
496  CHARACTER(LEN=*),INTENT(IN) :: phname,phtitle
497  INTEGER,INTENT(OUT) :: phid
[4]498!---------------------------------------------------------------------
[962]499  CALL histh_all &
500 & (2,idf,pim,pjm,phname,phtitle,phid,x_2d=plon,y_2d=plat)
501!-------------------------
502END SUBROUTINE histh_reg2d
503!===
504SUBROUTINE histh_irreg &
505 & (idf,pim,plon,plon_bounds,plat,plat_bounds,phname,phtitle,phid)
506!---------------------------------------------------------------------
507!- histhori for irregular grid (see histh_all)
508!---------------------------------------------------------------------
[4]509  IMPLICIT NONE
510!-
[962]511  INTEGER,INTENT(IN) :: idf,pim
512  REAL,DIMENSION(:),INTENT(IN) :: plon,plat
[4]513  REAL,DIMENSION(:,:),INTENT(IN) :: plon_bounds,plat_bounds
[962]514  CHARACTER(LEN=*),INTENT(IN) :: phname,phtitle
515  INTEGER,INTENT(OUT) :: phid
[429]516!---------------------------------------------------------------------
[962]517  CALL histh_all &
518 & (3,idf,pim,pim,phname,phtitle,phid, &
519 &  x_1d=plon,y_1d=plat,x_bnds=plon_bounds,y_bnds=plat_bounds)
520!-------------------------
521END SUBROUTINE histh_irreg
[4]522!===
[962]523SUBROUTINE histh_all &
524 & (k_typ,idf,pim,pjm,phname,phtitle,phid, &
525 &  x_1d,y_1d,x_2d,y_2d,x_bnds,y_bnds)
[4]526!---------------------------------------------------------------------
[962]527!- General interface for horizontal grids.
528!- This subroutine is made to declare a new horizontal grid.
[4]529!- It has to have the same number of points as
530!- the original and thus in this routine we will only
531!- add two variable (longitude and latitude).
532!- Any variable in the file can thus point to this pair
533!- through an attribute. This routine is very usefull
534!- to allow staggered grids.
535!-
536!- INPUT
537!-
[962]538!- k_typ   : Type of the grid (1 rectilinear, 2 regular, 3 irregular)
[856]539!- idf     : The id of the file to which the grid should be added
[4]540!- pim     : Size in the longitude direction
[962]541!- pjm     : Size in the latitude direction (pjm=pim for type 3)
[4]542!- phname  : The name of grid
543!- phtitle : The title of the grid
544!-
545!- OUTPUT
546!-
547!- phid    : Id of the created grid
548!-
[962]549!- Optional INPUT arguments
[4]550!-
[962]551!- For rectilinear or irregular grid
552!- x_1d  : The longitudes
553!- y_1d  : The latitudes
554!- For regular grid
555!- x_2d  : The longitudes
556!- y_2d  : The latitudes
557!- One pair (x_1d,y_1d) or (x_2d,y_2d) must be supplied.
[4]558!-
[962]559!- For irregular grid.
560!- x_bnds : The boundaries of the grid in longitude
561!- y_bnds : The boundaries of the grid in latitude
[4]562!---------------------------------------------------------------------
563  IMPLICIT NONE
564!-
[962]565  INTEGER,INTENT(IN) :: k_typ
[856]566  INTEGER,INTENT(IN) :: idf,pim,pjm
[362]567  CHARACTER(LEN=*),INTENT(IN) :: phname,phtitle
[4]568  INTEGER,INTENT(OUT) :: phid
[962]569  REAL,DIMENSION(:),INTENT(IN),OPTIONAL :: x_1d,y_1d
570  REAL,DIMENSION(:,:),INTENT(IN),OPTIONAL :: x_2d,y_2d
571  REAL,DIMENSION(:,:),INTENT(IN),OPTIONAL :: x_bnds,y_bnds
[4]572!-
[362]573  CHARACTER(LEN=25) :: lon_name,lat_name
[962]574  CHARACTER(LEN=30) :: lonbound_name,latbound_name
575  INTEGER :: i_s,i_e
576  INTEGER,DIMENSION(2) :: dims,dims_b
577  INTEGER :: nbbounds
578  INTEGER :: nlonidb,nlatidb,twoid
579  LOGICAL :: transp = .FALSE.
580  REAL,ALLOCATABLE,DIMENSION(:,:) :: bounds_trans
581  REAL :: wmn,wmx
[362]582  INTEGER :: nlonid,nlatid
[962]583  INTEGER :: o_x,o_y,s_x,s_y
[760]584  INTEGER :: iret,nfid
[962]585  CHARACTER(LEN=11) :: c_nam
[429]586  LOGICAL :: l_dbg
[4]587!---------------------------------------------------------------------
[429]588  CALL ipsldbg (old_status=l_dbg)
[4]589!-
[962]590  IF     (k_typ == 1) THEN
591    c_nam = 'histh_reg1d'
592  ELSEIF (k_typ == 2) THEN
593    c_nam = 'histh_reg2d'
594  ELSEIF (k_typ == 3) THEN
595    c_nam = 'histh_irreg'
596  ELSE
597    CALL ipslerr (3,"histhori", &
598 &    'Illegal value of k_typ argument','in internal interface','?')
599  ENDIF
600!-
[4]601! 1.0 Check that all fits in the buffers
602!-
[856]603  IF (    (pim /= W_F(idf)%full_size(1)) &
[962]604 &    .OR.(W_F(idf)%regular.AND.(pjm /= W_F(idf)%full_size(2)))  &
605 &    .OR.(.NOT.W_F(idf)%regular.AND.(W_F(idf)%full_size(2) /= 1)) ) THEN
[4]606    CALL ipslerr (3,"histhori", &
[760]607 &   'The new horizontal grid does not have the same size', &
608 &   'as the one provided to histbeg. This is not yet ', &
609 &   'possible in the hist package.')
[4]610  ENDIF
611!-
612! 1.1 Create all the variables needed
613!-
[962]614  IF (l_dbg) WRITE(*,*) c_nam//" 1.0"
[4]615!-
[856]616  nfid = W_F(idf)%ncfid
[4]617!-
[962]618  IF (k_typ == 3) THEN
619    IF     (SIZE(x_bnds,DIM=1) == pim) THEN
620      nbbounds = SIZE(x_bnds,DIM=2)
621      transp = .TRUE.
622    ELSEIF (SIZE(x_bnds,DIM=2) == pim) THEN
623      nbbounds = SIZE(x_bnds,DIM=1)
624      transp = .FALSE.
625    ELSE
626      CALL ipslerr (3,"histhori", &
627 &     'The boundary variable does not have any axis corresponding', &
628 &     'to the size of the longitude or latitude variable','.')
629    ENDIF
630    ALLOCATE(bounds_trans(nbbounds,pim))
631    iret = NF90_DEF_DIM(nfid,'nbnd',nbbounds,twoid)
632    dims_b(1:2) = (/ twoid,W_F(idf)%xid /)
633  ENDIF
634!-
[856]635  dims(1:2) = (/ W_F(idf)%xid,W_F(idf)%yid /)
[4]636!-
[962]637  IF     (k_typ == 1) THEN
[856]638    IF (W_F(idf)%n_hax == 0) THEN
[4]639      lon_name = 'lon'
640      lat_name = 'lat'
641    ELSE
[962]642      lon_name = 'lon_'//TRIM(phname)
643      lat_name = 'lat_'//TRIM(phname)
[4]644    ENDIF
[962]645  ELSEIF (k_typ == 2) THEN
[856]646    IF (W_F(idf)%n_hax == 0) THEN
[4]647      lon_name = 'nav_lon'
648      lat_name = 'nav_lat'
649    ELSE
[962]650      lon_name = 'nav_lon_'//TRIM(phname)
651      lat_name = 'nav_lat_'//TRIM(phname)
[4]652    ENDIF
[962]653  ELSEIF (k_typ == 3) THEN
654    IF (W_F(idf)%n_hax == 0) THEN
655      lon_name = 'nav_lon'
656      lat_name = 'nav_lat'
657    ELSE
658      lon_name = 'nav_lon_'//TRIM(phname)
659      lat_name = 'nav_lat_'//TRIM(phname)
660    ENDIF
661    lonbound_name = TRIM(lon_name)//'_bounds'
662    latbound_name = TRIM(lat_name)//'_bounds'
[4]663  ENDIF
664!-
665! 1.2 Save the informations
666!-
[856]667  phid = W_F(idf)%n_hax+1
668  W_F(idf)%n_hax = phid
669  W_F(idf)%hax_name(phid,1:2) = (/ lon_name,lat_name /)
[4]670!-
671! 2.0 Longitude
672!-
[962]673  IF (l_dbg) WRITE(*,*) c_nam//" 2.0"
[4]674!-
[962]675  i_s = 1;
676  IF ( (k_typ == 1).OR.(k_typ == 3) ) THEN
677    i_e = 1; wmn = MINVAL(x_1d); wmx = MAXVAL(x_1d);
678  ELSEIF (k_typ == 2) THEN
679    i_e = 2; wmn = MINVAL(x_2d); wmx = MAXVAL(x_2d);
[4]680  ENDIF
[962]681  iret = NF90_DEF_VAR(nfid,lon_name,NF90_REAL4,dims(i_s:i_e),nlonid)
682  IF (k_typ == 1) THEN
683    iret = NF90_PUT_ATT(nfid,nlonid,'axis',"X")
[362]684  ENDIF
[962]685  iret = NF90_PUT_ATT(nfid,nlonid,'standard_name',"longitude")
686  iret = NF90_PUT_ATT(nfid,nlonid,'units',"degrees_east")
687  iret = NF90_PUT_ATT(nfid,nlonid,'valid_min',REAL(wmn,KIND=4))
688  iret = NF90_PUT_ATT(nfid,nlonid,'valid_max',REAL(wmx,KIND=4))
689  iret = NF90_PUT_ATT(nfid,nlonid,'long_name',"Longitude")
690  iret = NF90_PUT_ATT(nfid,nlonid,'nav_model',TRIM(phtitle))
[4]691!-
[962]692  IF (k_typ == 3) THEN
693!---
694!-- 2.1 Longitude bounds
695!---
696    iret = NF90_PUT_ATT(nfid,nlonid,'bounds',TRIM(lonbound_name))
697    iret = NF90_DEF_VAR(nfid,lonbound_name,NF90_REAL4,dims_b(1:2),nlonidb)
698    iret = NF90_PUT_ATT(nfid,nlonidb,'long_name', &
699 &          'Boundaries for coordinate variable '//TRIM(lon_name))
[4]700  ENDIF
701!-
[962]702! 3.0 Latitude
[4]703!-
[962]704  IF (l_dbg) WRITE(*,*) c_nam//" 3.0"
[4]705!-
[962]706  i_e = 2;
707  IF ( (k_typ == 1).OR.(k_typ == 3) ) THEN
708    i_s = 2; wmn = MINVAL(y_1d); wmx = MAXVAL(y_1d);
709  ELSEIF (k_typ == 2) THEN
710    i_s = 1; wmn = MINVAL(y_2d); wmx = MAXVAL(y_2d);
[4]711  ENDIF
[962]712  iret = NF90_DEF_VAR(nfid,lat_name,NF90_REAL4,dims(i_s:i_e),nlatid)
713  IF (k_typ == 1) THEN
714    iret = NF90_PUT_ATT(nfid,nlatid,'axis',"Y")
[4]715  ENDIF
716!-
[962]717  iret = NF90_PUT_ATT(nfid,nlatid,'standard_name',"latitude")
718  iret = NF90_PUT_ATT(nfid,nlatid,'units',"degrees_north")
719  iret = NF90_PUT_ATT(nfid,nlatid,'valid_min',REAL(wmn,KIND=4))
720  iret = NF90_PUT_ATT(nfid,nlatid,'valid_max',REAL(wmx,KIND=4))
721  iret = NF90_PUT_ATT(nfid,nlatid,'long_name',"Latitude")
722  iret = NF90_PUT_ATT(nfid,nlatid,'nav_model',TRIM(phtitle))
[4]723!-
[962]724  IF (k_typ == 3) THEN
725!---
726!-- 3.1 Latitude bounds
727!---
728    iret = NF90_PUT_ATT(nfid,nlatid,'bounds',TRIM(latbound_name))
729    iret = NF90_DEF_VAR(nfid,latbound_name,NF90_REAL4,dims_b(1:2),nlatidb)
730    iret = NF90_PUT_ATT(nfid,nlatidb,'long_name', &
731 &          'Boundaries for coordinate variable '//TRIM(lat_name))
[4]732  ENDIF
733!-
[962]734  iret = NF90_ENDDEF(nfid)
[4]735!-
736! 4.0 storing the geographical coordinates
737!-
[962]738  IF (l_dbg) WRITE(*,*) c_nam//" 4.0"
[4]739!-
[962]740  IF ( (k_typ == 1).OR.(k_typ == 2) ) THEN
741    o_x = W_F(idf)%slab_ori(1)
742    o_y = W_F(idf)%slab_ori(2)
743    s_x = W_F(idf)%slab_siz(1)
744    s_y = W_F(idf)%slab_siz(2)
745!---
746!-- Transfer the longitude and  the latitude
747!---
748    IF     (k_typ == 1) THEN
749      iret = NF90_PUT_VAR(nfid,nlonid,x_1d(o_x:o_x+s_x-1))
750      iret = NF90_PUT_VAR(nfid,nlatid,y_1d(o_y:o_y+s_y-1))
751    ELSEIF (k_typ == 2) THEN
752      iret = NF90_PUT_VAR(nfid,nlonid, &
753 &            x_2d(o_x:o_x+s_x-1,o_y:o_y+s_y-1))
754      iret = NF90_PUT_VAR(nfid,nlatid, &
755 &            y_2d(o_x:o_x+s_x-1,o_y:o_y+s_y-1))
756    ENDIF
757  ELSEIF (k_typ == 3) THEN
758!---
759!-- Transfer the longitude and the longitude bounds
760!---
761    iret = NF90_PUT_VAR(nfid,nlonid,x_1d(1:pim))
762!---
763    IF (transp) THEN
764      bounds_trans = TRANSPOSE(x_bnds)
765    ELSE
766      bounds_trans = x_bnds
767    ENDIF
768    iret = NF90_PUT_VAR(nfid,nlonidb,bounds_trans(1:nbbounds,1:pim))
769!---
770!-- Transfer the latitude and the latitude bounds
771!---
772    iret = NF90_PUT_VAR(nfid,nlatid,y_1d(1:pim))
773!---
774    IF (transp) THEN
775      bounds_trans = TRANSPOSE(y_bnds)
776    ELSE
777      bounds_trans = y_bnds
778    ENDIF
779    iret = NF90_PUT_VAR(nfid,nlatidb,bounds_trans(1:nbbounds,1:pim))
780!---
781    DEALLOCATE(bounds_trans)
[4]782  ENDIF
783!-
[962]784  iret = NF90_REDEF(nfid)
785!-----------------------
786END SUBROUTINE histh_all
[4]787!===
[856]788SUBROUTINE histvert (idf,pzaxname,pzaxtitle,pzaxunit, &
[358]789 &                   pzsize,pzvalues,pzaxid,pdirect)
[4]790!---------------------------------------------------------------------
791!- This subroutine defines a vertical axis and returns it s id.
792!- It gives the user the possibility to the user to define many
793!- different vertical axes. For each variable defined with histdef a
794!- vertical axis can be specified with by it s ID.
795!-
796!- INPUT
797!-
[856]798!- idf      : ID of the file the variable should be archived in
[4]799!- pzaxname : Name of the vertical axis
800!- pzaxtitle: title of the vertical axis
[427]801!- pzaxunit : Units of the vertical axis (no units if blank string)
[4]802!- pzsize   : size of the vertical axis
803!- pzvalues : Coordinate values of the vetical axis
804!-
805!- pdirect  : is an optional argument which allows to specify the
806!-            the positive direction of the axis : up or down.
807!- OUTPUT
808!-
809!- pzaxid   : Returns the ID of the axis.
810!-            Note that this is not the netCDF ID !
811!-
812!- VERSION
813!-
814!---------------------------------------------------------------------
815  IMPLICIT NONE
816!-
[856]817  INTEGER,INTENT(IN) :: idf,pzsize
[4]818  CHARACTER(LEN=*),INTENT(IN) :: pzaxname,pzaxunit,pzaxtitle
819  REAL,INTENT(IN) :: pzvalues(pzsize)
[362]820  INTEGER,INTENT(OUT) :: pzaxid
[75]821  CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: pdirect
[4]822!-
[358]823  INTEGER :: pos,iv,zdimid,zaxid_tmp
824  CHARACTER(LEN=70) :: str71
[4]825  CHARACTER(LEN=20) :: direction
[760]826  INTEGER :: iret,leng,nfid
[429]827  LOGICAL :: l_dbg
[4]828!---------------------------------------------------------------------
[429]829  CALL ipsldbg (old_status=l_dbg)
[4]830!-
831! 1.0 Verifications :
832!    Do we have enough space for an extra axis ?
833!    Is the name already in use ?
834!-
[429]835  IF (l_dbg) WRITE(*,*) "histvert : 1.0 Verifications", &
[4]836 &                      pzaxname,'---',pzaxunit,'---',pzaxtitle
837!-
[1028]838! Direction of the vertical axis. Can we get if from the user.
[4]839!-
840  IF (PRESENT(pdirect)) THEN
841    direction = TRIM(pdirect)
842    CALL strlowercase (direction)
843  ELSE
844    direction = 'unknown'
845  ENDIF
846!-
847! Check the consistency of the attribute
848!-
[1028]849  IF (     PRESENT(pdirect)    &
850 &    .AND.(direction /= 'up') &
851 &    .AND.(direction /= 'down') ) THEN
[4]852    direction = 'unknown'
853    CALL ipslerr (2,"histvert",&
[1028]854 & "The specified positive direction for the vertical axis is invalid.",&
855 & "The value must be up or down.","The attribute will not be written.")
[4]856  ENDIF
857!-
[856]858  IF (W_F(idf)%n_zax+1 > nb_zax_max) THEN
[4]859    CALL ipslerr (3,"histvert", &
860   &  'Table of vertical axes too small. You should increase ',&
[358]861   &  'nb_zax_max in histcom.f90 in order to accomodate all ', &
[4]862   &  'these variables ')
863  ENDIF
864!-
[856]865  iv = W_F(idf)%n_zax
[358]866  IF (iv > 1) THEN
[856]867    CALL find_str (W_F(idf)%zax_name(1:iv-1),pzaxname,pos)
[4]868  ELSE
869    pos = 0
870  ENDIF
871!-
[358]872  IF (pos > 0) THEN
873    WRITE(str71,'("Check variable ",A," in file",I3)') &
[856]874 &    TRIM(pzaxname),idf
[358]875    CALL ipslerr (3,"histvert", &
876 &    "Vertical axis already exists",TRIM(str71), &
877 &    "Can also be a wrong file ID in another declaration")
[4]878  ENDIF
879!-
[856]880  iv = W_F(idf)%n_zax+1
[4]881!-
882! 2.0 Add the information to the file
883!-
[429]884  IF (l_dbg) &
[4]885 &  WRITE(*,*) "histvert : 2.0 Add the information to the file"
886!-
[856]887  nfid = W_F(idf)%ncfid
[4]888!-
889  leng = MIN(LEN_TRIM(pzaxname),20)
[760]890  iret = NF90_DEF_DIM (nfid,pzaxname(1:leng),pzsize,zaxid_tmp)
[881]891  iret = NF90_DEF_VAR (nfid,pzaxname(1:leng),NF90_REAL4, &
[4]892 &                     zaxid_tmp,zdimid)
[760]893  iret = NF90_PUT_ATT (nfid,zdimid,'axis',"Z")
894  iret = NF90_PUT_ATT (nfid,zdimid,'standard_name',"model_level_number")
[4]895  leng = MIN(LEN_TRIM(pzaxunit),20)
[358]896  IF (leng > 0) THEN
[760]897    iret = NF90_PUT_ATT (nfid,zdimid,'units',pzaxunit(1:leng))
[358]898  ENDIF
[1028]899  IF (direction /= 'unknown') THEN
900    iret = NF90_PUT_ATT (nfid,zdimid,'positive',TRIM(direction))
901  ENDIF
[760]902  iret = NF90_PUT_ATT (nfid,zdimid,'valid_min', &
[4]903 &                     REAL(MINVAL(pzvalues(1:pzsize)),KIND=4))
[760]904  iret = NF90_PUT_ATT (nfid,zdimid,'valid_max', &
[4]905 &                     REAL(MAXVAL(pzvalues(1:pzsize)),KIND=4))
906  leng = MIN(LEN_TRIM(pzaxname),20)
[760]907  iret = NF90_PUT_ATT (nfid,zdimid,'title',pzaxname(1:leng))
[4]908  leng = MIN(LEN_TRIM(pzaxtitle),80)
[760]909  iret = NF90_PUT_ATT (nfid,zdimid,'long_name',pzaxtitle(1:leng))
[4]910!-
[760]911  iret = NF90_ENDDEF (nfid)
[4]912!-
[760]913  iret = NF90_PUT_VAR (nfid,zdimid,pzvalues(1:pzsize))
[4]914!-
[760]915  iret = NF90_REDEF (nfid)
[4]916!-
917!- 3.0 add the information to the common
918!-
[429]919  IF (l_dbg) &
[4]920  &  WRITE(*,*) "histvert : 3.0 add the information to the common"
921!-
[856]922  W_F(idf)%n_zax = iv
923  W_F(idf)%zax_size(iv) = pzsize
924  W_F(idf)%zax_name(iv) = pzaxname
925  W_F(idf)%zax_ids(iv) = zaxid_tmp
[760]926  pzaxid = iv
[4]927!----------------------
928END SUBROUTINE histvert
929!===
[806]930SUBROUTINE histdef &
[856]931 &  (idf,pvarname,ptitle,punit, &
[806]932 &   pxsize,pysize,phoriid,pzsize,par_oriz,par_szz,pzid, &
933 &   xtype,popp,pfreq_opp,pfreq_wrt,var_range,standard_name)
[4]934!---------------------------------------------------------------------
935!- With this subroutine each variable to be archived on the history
936!- tape should be declared.
937!-
938!- It gives the user the choise of operation
939!- to be performed on the variables, the frequency of this operation
940!- and finaly the frequency of the archiving.
941!-
942!- INPUT
943!-
[856]944!- idf      : ID of the file the variable should be archived in
[4]945!- pvarname : Name of the variable, short and easy to remember
946!- ptitle   : Full name of the variable
[358]947!- punit    : Units of the variable (no units if blank string)
[4]948!-
949!- The next 3 arguments give the size of that data
950!- that will be passed to histwrite. The zoom will be
951!- done there with the horizontal information obtained
952!- in histbeg and the vertical information to follow.
953!-
954!- pxsize   : Size in X direction (size of the data that will be
955!-            given to histwrite)
956!- pysize   : Size in Y direction
957!- phoriid  : ID of the horizontal axis
958!-
959!- The next two arguments give the vertical zoom to use.
960!-
961!- pzsize   : Size in Z direction (If 1 then no axis is declared
962!-            for this variable and pzid is not used)
963!- par_oriz : Off set of the zoom
964!- par_szz  : Size of the zoom
965!-
966!- pzid     : ID of the vertical axis to use. It has to have
967!-            the size of the zoom.
[806]968!- xtype    : External netCDF type (hist_r4/hist_r8)
[4]969!- popp     : Operation to be performed. The following options
970!-            exist today :
971!- inst : keeps instantaneous values for writting
972!- ave  : Computes the average from call between writes
973!- pfreq_opp: Frequency of this operation (in seconds)
974!- pfreq_wrt: Frequency at which the variable should be
975!-            written (in seconds)
[75]976!- var_range: Range of the variable.
977!-            If the minimum is greater than the maximum,
978!-            the values will be calculated.
[4]979!-
980!- VERSION
981!---------------------------------------------------------------------
982  IMPLICIT NONE
983!-
[856]984  INTEGER,INTENT(IN) :: idf,pxsize,pysize,pzsize,pzid
[806]985  INTEGER,INTENT(IN) :: par_oriz,par_szz,xtype,phoriid
[362]986  CHARACTER(LEN=*),INTENT(IN) :: pvarname,punit,popp,ptitle
987  REAL,INTENT(IN) :: pfreq_opp,pfreq_wrt
[75]988  REAL,DIMENSION(2),OPTIONAL,INTENT(IN) :: var_range
[806]989  CHARACTER(LEN=*),OPTIONAL,INTENT(IN) :: standard_name
[4]990!-
[856]991  INTEGER :: iv
[362]992  CHARACTER(LEN=70) :: str70,str71,str72
[4]993  CHARACTER(LEN=20) :: tmp_name
[358]994  CHARACTER(LEN=40) :: str40
[4]995  CHARACTER(LEN=10) :: str10
996  CHARACTER(LEN=120) :: ex_topps
[845]997  REAL :: un_an,un_jour,test_fopp,test_fwrt
[362]998  INTEGER :: pos,buff_sz
[429]999  LOGICAL :: l_dbg
1000!---------------------------------------------------------------------
1001  CALL ipsldbg (old_status=l_dbg)
[4]1002!-
1003  ex_topps = 'ave, inst, t_min, t_max, t_sum, once, never, l_max, l_min'
1004!-
[856]1005  W_F(idf)%n_var = W_F(idf)%n_var+1
1006  iv = W_F(idf)%n_var
[4]1007!-
[358]1008  IF (iv > nb_var_max) THEN
[4]1009    CALL ipslerr (3,"histdef", &
1010   &  'Table of variables too small. You should increase nb_var_max',&
[358]1011   &  'in histcom.f90 in order to accomodate all these variables', &
[4]1012   &  ' ')
1013  ENDIF
1014!-
1015! 1.0 Transfer informations on the variable to the common
1016!     and verify that it does not already exist
1017!-
[429]1018  IF (l_dbg) WRITE(*,*) "histdef : 1.0"
[4]1019!-
1020  IF (iv > 1) THEN
[856]1021    CALL find_str (W_F(idf)%W_V(1:iv-1)%v_name,pvarname,pos)
[4]1022  ELSE
1023    pos = 0
1024  ENDIF
1025!-
1026  IF (pos > 0) THEN
1027    str70 = "Variable already exists"
[358]1028    WRITE(str71,'("Check variable  ",a," in file",I3)') &
[856]1029 &    TRIM(pvarname),idf
[4]1030    str72 = "Can also be a wrong file ID in another declaration"
[362]1031    CALL ipslerr (3,"histdef",str70,str71,str72)
[4]1032  ENDIF
1033!-
[856]1034  W_F(idf)%W_V(iv)%v_name = pvarname
1035  W_F(idf)%W_V(iv)%title = ptitle
1036  W_F(idf)%W_V(iv)%unit_name = punit
[806]1037  IF (PRESENT(standard_name)) THEN
[856]1038    W_F(idf)%W_V(iv)%std_name = standard_name
[806]1039  ELSE
[856]1040    W_F(idf)%W_V(iv)%std_name = ptitle
[806]1041  ENDIF
[856]1042  tmp_name = W_F(idf)%W_V(iv)%v_name
[4]1043!-
1044! 1.1 decode the operations
1045!-
[856]1046  W_F(idf)%W_V(iv)%fullop = popp
[4]1047  CALL buildop &
[856]1048 &  (TRIM(popp),ex_topps,W_F(idf)%W_V(iv)%topp,missing_val, &
1049 &   W_F(idf)%W_V(iv)%sopp,W_F(idf)%W_V(iv)%scal, &
1050 &   W_F(idf)%W_V(iv)%nbopp)
[4]1051!-
1052! 1.2 If we have an even number of operations
1053!     then we need to add identity
1054!-
[856]1055  IF ( MOD(W_F(idf)%W_V(iv)%nbopp,2) == 0) THEN
1056    W_F(idf)%W_V(iv)%nbopp = W_F(idf)%W_V(iv)%nbopp+1
1057    W_F(idf)%W_V(iv)%sopp(W_F(idf)%W_V(iv)%nbopp) = 'ident'
1058    W_F(idf)%W_V(iv)%scal(W_F(idf)%W_V(iv)%nbopp) = missing_val
[4]1059  ENDIF
1060!-
[752]1061! 1.3 External type of the variable
1062!-
[806]1063  IF (xtype == hist_r8) THEN
[856]1064    W_F(idf)%W_V(iv)%v_typ = hist_r8
[752]1065  ELSE
[856]1066    W_F(idf)%W_V(iv)%v_typ = hist_r4
[752]1067  ENDIF
1068!-
[4]1069! 2.0 Put the size of the variable in the common and check
1070!-
[760]1071  IF (l_dbg) THEN
[856]1072    WRITE(*,*) "histdef : 2.0",idf,iv,W_F(idf)%W_V(iv)%nbopp, &
1073 &    W_F(idf)%W_V(iv)%sopp(1:W_F(idf)%W_V(iv)%nbopp), &
1074 &    W_F(idf)%W_V(iv)%scal(1:W_F(idf)%W_V(iv)%nbopp)
[760]1075  ENDIF
[4]1076!-
[856]1077  W_F(idf)%W_V(iv)%scsize(1:3) = (/ pxsize,pysize,pzsize /)
1078  W_F(idf)%W_V(iv)%zorig(1:3) = &
1079 &  (/ W_F(idf)%slab_ori(1),W_F(idf)%slab_ori(2),par_oriz /)
1080  W_F(idf)%W_V(iv)%zsize(1:3) = &
[962]1081 &  (/ W_F(idf)%slab_siz(1),W_F(idf)%slab_siz(2),par_szz /)
[4]1082!-
[760]1083! Is the size of the full array the same as that of the coordinates ?
[4]1084!-
[856]1085  IF (    (pxsize > W_F(idf)%full_size(1)) &
1086 &    .OR.(pysize > W_F(idf)%full_size(2)) ) THEN
[4]1087!-
1088    str70 = "The size of the variable is different "// &
1089 &          "from the one of the coordinates"
[362]1090    WRITE(str71,'("Size of coordinates :",2I4)') &
[856]1091 &   W_F(idf)%full_size(1),W_F(idf)%full_size(2)
[4]1092    WRITE(str72,'("Size declared for variable ",a," :",2I4)') &
[362]1093 &   TRIM(tmp_name),pxsize,pysize
1094    CALL ipslerr (3,"histdef",str70,str71,str72)
[4]1095  ENDIF
1096!-
[760]1097! Is the size of the zoom smaller than the coordinates ?
[4]1098!-
[962]1099  IF (    (W_F(idf)%full_size(1) < W_F(idf)%slab_siz(1)) &
1100 &    .OR.(W_F(idf)%full_size(2) < W_F(idf)%slab_siz(2)) ) THEN
[4]1101    str70 = &
1102 &   "Size of variable should be greater or equal to those of the zoom"
[362]1103    WRITE(str71,'("Size of XY zoom :",2I4)') &
[962]1104 &   W_F(idf)%slab_siz(1),W_F(idf)%slab_siz(2)
[760]1105    WRITE(str72,'("Size declared for variable ",A," :",2I4)') &
[362]1106 &   TRIM(tmp_name),pxsize,pysize
1107    CALL ipslerr (3,"histdef",str70,str71,str72)
[4]1108  ENDIF
1109!-
1110! 2.1 We store the horizontal grid information with minimal
1111!     and a fall back onto the default grid
1112!-
[856]1113  IF ( (phoriid > 0).AND.(phoriid <= W_F(idf)%n_hax) ) THEN
1114    W_F(idf)%W_V(iv)%h_axid = phoriid
[4]1115  ELSE
[856]1116    W_F(idf)%W_V(iv)%h_axid = 1
[4]1117    CALL ipslerr (2,"histdef", &
1118   &  'We use the default grid for variable as an invalide',&
[362]1119   &  'ID was provided for variable : ',TRIM(pvarname))
[4]1120  ENDIF
1121!-
1122! 2.2 Check the vertical coordinates if needed
1123!-
1124  IF (par_szz > 1) THEN
1125!-
1126!-- Does the vertical coordinate exist ?
1127!-
[856]1128    IF (pzid > W_F(idf)%n_zax) THEN
[4]1129      WRITE(str70, &
[1011]1130 &    '("The vertical coordinate chosen for variable ",A)') &
[4]1131 &     TRIM(tmp_name)
1132      str71 = " Does not exist."
[362]1133      CALL ipslerr (3,"histdef",str70,str71," ")
[4]1134    ENDIF
1135!-
1136!-- Is the vertical size of the variable equal to that of the axis ?
1137!-
[856]1138    IF (par_szz /= W_F(idf)%zax_size(pzid)) THEN
[4]1139      str70 = "The size of the zoom does not correspond "// &
1140 &            "to the size of the chosen vertical axis"
[362]1141      WRITE(str71,'("Size of zoom in z :",I4)') par_szz
[122]1142      WRITE(str72,'("Size declared for axis ",A," :",I4)') &
[856]1143 &     TRIM(W_F(idf)%zax_name(pzid)),W_F(idf)%zax_size(pzid)
[362]1144      CALL ipslerr (3,"histdef",str70,str71,str72)
[4]1145    ENDIF
1146!-
[760]1147!-- Is the zoom smaller that the total size of the variable ?
[4]1148!-
[358]1149    IF (pzsize < par_szz) THEN
[4]1150      str70 = "The vertical size of variable "// &
1151 &            "is smaller than that of the zoom."
[362]1152      WRITE(str71,'("Declared vertical size of data :",I5)') pzsize
[4]1153      WRITE(str72,'("Size of zoom for variable ",a," = ",I5)') &
1154 &     TRIM(tmp_name),par_szz
[362]1155      CALL ipslerr (3,"histdef",str70,str71,str72)
[4]1156    ENDIF
[856]1157    W_F(idf)%W_V(iv)%z_axid = pzid
[4]1158  ELSE
[856]1159    W_F(idf)%W_V(iv)%z_axid = -99
[4]1160  ENDIF
1161!-
[856]1162! 3.0 We get the size of the arrays histwrite will get
1163!     and eventually allocate the time_buffer
[4]1164!-
[856]1165  IF (l_dbg) THEN
1166    WRITE(*,*) "histdef : 3.0"
1167  ENDIF
[4]1168!-
[856]1169  buff_sz = W_F(idf)%W_V(iv)%zsize(1) &
1170 &         *W_F(idf)%W_V(iv)%zsize(2) &
1171 &         *W_F(idf)%W_V(iv)%zsize(3)
[4]1172!-
[856]1173  IF (     (TRIM(W_F(idf)%W_V(iv)%topp) /= "inst") &
1174 &    .AND.(TRIM(W_F(idf)%W_V(iv)%topp) /= "once") &
1175 &    .AND.(TRIM(W_F(idf)%W_V(iv)%topp) /= "never") )THEN
1176    ALLOCATE(W_F(idf)%W_V(iv)%t_bf(buff_sz))
1177    W_F(idf)%W_V(iv)%t_bf(:) = 0.
[429]1178    IF (l_dbg) THEN
[856]1179      WRITE(*,*) "histdef : 3.0 allocating time_buffer for", &
1180 &      " idf = ",idf," iv = ",iv," size = ",buff_sz
[4]1181    ENDIF
1182  ENDIF
1183!-
1184! 4.0 Transfer the frequency of the operations and check
1185!     for validity. We have to pay attention to negative values
1186!     of the frequency which indicate monthly time-steps.
1187!     The strategy is to bring it back to seconds for the tests
1188!-
[429]1189  IF (l_dbg) WRITE(*,*) "histdef : 4.0"
[4]1190!-
[856]1191  W_F(idf)%W_V(iv)%freq_opp = pfreq_opp
1192  W_F(idf)%W_V(iv)%freq_wrt = pfreq_wrt
[4]1193!-
[362]1194  CALL ioget_calendar(un_an,un_jour)
[358]1195  IF (pfreq_opp < 0) THEN
[4]1196    CALL ioget_calendar(un_an)
1197    test_fopp = pfreq_opp*(-1.)*un_an/12.*un_jour
1198  ELSE
1199    test_fopp = pfreq_opp
1200  ENDIF
[358]1201  IF (pfreq_wrt < 0) THEN
[4]1202    CALL ioget_calendar(un_an)
1203    test_fwrt = pfreq_wrt*(-1.)*un_an/12.*un_jour
1204  ELSE
1205    test_fwrt = pfreq_wrt
1206  ENDIF
1207!-
1208! 4.1 Frequency of operations and output should be larger than deltat !
1209!-
[856]1210  IF (test_fopp < W_F(idf)%deltat) THEN
[4]1211    str70 = 'Frequency of operations should be larger than deltat'
1212    WRITE(str71,'("It is not the case for variable ",a," :",F10.4)') &
1213 &   TRIM(tmp_name),pfreq_opp
1214    str72 = "PATCH : frequency set to deltat"
1215!-
[362]1216    CALL ipslerr (2,"histdef",str70,str71,str72)
[4]1217!-
[856]1218    W_F(idf)%W_V(iv)%freq_opp = W_F(idf)%deltat
[4]1219  ENDIF
1220!-
[856]1221  IF (test_fwrt < W_F(idf)%deltat) THEN
[4]1222    str70 = 'Frequency of output should be larger than deltat'
1223    WRITE(str71,'("It is not the case for variable ",a," :",F10.4)') &
1224 &   TRIM(tmp_name),pfreq_wrt
1225    str72 = "PATCH : frequency set to deltat"
1226!-
[362]1227    CALL ipslerr (2,"histdef",str70,str71,str72)
[4]1228!-
[856]1229    W_F(idf)%W_V(iv)%freq_wrt = W_F(idf)%deltat
[4]1230  ENDIF
1231!-
1232! 4.2 First the existence of the operation is tested and then
1233!     its compaticility with the choice of frequencies
1234!-
[856]1235  IF (TRIM(W_F(idf)%W_V(iv)%topp) == "inst") THEN
[4]1236    IF (test_fopp /= test_fwrt) THEN
1237      str70 = 'For instantaneous output the frequency '// &
1238 &            'of operations and output'
1239      WRITE(str71, &
1240 &     '("should be the same, this was not case for variable ",a)') &
1241 &      TRIM(tmp_name)
1242      str72 = "PATCH : The smalest frequency of both is used"
[362]1243      CALL ipslerr (2,"histdef",str70,str71,str72)
[358]1244      IF (test_fopp < test_fwrt) THEN
[856]1245        W_F(idf)%W_V(iv)%freq_opp = pfreq_opp
1246        W_F(idf)%W_V(iv)%freq_wrt = pfreq_opp
[4]1247      ELSE
[856]1248        W_F(idf)%W_V(iv)%freq_opp = pfreq_wrt
1249        W_F(idf)%W_V(iv)%freq_wrt = pfreq_wrt
[4]1250      ENDIF
1251    ENDIF
[856]1252  ELSE IF (INDEX(ex_topps,TRIM(W_F(idf)%W_V(iv)%topp)) > 0) THEN
[4]1253    IF (test_fopp > test_fwrt) THEN
1254      str70 = 'For averages the frequency of operations '// &
[845]1255 &            'should be smaller or equal'
[4]1256      WRITE(str71, &
1257 &     '("to that of output. It is not the case for variable ",a)') &
1258 &     TRIM(tmp_name)
1259      str72 = 'PATCH : The output frequency is used for both'
[362]1260      CALL ipslerr (2,"histdef",str70,str71,str72)
[856]1261      W_F(idf)%W_V(iv)%freq_opp = pfreq_wrt
[4]1262    ENDIF
1263  ELSE
[845]1264    WRITE (str70,'("Operation on variable ",A," is unknown")') &
1265 &   TRIM(tmp_name)
1266    WRITE (str71,'("operation requested is :",A)') &
[856]1267 &   W_F(idf)%W_V(iv)%topp
1268    WRITE (str72,'("File ID :",I3)') idf
[362]1269    CALL ipslerr (3,"histdef",str70,str71,str72)
[4]1270  ENDIF
1271!-
1272! 5.0 Initialize other variables of the common
1273!-
[429]1274  IF (l_dbg) WRITE(*,*) "histdef : 5.0"
[4]1275!-
[856]1276  W_F(idf)%W_V(iv)%hist_wrt_rng = (PRESENT(var_range))
1277  IF (W_F(idf)%W_V(iv)%hist_wrt_rng) THEN
1278    W_F(idf)%W_V(iv)%hist_calc_rng = (var_range(1) > var_range(2))
1279    IF (W_F(idf)%W_V(iv)%hist_calc_rng) THEN
1280      W_F(idf)%W_V(iv)%hist_minmax(1:2) = &
[362]1281 &      (/ ABS(missing_val),-ABS(missing_val) /)
[75]1282    ELSE
[856]1283      W_F(idf)%W_V(iv)%hist_minmax(1:2) = var_range(1:2)
[75]1284    ENDIF
1285  ENDIF
[4]1286!-
[856]1287! - freq_opp(idf,iv)/2./deltat(idf)
1288  W_F(idf)%W_V(iv)%last_opp = W_F(idf)%itau0
1289! - freq_wrt(idf,iv)/2./deltat(idf)
1290  W_F(idf)%W_V(iv)%last_wrt = W_F(idf)%itau0
1291! - freq_opp(idf,iv)/2./deltat(idf)
1292  W_F(idf)%W_V(iv)%last_opp_chk = W_F(idf)%itau0
1293! - freq_wrt(idf,iv)/2./deltat(idf)
1294  W_F(idf)%W_V(iv)%last_wrt_chk = W_F(idf)%itau0
1295  W_F(idf)%W_V(iv)%nb_opp = 0
1296  W_F(idf)%W_V(iv)%nb_wrt = 0
[4]1297!-
1298! 6.0 Get the time axis for this variable
1299!-
[429]1300  IF (l_dbg) WRITE(*,*) "histdef : 6.0"
[4]1301!-
1302! No time axis for once, l_max, l_min or never operation
1303!-
[856]1304  IF (     (TRIM(W_F(idf)%W_V(iv)%topp) /= 'once')  &
1305 &    .AND.(TRIM(W_F(idf)%W_V(iv)%topp) /= 'never') &
1306 &    .AND.(TRIM(W_F(idf)%W_V(iv)%topp) /= 'l_max') &
1307 &    .AND.(TRIM(W_F(idf)%W_V(iv)%topp) /= 'l_min') ) THEN
[1011]1308    IF (TRIM(W_F(idf)%W_V(iv)%topp) == 'inst') THEN
1309      str10 = 't_inst_'
1310    ELSE
1311      str10 = 't_op_'
1312    ENDIF
1313    IF (W_F(idf)%W_V(iv)%freq_wrt > 0) THEN
1314      WRITE (UNIT=str40,FMT='(A,I8.8)') &
1315&      TRIM(str10),INT(W_F(idf)%W_V(iv)%freq_wrt)
1316    ELSE
1317      WRITE (UNIT=str40,FMT='(A,I2.2,"month")') &
1318&      TRIM(str10),ABS(INT(W_F(idf)%W_V(iv)%freq_wrt))
1319    ENDIF
1320    CALL find_str (W_F(idf)%W_V(1:W_F(idf)%n_tax)%tax_name,str40,pos)
[358]1321    IF (pos < 0) THEN
[856]1322      W_F(idf)%n_tax = W_F(idf)%n_tax+1
[1023]1323      W_F(idf)%W_V(iv)%l_bnd = &
1324 &      (TRIM(W_F(idf)%W_V(iv)%topp) /= 'inst')
[856]1325      W_F(idf)%W_V(W_F(idf)%n_tax)%tax_name = str40
1326      W_F(idf)%W_V(W_F(idf)%n_tax)%tax_last = 0
1327      W_F(idf)%W_V(iv)%t_axid = W_F(idf)%n_tax
[4]1328    ELSE
[856]1329      W_F(idf)%W_V(iv)%t_axid = pos
[4]1330    ENDIF
1331  ELSE
[845]1332    IF (l_dbg) THEN
[856]1333      WRITE(*,*) "histdef : 7.0 ",TRIM(W_F(idf)%W_V(iv)%topp),'----'
[845]1334    ENDIF
[856]1335    W_F(idf)%W_V(iv)%t_axid = -99
[4]1336  ENDIF
1337!-
1338! 7.0 prepare frequence of writing and operation
1339!     for never or once operation
1340!-
[856]1341  IF (    (TRIM(W_F(idf)%W_V(iv)%topp) == 'once')  &
1342 &    .OR.(TRIM(W_F(idf)%W_V(iv)%topp) == 'never') ) THEN
1343    W_F(idf)%W_V(iv)%freq_opp = 0.
1344    W_F(idf)%W_V(iv)%freq_wrt = 0.
[4]1345  ENDIF
1346!---------------------
1347END SUBROUTINE histdef
1348!===
[856]1349SUBROUTINE histend (idf)
[4]1350!---------------------------------------------------------------------
1351!- This subroutine end the decalaration of variables and sets the
1352!- time axes in the netcdf file and puts it into the write mode.
1353!-
1354!- INPUT
1355!-
[856]1356!- idf : ID of the file to be worked on
[4]1357!-
1358!- VERSION
1359!-
1360!---------------------------------------------------------------------
1361  IMPLICIT NONE
1362!-
[856]1363  INTEGER,INTENT(IN) :: idf
[4]1364!-
[760]1365  INTEGER :: nfid,nvid,iret,ndim,iv,itx,ziv,itax,dim_cnt
[362]1366  INTEGER,DIMENSION(4) :: dims
1367  INTEGER :: year,month,day,hours,minutes
[4]1368  REAL :: sec
1369  REAL :: rtime0
1370  CHARACTER(LEN=30) :: str30
[1023]1371  CHARACTER(LEN=35) :: str35
[4]1372  CHARACTER(LEN=120) :: assoc
1373  CHARACTER(LEN=70) :: str70
1374  CHARACTER(LEN=3),DIMENSION(12) :: cal =   &
1375 &  (/ 'JAN','FEB','MAR','APR','MAY','JUN', &
1376 &     'JUL','AUG','SEP','OCT','NOV','DEC' /)
1377  CHARACTER(LEN=7) :: tmp_opp
[1023]1378  LOGICAL :: l_b
[429]1379  LOGICAL :: l_dbg
1380!---------------------------------------------------------------------
1381  CALL ipsldbg (old_status=l_dbg)
[4]1382!-
[856]1383  nfid = W_F(idf)%ncfid
[4]1384!-
1385! 1.0 Create the time axes
1386!-
[429]1387  IF (l_dbg) WRITE(*,*) "histend : 1.0"
[1023]1388!-
1389! 1.1 Define the time dimensions needed for this file
1390!-
[760]1391  iret = NF90_DEF_DIM (nfid,'time_counter', &
[856]1392 &                     NF90_UNLIMITED,W_F(idf)%tid)
[1023]1393  DO iv=1,W_F(idf)%n_var
1394    IF (W_F(idf)%W_V(iv)%l_bnd) THEN
1395      iret = NF90_DEF_DIM (nfid,'tbnds',2,W_F(idf)%bid)
1396      EXIT
1397    ENDIF
1398  ENDDO
[4]1399!-
[1023]1400! 1.2 Define all the time axes needed for this file
[4]1401!-
[856]1402  DO itx=1,W_F(idf)%n_tax
1403    dims(1) = W_F(idf)%tid
[1023]1404    l_b = (INDEX(W_F(idf)%W_V(itx)%tax_name,"t_op_") == 1)
[1027]1405    IF (itx > 1) THEN
[1011]1406      str30 = W_F(idf)%W_V(itx)%tax_name
[4]1407    ELSE
1408      str30 = "time_counter"
1409    ENDIF
[1023]1410    IF (l_b) THEN
1411      str35 = TRIM(str30)//'_bnds'
1412    ENDIF
[1011]1413    iret = NF90_DEF_VAR (nfid,TRIM(str30),NF90_REAL8, &
1414 &          dims(1),W_F(idf)%W_V(itx)%tdimid)
1415    IF (itx <= 1) THEN
[856]1416      iret = NF90_PUT_ATT (nfid,W_F(idf)%W_V(itx)%tdimid,'axis',"T")
[362]1417    ENDIF
[856]1418    iret = NF90_PUT_ATT (nfid,W_F(idf)%W_V(itx)%tdimid, &
[1011]1419 &          'standard_name',"time")
[4]1420!---
1421!   To transform the current itau into a real date and take it
1422!   as the origin of the file requires the time counter to change.
1423!   Thus it is an operation the user has to ask for.
1424!   This function should thus only be re-instated
1425!   if there is a ioconf routine to control it.
1426!---
[856]1427!-- rtime0 = itau2date(itau0(idf),date0(idf),deltat(idf))
1428    rtime0 = W_F(idf)%date0
[4]1429!-
[362]1430    CALL ju2ymds(rtime0,year,month,day,sec)
[4]1431!---
1432!   Catch any error induced by a change in calendar !
1433!---
1434    IF (year < 0) THEN
1435      year = 2000+year
1436    ENDIF
1437!-
1438    hours = INT(sec/(60.*60.))
1439    minutes = INT((sec-hours*60.*60.)/60.)
1440    sec = sec-(hours*60.*60.+minutes*60.)
1441!-
[240]1442    WRITE (UNIT=str70, &
1443 &   FMT='(A,I4.4,"-",I2.2,"-",I2.2," ",I2.2,":",I2.2,":",I2.2)') &
1444 &    'seconds since ',year,month,day,hours,minutes,INT(sec)
[856]1445    iret = NF90_PUT_ATT (nfid,W_F(idf)%W_V(itx)%tdimid, &
[760]1446 &           'units',TRIM(str70))
[4]1447!-
1448    CALL ioget_calendar (str30)
[856]1449    iret = NF90_PUT_ATT (nfid,W_F(idf)%W_V(itx)%tdimid, &
[760]1450 &           'calendar',TRIM(str30))
[4]1451!-
[856]1452    iret = NF90_PUT_ATT (nfid,W_F(idf)%W_V(itx)%tdimid, &
[760]1453 &           'title','Time')
[4]1454!-
[856]1455    iret = NF90_PUT_ATT (nfid,W_F(idf)%W_V(itx)%tdimid, &
[760]1456 &           'long_name','Time axis')
[4]1457!-
[240]1458    WRITE (UNIT=str70, &
1459 &   FMT='(" ",I4.4,"-",A3,"-",I2.2," ",I2.2,":",I2.2,":",I2.2)') &
1460 &    year,cal(month),day,hours,minutes,INT(sec)
[856]1461    iret = NF90_PUT_ATT (nfid,W_F(idf)%W_V(itx)%tdimid, &
[760]1462 &           'time_origin',TRIM(str70))
[1023]1463!---
1464    IF (l_b) THEN
1465      iret = NF90_PUT_ATT (nfid,W_F(idf)%W_V(itx)%tdimid, &
1466 &             'bounds',TRIM(str35))
1467      dims(1:2) = (/ W_F(idf)%bid,W_F(idf)%tid /)
1468      iret = NF90_DEF_VAR (nfid,TRIM(str35),NF90_REAL8, &
1469 &            dims(1:2),W_F(idf)%W_V(itx)%tbndid)
1470    ENDIF
[4]1471  ENDDO
1472!-
1473! 2.0 declare the variables
1474!-
[429]1475  IF (l_dbg) WRITE(*,*) "histend : 2.0"
[4]1476!-
[856]1477  DO iv=1,W_F(idf)%n_var
[4]1478!---
[856]1479    itax = W_F(idf)%W_V(iv)%t_axid
[4]1480!---
[856]1481    IF (W_F(idf)%regular) THEN
1482      dims(1:2) = (/ W_F(idf)%xid,W_F(idf)%yid /)
[4]1483      dim_cnt = 2
1484    ELSE
[856]1485      dims(1) = W_F(idf)%xid
[4]1486      dim_cnt = 1
1487    ENDIF
1488!---
[856]1489    tmp_opp = W_F(idf)%W_V(iv)%topp
1490    ziv = W_F(idf)%W_V(iv)%z_axid
[4]1491!---
1492!   2.1 dimension of field
1493!---
[358]1494    IF ((TRIM(tmp_opp) /= 'never')) THEN
[4]1495      IF (     (TRIM(tmp_opp) /= 'once')  &
1496     &    .AND.(TRIM(tmp_opp) /= 'l_max') &
1497     &    .AND.(TRIM(tmp_opp) /= 'l_min') ) THEN
1498        IF (ziv == -99) THEN
1499          ndim = dim_cnt+1
[856]1500          dims(dim_cnt+1:dim_cnt+2) = (/ W_F(idf)%tid,0 /)
[4]1501        ELSE
1502          ndim = dim_cnt+2
[760]1503          dims(dim_cnt+1:dim_cnt+2) = &
[856]1504 &         (/ W_F(idf)%zax_ids(ziv),W_F(idf)%tid /)
[4]1505        ENDIF
1506      ELSE
1507        IF (ziv == -99) THEN
1508          ndim = dim_cnt
[362]1509          dims(dim_cnt+1:dim_cnt+2) = (/ 0,0 /)
[4]1510        ELSE
1511          ndim = dim_cnt+1
[856]1512          dims(dim_cnt+1:dim_cnt+2) = (/ W_F(idf)%zax_ids(ziv),0 /)
[4]1513        ENDIF
1514      ENDIF
1515!-
[856]1516      iret = NF90_DEF_VAR (nfid,TRIM(W_F(idf)%W_V(iv)%v_name), &
1517 &             W_F(idf)%W_V(iv)%v_typ,dims(1:ABS(ndim)),nvid)
[4]1518!-
[856]1519      W_F(idf)%W_V(iv)%ncvid = nvid
[4]1520!-
[856]1521      IF (LEN_TRIM(W_F(idf)%W_V(iv)%unit_name) > 0) THEN
[760]1522        iret = NF90_PUT_ATT (nfid,nvid,'units', &
[856]1523 &                           TRIM(W_F(idf)%W_V(iv)%unit_name))
[358]1524      ENDIF
[760]1525      iret = NF90_PUT_ATT (nfid,nvid,'standard_name', &
[856]1526 &                         TRIM(W_F(idf)%W_V(iv)%std_name))
[4]1527!-
[879]1528      IF (W_F(idf)%W_V(iv)%v_typ == hist_r8) THEN
1529        iret = NF90_PUT_ATT (nfid,nvid,'_FillValue',NF90_FILL_REAL8)
1530      ELSE
1531        iret = NF90_PUT_ATT (nfid,nvid,'_FillValue',NF90_FILL_REAL4)
1532      ENDIF
[856]1533      IF (W_F(idf)%W_V(iv)%hist_wrt_rng) THEN
[881]1534        IF (W_F(idf)%W_V(iv)%v_typ == hist_r8) THEN
1535          iret = NF90_PUT_ATT (nfid,nvid,'valid_min', &
1536 &                 REAL(W_F(idf)%W_V(iv)%hist_minmax(1),KIND=8))
1537          iret = NF90_PUT_ATT (nfid,nvid,'valid_max', &
1538 &                 REAL(W_F(idf)%W_V(iv)%hist_minmax(2),KIND=8))
1539        ELSE
1540          iret = NF90_PUT_ATT (nfid,nvid,'valid_min', &
1541 &                 REAL(W_F(idf)%W_V(iv)%hist_minmax(1),KIND=4))
1542          iret = NF90_PUT_ATT (nfid,nvid,'valid_max', &
1543 &                 REAL(W_F(idf)%W_V(iv)%hist_minmax(2),KIND=4))
1544        ENDIF
[75]1545      ENDIF
[760]1546      iret = NF90_PUT_ATT (nfid,nvid,'long_name', &
[856]1547 &                         TRIM(W_F(idf)%W_V(iv)%title))
[760]1548      iret = NF90_PUT_ATT (nfid,nvid,'online_operation', &
[856]1549 &                         TRIM(W_F(idf)%W_V(iv)%fullop))
[4]1550!-
1551      SELECT CASE(ndim)
[240]1552      CASE(-3,2:4)
[4]1553      CASE DEFAULT
1554        CALL ipslerr (3,"histend", &
1555       &  'less than 2 or more than 4 dimensions are not', &
1556       &  'allowed at this stage',' ')
1557      END SELECT
1558!-
[856]1559      assoc=TRIM(W_F(idf)%hax_name(W_F(idf)%W_V(iv)%h_axid,2)) &
1560 &   //' '//TRIM(W_F(idf)%hax_name(W_F(idf)%W_V(iv)%h_axid,1))
[362]1561!-
[856]1562      ziv = W_F(idf)%W_V(iv)%z_axid
[4]1563      IF (ziv > 0) THEN
[856]1564        str30 = W_F(idf)%zax_name(ziv)
[4]1565        assoc = TRIM(str30)//' '//TRIM(assoc)
1566      ENDIF
1567!-
1568      IF (itax > 0) THEN
[1027]1569        IF (itax > 1) THEN
[1023]1570          str30 = W_F(idf)%W_V(itax)%tax_name
[4]1571        ELSE
1572          str30 = "time_counter"
1573        ENDIF
1574        assoc = TRIM(str30)//' '//TRIM(assoc)
1575!-
[429]1576        IF (l_dbg) THEN
[4]1577          WRITE(*,*) "histend : 2.0.n, freq_opp, freq_wrt", &
[856]1578 &          W_F(idf)%W_V(iv)%freq_opp,W_F(idf)%W_V(iv)%freq_wrt
[4]1579        ENDIF
1580!-
[760]1581        iret = NF90_PUT_ATT (nfid,nvid,'interval_operation', &
[856]1582 &                           REAL(W_F(idf)%W_V(iv)%freq_opp,KIND=4))
[760]1583        iret = NF90_PUT_ATT (nfid,nvid,'interval_write', &
[856]1584 &                           REAL(W_F(idf)%W_V(iv)%freq_wrt,KIND=4))
[4]1585      ENDIF
[760]1586      iret = NF90_PUT_ATT (nfid,nvid,'coordinates',TRIM(assoc))
[4]1587    ENDIF
1588  ENDDO
1589!-
[240]1590! 2.2 Add DOMAIN attributes if needed
1591!-
[856]1592  IF (W_F(idf)%dom_id_svg >= 0) THEN
1593    CALL flio_dom_att (nfid,W_F(idf)%dom_id_svg)
[240]1594  ENDIF
1595!-
[358]1596! 3.0 Put the netcdf file into write mode
[4]1597!-
[429]1598  IF (l_dbg) WRITE(*,*) "histend : 3.0"
[4]1599!-
[760]1600  iret = NF90_ENDDEF (nfid)
[4]1601!-
1602! 4.0 Give some informations to the user
1603!-
[429]1604  IF (l_dbg) WRITE(*,*) "histend : 4.0"
[4]1605!-
[856]1606  WRITE(str70,'("All variables have been initialized on file :",I3)') idf
[4]1607  CALL ipslerr (1,'histend',str70,'',' ')
1608!---------------------
1609END SUBROUTINE histend
1610!===
[856]1611SUBROUTINE histwrite_r1d (idf,pvarname,pitau,pdata,nbindex,nindex)
[4]1612!---------------------------------------------------------------------
1613  IMPLICIT NONE
1614!-
[856]1615  INTEGER,INTENT(IN) :: idf,pitau,nbindex
[362]1616  INTEGER,DIMENSION(nbindex),INTENT(IN) :: nindex
[4]1617  REAL,DIMENSION(:),INTENT(IN) :: pdata
1618  CHARACTER(LEN=*),INTENT(IN) :: pvarname
1619!---------------------------------------------------------------------
[856]1620  CALL histw_rnd (idf,pvarname,pitau,nbindex,nindex,pdata_1d=pdata)
[4]1621!---------------------------
1622END SUBROUTINE histwrite_r1d
1623!===
[856]1624SUBROUTINE histwrite_r2d (idf,pvarname,pitau,pdata,nbindex,nindex)
[4]1625!---------------------------------------------------------------------
1626  IMPLICIT NONE
1627!-
[856]1628  INTEGER,INTENT(IN) :: idf,pitau,nbindex
[362]1629  INTEGER,DIMENSION(nbindex),INTENT(IN) :: nindex
[4]1630  REAL,DIMENSION(:,:),INTENT(IN) :: pdata
1631  CHARACTER(LEN=*),INTENT(IN) :: pvarname
1632!---------------------------------------------------------------------
[856]1633  CALL histw_rnd (idf,pvarname,pitau,nbindex,nindex,pdata_2d=pdata)
[4]1634!---------------------------
1635END SUBROUTINE histwrite_r2d
1636!===
[856]1637SUBROUTINE histwrite_r3d (idf,pvarname,pitau,pdata,nbindex,nindex)
[4]1638!---------------------------------------------------------------------
1639  IMPLICIT NONE
1640!-
[856]1641  INTEGER,INTENT(IN) :: idf,pitau,nbindex
[362]1642  INTEGER,DIMENSION(nbindex),INTENT(IN) :: nindex
[4]1643  REAL,DIMENSION(:,:,:),INTENT(IN) :: pdata
1644  CHARACTER(LEN=*),INTENT(IN) :: pvarname
[362]1645!---------------------------------------------------------------------
[856]1646  CALL histw_rnd (idf,pvarname,pitau,nbindex,nindex,pdata_3d=pdata)
[362]1647!---------------------------
1648END SUBROUTINE histwrite_r3d
1649!===
[856]1650SUBROUTINE histw_rnd (idf,pvarname,pitau,nbindex,nindex, &
[362]1651  &                   pdata_1d,pdata_2d,pdata_3d)
1652!---------------------------------------------------------------------
1653  IMPLICIT NONE
[4]1654!-
[856]1655  INTEGER,INTENT(IN) :: idf,pitau,nbindex
[362]1656  INTEGER,DIMENSION(nbindex),INTENT(IN) :: nindex
1657  CHARACTER(LEN=*),INTENT(IN) :: pvarname
1658  REAL,DIMENSION(:),INTENT(IN),OPTIONAL     :: pdata_1d
1659  REAL,DIMENSION(:,:),INTENT(IN),OPTIONAL   :: pdata_2d
1660  REAL,DIMENSION(:,:,:),INTENT(IN),OPTIONAL :: pdata_3d
1661!-
1662  LOGICAL :: do_oper,do_write,largebuf,l1d,l2d,l3d
[856]1663  INTEGER :: iv,io,nbpt_out
[362]1664  INTEGER              :: nbpt_in1
1665  INTEGER,DIMENSION(2) :: nbpt_in2
1666  INTEGER,DIMENSION(3) :: nbpt_in3
[856]1667  REAL,ALLOCATABLE,DIMENSION(:),SAVE :: tbf_1
[4]1668  CHARACTER(LEN=7) :: tmp_opp
[362]1669  CHARACTER(LEN=13) :: c_nam
[429]1670  LOGICAL :: l_dbg
1671!---------------------------------------------------------------------
1672  CALL ipsldbg (old_status=l_dbg)
[4]1673!-
[362]1674  l1d=PRESENT(pdata_1d); l2d=PRESENT(pdata_2d); l3d=PRESENT(pdata_3d);
1675  IF      (l1d) THEN
1676    c_nam = 'histwrite_r1d'
1677  ELSE IF (l2d) THEN
1678    c_nam = 'histwrite_r2d'
1679  ELSE IF (l3d) THEN
1680    c_nam = 'histwrite_r3d'
1681  ENDIF
[4]1682!-
[953]1683  IF (l_dbg) THEN
1684    WRITE(*,*) "histwrite : ",c_nam
1685  ENDIF
1686!-
[4]1687! 1.0 Try to catch errors like specifying the wrong file ID.
1688!     Thanks Marine for showing us what errors users can make !
1689!-
[962]1690  IF ( (idf < 1).OR.(idf > nb_files_max) ) THEN
[4]1691    CALL ipslerr (3,"histwrite", &
1692 &    'Illegal file ID in the histwrite of variable',pvarname,' ')
1693  ENDIF
1694!-
1695! 1.1 Find the id of the variable to be written and the real time
1696!-
[856]1697  CALL histvar_seq (idf,pvarname,iv)
[4]1698!-
1699! 2.0 do nothing for never operation
1700!-
[856]1701  tmp_opp = W_F(idf)%W_V(iv)%topp
[4]1702!-
1703  IF (TRIM(tmp_opp) == "never") THEN
[856]1704    W_F(idf)%W_V(iv)%last_opp_chk = -99
1705    W_F(idf)%W_V(iv)%last_wrt_chk = -99
[4]1706  ENDIF
1707!-
1708! 3.0 We check if we need to do an operation
1709!-
[856]1710  IF (W_F(idf)%W_V(iv)%last_opp_chk == pitau) THEN
[4]1711    CALL ipslerr (3,"histwrite", &
[640]1712 &    'This variable has already been analysed at the present', &
1713 &    'time step',TRIM(pvarname))
[4]1714  ENDIF
1715!-
1716  CALL isittime &
[856]1717 &  (pitau,W_F(idf)%date0,W_F(idf)%deltat, &
1718 &   W_F(idf)%W_V(iv)%freq_opp, &
1719 &   W_F(idf)%W_V(iv)%last_opp, &
1720 &   W_F(idf)%W_V(iv)%last_opp_chk,do_oper)
[4]1721!-
1722! 4.0 We check if we need to write the data
1723!-
[856]1724  IF (W_F(idf)%W_V(iv)%last_wrt_chk == pitau) THEN
[4]1725    CALL ipslerr (3,"histwrite", &
[760]1726 &    'This variable as already been written for the present', &
1727 &    'time step',' ')
[4]1728  ENDIF
1729!-
1730  CALL isittime &
[856]1731 &  (pitau,W_F(idf)%date0,W_F(idf)%deltat, &
1732 &   W_F(idf)%W_V(iv)%freq_wrt, &
1733 &   W_F(idf)%W_V(iv)%last_wrt, &
1734 &   W_F(idf)%W_V(iv)%last_wrt_chk,do_write)
[4]1735!-
1736! 5.0 histwrite called
1737!-
1738  IF (do_oper.OR.do_write) THEN
1739!-
1740!-- 5.1 Get the sizes of the data we will handle
1741!-
[856]1742    IF (W_F(idf)%W_V(iv)%datasz_in(1) <= 0) THEN
[4]1743!---- There is the risk here that the user has over-sized the array.
1744!---- But how can we catch this ?
1745!---- In the worst case we will do impossible operations
1746!---- on part of the data !
[856]1747      W_F(idf)%W_V(iv)%datasz_in(1:3) = -1
[362]1748      IF      (l1d) THEN
[856]1749        W_F(idf)%W_V(iv)%datasz_in(1) = SIZE(pdata_1d)
[362]1750      ELSE IF (l2d) THEN
[856]1751        W_F(idf)%W_V(iv)%datasz_in(1) = SIZE(pdata_2d,DIM=1)
1752        W_F(idf)%W_V(iv)%datasz_in(2) = SIZE(pdata_2d,DIM=2)
[362]1753      ELSE IF (l3d) THEN
[856]1754        W_F(idf)%W_V(iv)%datasz_in(1) = SIZE(pdata_3d,DIM=1)
1755        W_F(idf)%W_V(iv)%datasz_in(2) = SIZE(pdata_3d,DIM=2)
1756        W_F(idf)%W_V(iv)%datasz_in(3) = SIZE(pdata_3d,DIM=3)
[362]1757      ENDIF
[4]1758    ENDIF
1759!-
1760!-- 5.2 The maximum size of the data will give the size of the buffer
1761!-
[856]1762    IF (W_F(idf)%W_V(iv)%datasz_max <= 0) THEN
[4]1763      largebuf = .FALSE.
[856]1764      DO io=1,W_F(idf)%W_V(iv)%nbopp
1765        IF (INDEX(fuchnbout,W_F(idf)%W_V(iv)%sopp(io)) > 0) THEN
[4]1766          largebuf = .TRUE.
1767        ENDIF
1768      ENDDO
1769      IF (largebuf) THEN
[856]1770        W_F(idf)%W_V(iv)%datasz_max = &
1771 &        W_F(idf)%W_V(iv)%scsize(1) &
1772 &       *W_F(idf)%W_V(iv)%scsize(2) &
1773 &       *W_F(idf)%W_V(iv)%scsize(3)
[4]1774      ELSE
[362]1775        IF      (l1d) THEN
[856]1776          W_F(idf)%W_V(iv)%datasz_max = &
1777 &          W_F(idf)%W_V(iv)%datasz_in(1)
[362]1778        ELSE IF (l2d) THEN
[856]1779          W_F(idf)%W_V(iv)%datasz_max = &
1780 &          W_F(idf)%W_V(iv)%datasz_in(1) &
1781 &         *W_F(idf)%W_V(iv)%datasz_in(2)
[362]1782        ELSE IF (l3d) THEN
[856]1783          W_F(idf)%W_V(iv)%datasz_max = &
1784 &          W_F(idf)%W_V(iv)%datasz_in(1) &
1785 &         *W_F(idf)%W_V(iv)%datasz_in(2) &
1786 &         *W_F(idf)%W_V(iv)%datasz_in(3)
[362]1787        ENDIF
[4]1788      ENDIF
1789    ENDIF
1790!-
[856]1791    IF (.NOT.ALLOCATED(tbf_1)) THEN
[429]1792      IF (l_dbg) THEN
[4]1793        WRITE(*,*) &
[856]1794 &       c_nam//" : allocate tbf_1 for size = ", &
1795 &       W_F(idf)%W_V(iv)%datasz_max
[4]1796      ENDIF
[856]1797      ALLOCATE(tbf_1(W_F(idf)%W_V(iv)%datasz_max))
1798    ELSE IF (W_F(idf)%W_V(iv)%datasz_max > SIZE(tbf_1)) THEN
[429]1799      IF (l_dbg) THEN
[4]1800        WRITE(*,*) &
[856]1801 &       c_nam//" : re-allocate tbf_1 for size = ", &
1802 &       W_F(idf)%W_V(iv)%datasz_max
[4]1803      ENDIF
[856]1804      DEALLOCATE(tbf_1)
1805      ALLOCATE(tbf_1(W_F(idf)%W_V(iv)%datasz_max))
[4]1806    ENDIF
1807!-
1808!-- We have to do the first operation anyway.
1809!-- Thus we do it here and change the ranke
1810!-- of the data at the same time. This should speed up things.
1811!-
[856]1812    nbpt_out = W_F(idf)%W_V(iv)%datasz_max
[362]1813    IF      (l1d) THEN
[856]1814      nbpt_in1 = W_F(idf)%W_V(iv)%datasz_in(1)
1815      CALL mathop (W_F(idf)%W_V(iv)%sopp(1),nbpt_in1,pdata_1d, &
[362]1816 &                 missing_val,nbindex,nindex, &
[856]1817 &                 W_F(idf)%W_V(iv)%scal(1),nbpt_out,tbf_1)
[362]1818    ELSE IF (l2d) THEN
[856]1819      nbpt_in2(1:2) = W_F(idf)%W_V(iv)%datasz_in(1:2)
1820      CALL mathop (W_F(idf)%W_V(iv)%sopp(1),nbpt_in2,pdata_2d, &
[362]1821 &                 missing_val,nbindex,nindex, &
[856]1822 &                 W_F(idf)%W_V(iv)%scal(1),nbpt_out,tbf_1)
[362]1823    ELSE IF (l3d) THEN
[856]1824      nbpt_in3(1:3) = W_F(idf)%W_V(iv)%datasz_in(1:3)
1825      CALL mathop (W_F(idf)%W_V(iv)%sopp(1),nbpt_in3,pdata_3d, &
[362]1826 &                 missing_val,nbindex,nindex, &
[856]1827 &                 W_F(idf)%W_V(iv)%scal(1),nbpt_out,tbf_1)
[362]1828    ENDIF
[856]1829    CALL histwrite_real (idf,iv,pitau,nbpt_out, &
1830 &            tbf_1,nbindex,nindex,do_oper,do_write)
[4]1831  ENDIF
1832!-
1833! 6.0 Manage time steps
1834!-
1835  IF ((TRIM(tmp_opp) /= "once").AND.(TRIM(tmp_opp) /= "never")) THEN
[856]1836    W_F(idf)%W_V(iv)%last_opp_chk = pitau
1837    W_F(idf)%W_V(iv)%last_wrt_chk = pitau
[4]1838  ELSE
[856]1839    W_F(idf)%W_V(iv)%last_opp_chk = -99
1840    W_F(idf)%W_V(iv)%last_wrt_chk = -99
[4]1841  ENDIF
[362]1842!-----------------------
1843END SUBROUTINE histw_rnd
[4]1844!===
1845SUBROUTINE histwrite_real &
[856]1846 & (idf,iv,pitau,nbdpt,tbf_1,nbindex,nindex,do_oper,do_write)
[4]1847!---------------------------------------------------------------------
1848!- This subroutine is internal and does the calculations and writing
1849!- if needed. At a later stage it should be split into an operation
1850!- and writing subroutines.
1851!---------------------------------------------------------------------
1852  IMPLICIT NONE
1853!-
[856]1854  INTEGER,INTENT(IN) :: idf,pitau,iv, &
[4]1855 &                      nbindex,nindex(nbindex),nbdpt
[856]1856  REAL,DIMENSION(:)  :: tbf_1
[4]1857  LOGICAL,INTENT(IN) :: do_oper,do_write
1858!-
[856]1859  INTEGER :: tsz,nfid,nvid,iret,itax,io,nbin,nbout
[440]1860  INTEGER :: nx,ny,nz,ky,kz,kt,kc
[362]1861  INTEGER,DIMENSION(4) :: corner,edges
[4]1862  INTEGER :: itime
1863!-
1864  REAL :: rtime
[1023]1865  REAL,DIMENSION(2) :: t_bnd
[4]1866  CHARACTER(LEN=7) :: tmp_opp
[856]1867  REAL,ALLOCATABLE,DIMENSION(:),SAVE :: tbf_2
[429]1868  LOGICAL :: l_dbg
1869!---------------------------------------------------------------------
1870  CALL ipsldbg (old_status=l_dbg)
[4]1871!-
[429]1872  IF (l_dbg) THEN
[856]1873    WRITE(*,*) "histwrite 0.0 : VAR : ",W_F(idf)%W_V(iv)%v_name
[879]1874    WRITE(*,*) "histwrite 0.0 : nbindex :",nbindex
1875    WRITE(*,*) "histwrite 0.0 : nindex  :",nindex(1:MIN(3,nbindex)),'...'
[4]1876  ENDIF
1877!-
1878! The sizes which can be encoutered
1879!-
[856]1880  tsz =  W_F(idf)%W_V(iv)%zsize(1) &
1881 &      *W_F(idf)%W_V(iv)%zsize(2) &
1882 &      *W_F(idf)%W_V(iv)%zsize(3)
[4]1883!-
[856]1884! 1.0 We allocate and the temporary space needed for operations.
1885!     The buffers are only deallocated when more space is needed.
1886!     This reduces the umber of allocates but increases memory needs.
[4]1887!-
[856]1888  IF (.NOT.ALLOCATED(tbf_2)) THEN
[429]1889    IF (l_dbg) THEN
[856]1890      WRITE(*,*) "histwrite_real 1.1 allocate tbf_2 ",SIZE(tbf_1)
[429]1891    ENDIF
[856]1892    ALLOCATE(tbf_2(W_F(idf)%W_V(iv)%datasz_max))
1893  ELSE IF (W_F(idf)%W_V(iv)%datasz_max > SIZE(tbf_2)) THEN
[429]1894    IF (l_dbg) THEN
[856]1895      WRITE(*,*) "histwrite_real 1.2 re-allocate tbf_2 : ", &
1896     & SIZE(tbf_1)," instead of ",SIZE(tbf_2)
[4]1897    ENDIF
[856]1898    DEALLOCATE(tbf_2)
1899    ALLOCATE(tbf_2(W_F(idf)%W_V(iv)%datasz_max))
[4]1900  ENDIF
1901!-
[856]1902  rtime = pitau*W_F(idf)%deltat
1903  tmp_opp = W_F(idf)%W_V(iv)%topp
[4]1904!-
[856]1905! 3.0 Do the operations or transfer the slab of data into tbf_1
[4]1906!-
[856]1907  IF (l_dbg) THEN
1908    WRITE(*,*) "histwrite: 3.0",idf
1909  ENDIF
[4]1910!-
1911! 3.1 DO the Operations only if needed
1912!-
[358]1913  IF (do_oper) THEN
[4]1914    nbout = nbdpt
1915!-
1916!-- 3.4 We continue the sequence of operations
1917!--     we started in the interface routine
1918!-
[856]1919    DO io=2,W_F(idf)%W_V(iv)%nbopp,2
[4]1920      nbin = nbout
[856]1921      nbout = W_F(idf)%W_V(iv)%datasz_max
1922      CALL mathop(W_F(idf)%W_V(iv)%sopp(io),nbin,tbf_1, &
1923 &      missing_val,nbindex,nindex,W_F(idf)%W_V(iv)%scal(io), &
1924 &      nbout,tbf_2)
[429]1925      IF (l_dbg) THEN
[4]1926        WRITE(*,*) &
[856]1927 &       "histwrite: 3.4a nbout : ",nbin,nbout,W_F(idf)%W_V(iv)%sopp(io)
[4]1928      ENDIF
1929!-
1930      nbin = nbout
[856]1931      nbout = W_F(idf)%W_V(iv)%datasz_max
1932      CALL mathop(W_F(idf)%W_V(iv)%sopp(io+1),nbin,tbf_2, &
1933 &      missing_val,nbindex,nindex,W_F(idf)%W_V(iv)%scal(io+1), &
1934 &      nbout,tbf_1)
[429]1935      IF (l_dbg) THEN
[4]1936        WRITE(*,*) &
[856]1937 &     "histwrite: 3.4b nbout : ",nbin,nbout,W_F(idf)%W_V(iv)%sopp(io+1)
[4]1938      ENDIF
1939    ENDDO
1940!-
1941!   3.5 Zoom into the data
1942!-
[429]1943    IF (l_dbg) THEN
[4]1944      WRITE(*,*) &
[856]1945 &     "histwrite: 3.5 size(tbf_1) : ",SIZE(tbf_1)
[4]1946      WRITE(*,*) &
[760]1947 &     "histwrite: 3.5 slab in X :", &
[856]1948 &     W_F(idf)%W_V(iv)%zorig(1),W_F(idf)%W_V(iv)%zsize(1)
[4]1949      WRITE(*,*) &
[760]1950 &     "histwrite: 3.5 slab in Y :", &
[856]1951 &     W_F(idf)%W_V(iv)%zorig(2),W_F(idf)%W_V(iv)%zsize(2)
[4]1952      WRITE(*,*) &
[760]1953 &     "histwrite: 3.5 slab in Z :", &
[856]1954 &     W_F(idf)%W_V(iv)%zorig(3),W_F(idf)%W_V(iv)%zsize(3)
[4]1955      WRITE(*,*) &
1956 &     "histwrite: 3.5 slab of input:", &
[856]1957 &     W_F(idf)%W_V(iv)%scsize(1), &
1958 &     W_F(idf)%W_V(iv)%scsize(2), &
1959 &     W_F(idf)%W_V(iv)%scsize(3)
[4]1960    ENDIF
[440]1961!---
1962!-- We have to consider blocks of contiguous data
1963!---
[856]1964    nx=MAX(W_F(idf)%W_V(iv)%zsize(1),1)
1965    ny=MAX(W_F(idf)%W_V(iv)%zsize(2),1)
1966    nz=MAX(W_F(idf)%W_V(iv)%zsize(3),1)
1967    IF     (     (W_F(idf)%W_V(iv)%zorig(1) == 1) &
1968 &          .AND.(   W_F(idf)%W_V(iv)%zsize(1) &
1969 &                == W_F(idf)%W_V(iv)%scsize(1)) &
1970 &          .AND.(W_F(idf)%W_V(iv)%zorig(2) == 1) &
1971 &          .AND.(   W_F(idf)%W_V(iv)%zsize(2) &
1972 &                == W_F(idf)%W_V(iv)%scsize(2))) THEN
1973      kt = (W_F(idf)%W_V(iv)%zorig(3)-1)*nx*ny
1974      tbf_2(1:nx*ny*nz) = tbf_1(kt+1:kt+nx*ny*nz)
1975    ELSEIF (     (W_F(idf)%W_V(iv)%zorig(1) == 1) &
1976 &          .AND.(   W_F(idf)%W_V(iv)%zsize(1) &
1977 &                == W_F(idf)%W_V(iv)%scsize(1))) THEN
[440]1978      kc = -nx*ny
[856]1979      DO kz=W_F(idf)%W_V(iv)%zorig(3),W_F(idf)%W_V(iv)%zorig(3)+nz-1
[440]1980        kc = kc+nx*ny
[856]1981        kt = ( (kz-1)*W_F(idf)%W_V(iv)%scsize(2) &
1982 &            +W_F(idf)%W_V(iv)%zorig(2)-1)*nx
1983        tbf_2(kc+1:kc+nx*ny) = tbf_1(kt+1:kt+nx*ny)
[440]1984      ENDDO
1985    ELSE
1986      kc = -nx
[856]1987      DO kz=W_F(idf)%W_V(iv)%zorig(3),W_F(idf)%W_V(iv)%zorig(3)+nz-1
1988        DO ky=W_F(idf)%W_V(iv)%zorig(2),W_F(idf)%W_V(iv)%zorig(2)+ny-1
[440]1989          kc = kc+nx
[856]1990          kt = ((kz-1)*W_F(idf)%W_V(iv)%scsize(2)+ky-1) &
1991 &            *W_F(idf)%W_V(iv)%scsize(1) &
1992 &            +W_F(idf)%W_V(iv)%zorig(1)-1
1993          tbf_2(kc+1:kc+nx) = tbf_1(kt+1:kt+nx)
[440]1994        ENDDO
1995      ENDDO
1996    ENDIF
[4]1997!-
[856]1998!-- 4.0 Get the min and max of the field
[4]1999!-
[856]2000    IF (l_dbg) THEN
2001      WRITE(*,*) "histwrite: 4.0 tbf_1",idf,iv, &
2002 &      TRIM(tmp_opp),' ---- ',LEN_TRIM(tmp_opp),nbindex
2003    ENDIF
[4]2004!-
[856]2005    IF (W_F(idf)%W_V(iv)%hist_calc_rng) THEN
2006      W_F(idf)%W_V(iv)%hist_minmax(1) = &
2007 &      MIN(W_F(idf)%W_V(iv)%hist_minmax(1), &
2008 &      MINVAL(tbf_2(1:tsz),MASK=tbf_2(1:tsz) /= missing_val))
2009      W_F(idf)%W_V(iv)%hist_minmax(2) = &
2010 &      MAX(W_F(idf)%W_V(iv)%hist_minmax(2), &
2011 &      MAXVAL(tbf_2(1:tsz),MASK=tbf_2(1:tsz) /= missing_val))
[75]2012    ENDIF
[4]2013!-
2014!-- 5.0 Do the operations if needed. In the case of instantaneous
[856]2015!--     output we do not transfer to the time_buffer.
[4]2016!-
[856]2017    IF (l_dbg) THEN
2018      WRITE(*,*) "histwrite: 5.0 idf : ",idf," iv : ",iv," tsz : ",tsz
2019    ENDIF
[4]2020!-
2021    IF (     (TRIM(tmp_opp) /= "inst") &
[760]2022 &      .AND.(TRIM(tmp_opp) /= "once") ) THEN
[856]2023      CALL moycum(tmp_opp,tsz,W_F(idf)%W_V(iv)%t_bf, &
2024 &           tbf_2,W_F(idf)%W_V(iv)%nb_opp)
[4]2025    ENDIF
2026!-
[856]2027    W_F(idf)%W_V(iv)%last_opp = pitau
2028    W_F(idf)%W_V(iv)%nb_opp = W_F(idf)%W_V(iv)%nb_opp+1
[4]2029!-
[440]2030  ENDIF
[4]2031!-
2032! 6.0 Write to file if needed
2033!-
[856]2034  IF (l_dbg) WRITE(*,*) "histwrite: 6.0",idf
[4]2035!-
[358]2036  IF (do_write) THEN
[4]2037!-
[856]2038    nfid = W_F(idf)%ncfid
2039    nvid = W_F(idf)%W_V(iv)%ncvid
[4]2040!-
2041!-- 6.1 Do the operations that are needed before writting
2042!-
[856]2043    IF (l_dbg) WRITE(*,*) "histwrite: 6.1",idf
[4]2044!-
2045    IF (     (TRIM(tmp_opp) /= "inst") &
[760]2046 &      .AND.(TRIM(tmp_opp) /= "once") ) THEN
[1023]2047      t_bnd(1:2) = (/ W_F(idf)%W_V(iv)%last_wrt*W_F(idf)%deltat,rtime /)
2048      rtime = (t_bnd(1)+t_bnd(2))/2.0
[4]2049    ENDIF
2050!-
2051!-- 6.2 Add a value to the time axis of this variable if needed
2052!-
2053    IF (     (TRIM(tmp_opp) /= "l_max") &
[760]2054 &      .AND.(TRIM(tmp_opp) /= "l_min") &
2055 &      .AND.(TRIM(tmp_opp) /= "once") ) THEN
[4]2056!-
[856]2057      IF (l_dbg) WRITE(*,*) "histwrite: 6.2",idf
[4]2058!-
[856]2059      itax  = W_F(idf)%W_V(iv)%t_axid
2060      itime = W_F(idf)%W_V(iv)%nb_wrt+1
[4]2061!-
[856]2062      IF (W_F(idf)%W_V(itax)%tax_last < itime) THEN
2063        iret = NF90_PUT_VAR (nfid,W_F(idf)%W_V(itax)%tdimid, &
[760]2064 &               (/ rtime /),start=(/ itime /),count=(/ 1 /))
[1023]2065        IF (W_F(idf)%W_V(itax)%tbndid > 0) THEN
2066          iret = NF90_PUT_VAR (nfid,W_F(idf)%W_V(itax)%tbndid, &
2067 &                 t_bnd,start=(/ 1,itime /),count=(/ 2,1 /))
2068        ENDIF
[856]2069        W_F(idf)%W_V(itax)%tax_last = itime
[4]2070      ENDIF
2071    ELSE
2072      itime=1
2073    ENDIF
2074!-
2075!-- 6.3 Write the data. Only in the case of instantaneous output
2076!       we do not write the buffer.
2077!-
[429]2078    IF (l_dbg) THEN
[856]2079      WRITE(*,*) "histwrite: 6.3",idf,nfid,nvid,iv,itime
[4]2080    ENDIF
2081!-
[856]2082    IF (W_F(idf)%W_V(iv)%scsize(3) == 1) THEN
2083      IF (W_F(idf)%regular) THEN
[362]2084        corner(1:4) = (/ 1,1,itime,0 /)
[856]2085        edges(1:4) = (/ W_F(idf)%W_V(iv)%zsize(1), &
2086 &                      W_F(idf)%W_V(iv)%zsize(2),1,0 /)
[4]2087      ELSE
[362]2088        corner(1:4) = (/ 1,itime,0,0 /)
[856]2089        edges(1:4) = (/ W_F(idf)%W_V(iv)%zsize(1),1,0,0 /)
[4]2090      ENDIF
2091    ELSE
[856]2092      IF (W_F(idf)%regular) THEN
[362]2093        corner(1:4) = (/ 1,1,1,itime /)
[856]2094        edges(1:4) = (/ W_F(idf)%W_V(iv)%zsize(1), &
2095 &                      W_F(idf)%W_V(iv)%zsize(2), &
2096 &                      W_F(idf)%W_V(iv)%zsize(3),1 /)
[4]2097      ELSE
[362]2098        corner(1:4) = (/ 1,1,itime,0 /)
[856]2099        edges(1:4) = (/ W_F(idf)%W_V(iv)%zsize(1), &
2100 &                      W_F(idf)%W_V(iv)%zsize(3),1,0 /)
[4]2101      ENDIF
2102    ENDIF
2103!-
2104    IF (     (TRIM(tmp_opp) /= "inst") &
2105 &      .AND.(TRIM(tmp_opp) /= "once") ) THEN
[856]2106      iret = NF90_PUT_VAR (nfid,nvid,W_F(idf)%W_V(iv)%t_bf, &
2107 &                         start=corner(1:4),count=edges(1:4))
[4]2108    ELSE
[856]2109      iret = NF90_PUT_VAR (nfid,nvid,tbf_2, &
2110 &                         start=corner(1:4),count=edges(1:4))
[4]2111    ENDIF
2112!-
[856]2113    W_F(idf)%W_V(iv)%last_wrt = pitau
2114    W_F(idf)%W_V(iv)%nb_wrt = W_F(idf)%W_V(iv)%nb_wrt+1
2115    W_F(idf)%W_V(iv)%nb_opp = 0
[4]2116!---
2117!   After the write the file can be synchronized so that no data is
2118!   lost in case of a crash. This feature gives up on the benefits of
2119!   buffering and should only be used in debuging mode. A flag is
2120!   needed here to switch to this mode.
2121!---
[760]2122!   iret = NF90_SYNC (nfid)
[4]2123!-
2124  ENDIF
2125!----------------------------
2126END SUBROUTINE histwrite_real
2127!===
[856]2128SUBROUTINE histvar_seq (idf,pvarname,idv)
[4]2129!---------------------------------------------------------------------
[856]2130!- This subroutine optimize the search for the variable in the table.
[4]2131!- In a first phase it will learn the succession of the variables
2132!- called and then it will use the table to guess what comes next.
2133!- It is the best solution to avoid lengthy searches through array
2134!- vectors.
2135!-
2136!- ARGUMENTS :
2137!-
[856]2138!- idf      : id of the file on which we work
[4]2139!- pvarname : The name of the variable we are looking for
[856]2140!- idv      : The var id we found
[4]2141!---------------------------------------------------------------------
2142  IMPLICIT NONE
2143!-
[856]2144  INTEGER,INTENT(in)  :: idf
[4]2145  CHARACTER(LEN=*),INTENT(IN) :: pvarname
[856]2146  INTEGER,INTENT(out) :: idv
[4]2147!-
2148  LOGICAL,SAVE :: learning(nb_files_max)=.TRUE.
2149  INTEGER,SAVE :: overlap(nb_files_max) = -1
[358]2150  INTEGER,SAVE :: varseq(nb_files_max,nb_var_max*3)
[4]2151  INTEGER,SAVE :: varseq_len(nb_files_max) = 0
2152  INTEGER,SAVE :: varseq_pos(nb_files_max)
2153  INTEGER,SAVE :: varseq_err(nb_files_max) = 0
[440]2154  INTEGER      :: ib,sp,nn,pos
[4]2155  CHARACTER(LEN=70) :: str70
[429]2156  LOGICAL :: l_dbg
2157!---------------------------------------------------------------------
2158  CALL ipsldbg (old_status=l_dbg)
[4]2159!-
[429]2160  IF (l_dbg) THEN
[856]2161    WRITE(*,*) 'histvar_seq, start of the subroutine :',learning(idf)
[4]2162  ENDIF
2163!-
[856]2164  IF (learning(idf)) THEN
[4]2165!-
2166!-- 1.0 We compute the length over which we are going
2167!--     to check the overlap
2168!-
[856]2169    IF (overlap(idf) <= 0) THEN
2170      IF (W_F(idf)%n_var > 6) THEN
2171        overlap(idf) = W_F(idf)%n_var/3*2
[4]2172      ELSE
[856]2173        overlap(idf) = W_F(idf)%n_var
[4]2174      ENDIF
2175    ENDIF
2176!-
2177!-- 1.1 Find the position of this string
2178!-
[856]2179    CALL find_str (W_F(idf)%W_V(1:W_F(idf)%n_var)%v_name,pvarname,pos)
[4]2180    IF (pos > 0) THEN
[856]2181      idv = pos
[4]2182    ELSE
2183      CALL ipslerr (3,"histvar_seq", &
2184 &      'The name of the variable you gave has not been declared', &
2185 &      'You should use subroutine histdef for declaring variable', &
[358]2186 &      TRIM(pvarname))
[4]2187    ENDIF
2188!-
2189!-- 1.2 If we have not given up we store the position
2190!--     in the sequence of calls
2191!-
[856]2192    IF (varseq_err(idf) >= 0) THEN
2193      sp = varseq_len(idf)+1
[4]2194      IF (sp <= nb_var_max*3) THEN
[856]2195        varseq(idf,sp) = idv
2196        varseq_len(idf) = sp
[4]2197      ELSE
2198        CALL ipslerr (2,"histvar_seq",&
2199 &       'The learning process has failed and we give up. '// &
2200 &       'Either you sequence is',&
2201 &       'too complex or I am too dumb. '// &
2202 &       'This will only affect the efficiency',&
2203 &       'of your code. Thus if you wish to save time'// &
2204 &       ' contact the IOIPSL team. ')
2205        WRITE(*,*) 'The sequence we have found up to now :'
[856]2206        WRITE(*,*) varseq(idf,1:sp-1)
2207        varseq_err(idf) = -1
[4]2208      ENDIF
2209!-
2210!---- 1.3 Check if we have found the right overlap
2211!-
[856]2212      IF (varseq_len(idf) >= overlap(idf)*2) THEN
[4]2213!-
2214!------ We skip a few variables if needed as they could come
2215!------ from the initialisation of the model.
2216!-
[856]2217        DO ib = 0,sp-overlap(idf)*2
2218          IF ( learning(idf) .AND.&
2219            & SUM(ABS(varseq(idf,ib+1:ib+overlap(idf)) -&
2220            & varseq(idf,sp-overlap(idf)+1:sp))) == 0 ) THEN
2221            learning(idf) = .FALSE.
2222            varseq_len(idf) = sp-overlap(idf)-ib
2223            varseq_pos(idf) = overlap(idf)+ib
2224            varseq(idf,1:varseq_len(idf)) = &
2225 &            varseq(idf,ib+1:ib+varseq_len(idf))
[4]2226          ENDIF
2227        ENDDO
2228      ENDIF
2229    ENDIF
2230  ELSE
2231!-
2232!-- 2.0 Now we know how the calls to histwrite are sequenced
2233!--     and we can get a guess at the var ID
2234!-
[856]2235    nn = varseq_pos(idf)+1
2236    IF (nn > varseq_len(idf)) nn = 1
[4]2237!-
[856]2238    idv = varseq(idf,nn)
[4]2239!-
[856]2240    IF (TRIM(W_F(idf)%W_V(idv)%v_name) /= TRIM(pvarname)) THEN
2241      CALL find_str (W_F(idf)%W_V(1:W_F(idf)%n_var)%v_name,pvarname,pos)
[4]2242      IF (pos > 0) THEN
[856]2243        idv = pos
[4]2244      ELSE
2245        CALL ipslerr (3,"histvar_seq", &
2246 &  'The name of the variable you gave has not been declared',&
[358]2247 &  'You should use subroutine histdef for declaring variable', &
2248 &  TRIM(pvarname))
[4]2249      ENDIF
[856]2250      varseq_err(idf) = varseq_err(idf)+1
[4]2251    ELSE
2252!-
2253!---- We only keep the new position if we have found the variable
2254!---- this way. This way an out of sequence call to histwrite does
2255!---- not defeat the process.
2256!-
[856]2257      varseq_pos(idf) = nn
[4]2258    ENDIF
2259!-
[856]2260    IF (varseq_err(idf) >= 10) THEN
2261      WRITE(str70,'("for file ",I3)') idf
[4]2262      CALL ipslerr (2,"histvar_seq", &
2263 &  'There were 10 errors in the learned sequence of variables',&
2264 &  str70,'This looks like a bug, please report it.')
[856]2265         varseq_err(idf) = 0
[4]2266    ENDIF
2267  ENDIF
2268!-
[429]2269  IF (l_dbg) THEN
[4]2270    WRITE(*,*) &
[856]2271 &   'histvar_seq, end of the subroutine :',TRIM(pvarname),idv
[4]2272  ENDIF
2273!-------------------------
2274END SUBROUTINE histvar_seq
2275!===
[977]2276SUBROUTINE histsync (idf)
[4]2277!---------------------------------------------------------------------
2278!- This subroutine will synchronise all
2279!- (or one if defined) opened files.
2280!-
2281!- VERSION
2282!-
2283!---------------------------------------------------------------------
2284  IMPLICIT NONE
2285!-
[977]2286! idf  : optional argument for fileid
2287  INTEGER,INTENT(in),OPTIONAL :: idf
[4]2288!-
[957]2289  INTEGER :: ifile,iret,i_s,i_e
[4]2290!-
[429]2291  LOGICAL :: l_dbg
[4]2292!---------------------------------------------------------------------
[429]2293  CALL ipsldbg (old_status=l_dbg)
[4]2294!-
[957]2295  IF (l_dbg) THEN
2296    WRITE(*,*) "->histsync"
2297  ENDIF
[429]2298!-
[977]2299  IF (PRESENT(idf)) THEN
2300    IF ( (idf >= 1).AND.(idf <= nb_files_max) ) THEN
2301      IF (W_F(idf)%ncfid > 0) THEN
2302        i_s = idf
2303        i_e = idf
[957]2304      ELSE
2305        i_s = 1
2306        i_e = 0
2307        CALL ipslerr (2,'histsync', &
2308 &       'Unable to synchronise the file :','probably','not opened')
2309      ENDIF
[4]2310    ELSE
[957]2311      CALL ipslerr (3,'histsync','Invalid file identifier',' ',' ')
[4]2312    ENDIF
[957]2313  ELSE
2314    i_s = 1
[962]2315    i_e = nb_files_max
[957]2316  ENDIF
[4]2317!-
[957]2318  DO ifile=i_s,i_e
2319    IF (W_F(ifile)%ncfid > 0) THEN
[429]2320      IF (l_dbg) THEN
[957]2321        WRITE(*,*) '  histsync - synchronising file number ',ifile
[4]2322      ENDIF
[957]2323      iret = NF90_SYNC(W_F(ifile)%ncfid)
[4]2324    ENDIF
[957]2325  ENDDO
[4]2326!-
[957]2327  IF (l_dbg) THEN
2328    WRITE(*,*) "<-histsync"
2329  ENDIF
[4]2330!----------------------
2331END SUBROUTINE histsync
2332!===
[856]2333SUBROUTINE histclo (idf)
[4]2334!---------------------------------------------------------------------
2335!- This subroutine will close all (or one if defined) opened files
2336!-
2337!- VERSION
2338!-
2339!---------------------------------------------------------------------
2340  IMPLICIT NONE
2341!-
[856]2342! idf  : optional argument for fileid
2343  INTEGER,INTENT(in),OPTIONAL :: idf
[4]2344!-
[957]2345  INTEGER :: ifile,nfid,nvid,iret,iv,i_s,i_e
[429]2346  LOGICAL :: l_dbg
[4]2347!---------------------------------------------------------------------
[429]2348  CALL ipsldbg (old_status=l_dbg)
[4]2349!-
[957]2350  IF (l_dbg) THEN
2351    WRITE(*,*) "->histclo"
2352  ENDIF
[429]2353!-
[856]2354  IF (PRESENT(idf)) THEN
[962]2355    IF ( (idf >= 1).AND.(idf <= nb_files_max) ) THEN
[977]2356      IF (W_F(idf)%ncfid > 0) THEN
[957]2357        i_s = idf
2358        i_e = idf
2359      ELSE
2360        i_s = 1
2361        i_e = 0
2362        CALL ipslerr (2,'histclo', &
2363 &       'Unable to close the file :','probably','not opened')
2364      ENDIF
2365    ELSE
2366      CALL ipslerr (3,'histclo','Invalid file identifier',' ',' ')
2367    ENDIF
[4]2368  ELSE
[957]2369    i_s = 1
[962]2370    i_e = nb_files_max
[4]2371  ENDIF
2372!-
[957]2373  DO ifile=i_s,i_e
2374    IF (W_F(ifile)%ncfid > 0) THEN
2375      IF (l_dbg) THEN
2376        WRITE(*,*) '  histclo - closing specified file number :',ifile
2377      ENDIF
2378      nfid = W_F(ifile)%ncfid
2379      iret = NF90_REDEF(nfid)
2380!-----
2381!---- 1. Loop on the number of variables to add some final information
2382!-----
2383      IF (l_dbg) THEN
2384        WRITE(*,*) '  Entering loop on vars : ',W_F(ifile)%n_var
2385      ENDIF
2386      DO iv=1,W_F(ifile)%n_var
2387!------ Extrema
2388        IF (W_F(ifile)%W_V(iv)%hist_wrt_rng) THEN
2389          IF (l_dbg) THEN
2390            WRITE(*,*) 'min value for file :',ifile,' var n. :',iv, &
2391 &                     ' is : ',W_F(ifile)%W_V(iv)%hist_minmax(1)
2392            WRITE(*,*) 'max value for file :',ifile,' var n. :',iv, &
2393 &                     ' is : ',W_F(ifile)%W_V(iv)%hist_minmax(2)
[881]2394          ENDIF
[957]2395          IF (W_F(ifile)%W_V(iv)%hist_calc_rng) THEN
2396!---------- Put the min and max values on the file
2397            nvid = W_F(ifile)%W_V(iv)%ncvid
2398            IF (W_F(ifile)%W_V(iv)%v_typ == hist_r8) THEN
2399              iret = NF90_PUT_ATT(nfid,nvid,'valid_min', &
2400 &                     REAL(W_F(ifile)%W_V(iv)%hist_minmax(1),KIND=8))
2401              iret = NF90_PUT_ATT(nfid,nvid,'valid_max', &
2402 &                     REAL(W_F(ifile)%W_V(iv)%hist_minmax(2),KIND=8))
2403            ELSE
2404              iret = NF90_PUT_ATT(nfid,nvid,'valid_min', &
2405 &                     REAL(W_F(ifile)%W_V(iv)%hist_minmax(1),KIND=4))
2406              iret = NF90_PUT_ATT(nfid,nvid,'valid_max', &
2407 &                     REAL(W_F(ifile)%W_V(iv)%hist_minmax(2),KIND=4))
2408            ENDIF
2409          ENDIF
[75]2410        ENDIF
[957]2411!------ Time-Buffers
2412        IF (ASSOCIATED(W_F(ifile)%W_V(iv)%t_bf)) THEN
2413          DEALLOCATE(W_F(ifile)%W_V(iv)%t_bf)
2414        ENDIF
[964]2415!------ Reinitialize the sizes
2416        W_F(ifile)%W_V(iv)%datasz_in(:) = -1
2417        W_F(ifile)%W_V(iv)%datasz_max = -1
[957]2418      ENDDO
2419!-----
2420!---- 2. Close the file
2421!-----
2422      IF (l_dbg) WRITE(*,*) '  close file :',nfid
2423      iret = NF90_CLOSE(nfid)
2424      W_F(ifile)%ncfid = -1
[964]2425      W_F(ifile)%dom_id_svg = -1
[4]2426    ENDIF
2427  ENDDO
[957]2428!-
2429  IF (l_dbg) THEN
2430    WRITE(*,*) "<-histclo"
2431  ENDIF
[4]2432!---------------------
2433END SUBROUTINE histclo
2434!===
2435SUBROUTINE ioconf_modname (str)
2436!---------------------------------------------------------------------
2437!- This subroutine allows to configure the name
2438!- of the model written into the file
2439!---------------------------------------------------------------------
2440  IMPLICIT NONE
2441!-
2442  CHARACTER(LEN=*),INTENT(IN) :: str
2443!---------------------------------------------------------------------
2444  IF (.NOT.lock_modname) THEN
2445    model_name = str(1:MIN(LEN_TRIM(str),80))
2446    lock_modname = .TRUE.
2447  ELSE
2448    CALL ipslerr (2,"ioconf_modname", &
2449   &  'The model name can only be changed once and only', &
2450   &  'before it is used. It is now set to :',model_name)
2451  ENDIF
2452!----------------------------
2453END SUBROUTINE ioconf_modname
2454!-
2455!===
2456!-
2457!-----------------
2458END MODULE histcom
Note: See TracBrowser for help on using the repository browser.