source: trunk/LMDZ.COMMON/libf/evolution/writediagpem.F90 @ 3316

Last change on this file since 3316 was 3214, checked in by jbclement, 17 months ago

PEM:

  • It is now possible to set the number of initial PCM calls independently of the number of "inter-PEM" PCM calls. It is useful to get a stable situation for the start of the simulation.
  • Correction of a bug: 'reshape_XIOS_output' treated the first two PCM runs instead of the last two. The numbering has been adapted in "launch_pem.sh" to get it right.
  • PEM outputs ("diagpem.nc" and "diagsoil_pem.nc") has been improved: 'Time' now evolves according to 'dt_pem' (usually year by year) and 'ecritpem' is a full variable of "time_evol_mod.F90".

JBC

File size: 34.3 KB
RevLine 
[3088]1MODULE writediagpem_mod
2
3implicit none
4
5!=======================================================================
6contains
7!=======================================================================
8
[3181]9SUBROUTINE writediagpem(ngrid,nom,titre,unite,dim,px)
[3088]10
11!  Ecriture de variables diagnostiques au choix dans la physique
[3097]12!  dans un fichier NetCDF nomme  'diagpem'. Ces variables peuvent etre
[3088]13!  3d (ex : temperature), 2d (ex : temperature de surface), ou
14!  0d (pour un scalaire qui ne depend que du temps : ex : la longitude
15!  solaire)
16!  (ou encore 1d, dans le cas de testphys1d, pour sortir une colonne)
17!  La periode d'ecriture est donnee par
[3214]18!  "ecritpem " regle dans le fichier de controle de run :  run.def
[3088]19!
20!    writediagpem peut etre appele de n'importe quelle subroutine
21!    de la physique, plusieurs fois. L'initialisation et la creation du
22!    fichier se fait au tout premier appel.
23!
24! WARNING : les variables dynamique (u,v,t,q,ps)
25!  sauvees par writediagpem avec une
26! date donnee sont legerement differentes que dans le fichier histoire car
27! on ne leur a pas encore ajoute de la dissipation et de la physique !!!
28! IL est  RECOMMANDE d'ajouter les tendance physique a ces variables
[3097]29! avant l'ecriture dans diagpem (cf. physiq.F)
[3088]30!
31! Modifs: Aug.2010 Ehouarn: enforce outputs to be real*4
[3093]32!         Oct 2011 Francois: enable having a 'diagpem.def' file to select
[3088]33!                            at runtime, which variables to put in file
[3122]34!         Oct 2023 JBC: conversion into Fortran 90 with module for the PEM
[3088]35!
36!  parametres (input) :
37!  ----------
38!      ngrid : nombres de point ou est calcule la physique
39!                (ngrid = 2+(jjm-1)*iim - 1/jjm)
40!                (= nlon ou klon dans la physique terrestre)
41!      unit : unite logique du fichier de sortie (toujours la meme)
42!      nom  : nom de la variable a sortir (chaine de caracteres)
43!      titre: titre de la variable (chaine de caracteres)
44!      unite : unite de la variable (chaine de caracteres)
45!      px : variable a sortir (real 0, 1, 2, ou 3d)
46!      dim : dimension de px : 0, 1, 2, ou 3 dimensions
47!
48!=================================================================
49use surfdat_h,          only: phisfi
50use geometry_mod,       only: cell_area
51use mod_phys_lmdz_para, only: is_parallel, is_mpi_root, is_master, gather
52use mod_grid_phy_lmdz,  only: klon_glo, Grid1Dto2D_glo, nbp_lon, nbp_lat, nbp_lev, grid_type, unstructured
[3214]53use time_evol_mod,      only: ecritpem, dt_pem
[3088]54
55implicit none
56
57! Commons
58include "netcdf.inc"
59
60! Arguments on input:
61integer,                        intent(in) :: ngrid
62character(len=*),               intent(in) :: nom, titre, unite
63integer,                        intent(in) :: dim
64real, dimension(ngrid,nbp_lev), intent(in) :: px
65
66! Local variables:
67real*4, dimension(nbp_lon + 1,nbp_lat,nbp_lev) :: dx3    ! to store a 3D data set
68real*4, dimension(nbp_lon + 1,nbp_lat)         :: dx2    ! to store a 2D (surface) data set
69real*4, dimension(nbp_lev)                     :: dx1    ! to store a 1D (column) data set
70real*4                                         :: dx0
71real*4, dimension(1,nbp_lev)                   :: dx3_1d ! to store a profile with 1D model
72real*4                                         :: dx2_1d ! to store a surface value with 1D model
73real*4, save                                   :: date
74
75!$OMP THREADPRIVATE(date)
76real, dimension((nbp_lon + 1),nbp_lat) :: phis
77real, dimension((nbp_lon + 1),nbp_lat) :: area
78integer                                :: irythme, ierr, ierr2, i, j, l, ig0
79integer,                          save :: zitau = 0
80character(27),                    save :: firstnom='1234567890'
81!$OMP THREADPRIVATE(zitau,firstnom)
82
83! Ajouts
84integer,           save :: ntime = 0
85!$OMP THREADPRIVATE(ntime)
86integer                 :: idim, varid
87integer                 :: nid
[3181]88character(*), parameter :: fichnom = "diagpem.nc"
[3088]89integer, dimension(4)   :: id
90integer, dimension(4)   :: edges, corner
91
[3093]92! Added to use diagpem.def to select output variable
[3097]93logical,                                  save :: diagpem_def
[3088]94logical                                        :: getout
95integer,                                  save :: n_nom_def
96integer                                        :: n
97integer, parameter                             :: n_nom_def_max = 199
98character(120), dimension(n_nom_def_max), save :: nom_def
99logical,                                  save :: firstcall = .true.
[3097]100!$OMP THREADPRIVATE(firstcall) !diagpem_def,n_nom_def,nom_def read in diagpem.def
[3088]101
102#ifdef CPP_PARA
103! Added to work in parallel mode
104    real, dimension(klon_glo,nbp_lev)        :: dx3_glop
105    real, dimension(nbp_lon,nbp_lat,nbp_lev) :: dx3_glo  ! to store a global 3D data set
106    real, dimension(klon_glo)                :: dx2_glop
107    real, dimension(nbp_lon,nbp_lat)         :: dx2_glo  ! to store a global 2D (surface) data set
108    real, dimension(ngrid)                   :: px2
109!    real, dimension(nbp_lev)                :: dx1_glo   ! to store a 1D (column) data set
110!    real :: dx0_glo
111    real, dimension(klon_glo) :: phisfi_glo ! surface geopotential on global physics grid
112    real, dimension(klon_glo) :: areafi_glo ! mesh area on global physics grid
113#else
114    real, dimension(ngrid) :: phisfi_glo ! surface geopotential on global physics grid
115    real, dimension(ngrid) :: areafi_glo ! mesh area on global physics grid
116#endif
117
118if (grid_type == unstructured) return
119
120!***************************************************************
121!Sortie des variables au rythme voulu
[3214]122irythme = int(ecritpem) ! output rate set by ecritpem
[3088]123
124!***************************************************************
[3093]125! At very first call, check if there is a "diagpem.def" to use and read it
126! ------------------------------------------------------------------------
[3088]127IF (firstcall) THEN
128    firstcall=.false.
129
130!$OMP MASTER
[3093]131    ! Open diagpem.def definition file if there is one:
132        open(99,file="diagpem.def",status='old',form='formatted',iostat=ierr2)
[3088]133
134        if (ierr2 == 0) then
[3097]135            diagpem_def=.true.
[3093]136            write(*,*) "*******************"
137            write(*,*) "Reading diagpem.def"
138            write(*,*) "*******************"
[3088]139            do n=1,n_nom_def_max
140                read(99,fmt='(a)',end=88) nom_def(n)
[3097]141                write(*,*) 'Output in diagpem: ', trim(nom_def(n))
[3088]142            enddo
143 88         continue
144            if (n.ge.n_nom_def_max) then
145                write(*,*)"n_nom_def_max too small in writediagpem.F:",n
146                call abort_physic("writediagpem","n_nom_def_max too small",1)
147            end if
148            n_nom_def=n-1
149            close(99)
150        else
[3097]151            diagpem_def=.false.
[3088]152        endif
153!$OMP END MASTER
154!$OMP BARRIER
155ENDIF ! of IF (firstcall)
156
[3097]157! Get out of write_diagpem if there is diagpem.def AND variable not listed
158!  -----------------------------------------------------------------------
159if (diagpem_def) then
[3088]160    getout=.true.
161    do n=1,n_nom_def
162        if (trim(nom_def(n)).eq.nom) getout=.false.
163    enddo
164    if (getout) return
165endif
166
[3097]167! Initialisation of 'firstnom' and create/open the "diagpem.nc" NetCDF file
168! -------------------------------------------------------------------------
[3093]169! (at very first call to the subroutine, in accordance with diagpem.def)
[3088]170if (firstnom.eq.'1234567890') then ! .true. for the very first valid
171    ! call to this subroutine; now set 'firstnom'
172    firstnom = nom
173    ! just to be sure, check that firstnom is large enough to hold nom
174    if (len_trim(firstnom).lt.len_trim(nom)) then
175        write(*,*) "writediagpem: Error !!!"
176        write(*,*) "   firstnom string not long enough!!"
177        write(*,*) "   increase its size to at least ",len_trim(nom)
178        call abort_physic("writediagpem","firstnom too short",1)
179    endif
180
181    zitau = -1 ! initialize zitau
182
183#ifdef CPP_PARA
184        ! Gather phisfi() geopotential on physics grid
185        call Gather(phisfi,phisfi_glo)
186        ! Gather cell_area() mesh area on physics grid
187        call Gather(cell_area,areafi_glo)
188#else
189        phisfi_glo(:)=phisfi(:)
190        areafi_glo(:)=cell_area(:)
191#endif
192
193    !! parallel: we cannot use the usual writediagpem method
194    !! call iophys_ini
195    if (is_master) then
196        ! only the master is required to do this
197        ! Create the NetCDF file
198        ierr = NF_CREATE(fichnom,NF_CLOBBER,nid)
199        ! Define the 'Time' dimension
200        ierr = nf_def_dim(nid,"Time",NF_UNLIMITED,idim)
201        ! Define the 'Time' variable
202    !#ifdef NC_DOUBLE
203    !    ierr = NF_DEF_VAR (nid, "Time", NF_DOUBLE, 1, idim,varid)
204    !#else
205        ierr = NF_DEF_VAR (nid, "Time", NF_FLOAT, 1, idim,varid)
206    !#endif
207        ! Add a long_name attribute
208        ierr = NF_PUT_ATT_TEXT (nid, varid, "long_name",4,"Time")
209        ! Add a units attribute
210        ierr = NF_PUT_ATT_TEXT(nid, varid,'units',29,"days since 0000-00-0 00:00:00")
211        ! Switch out of NetCDF Define mode
212        ierr = NF_ENDDEF(nid)
213
214        ! Build phis() and area()
215        IF (klon_glo>1) THEN
216            do i=1,nbp_lon+1 ! poles
217            phis(i,1)=phisfi_glo(1)
218            phis(i,nbp_lat)=phisfi_glo(klon_glo)
219            ! for area, divide at the poles by nbp_lon
220            area(i,1)=areafi_glo(1)/nbp_lon
221            area(i,nbp_lat)=areafi_glo(klon_glo)/nbp_lon
222            enddo
223            do j=2,nbp_lat-1
224            ig0= 1+(j-2)*nbp_lon
225            do i=1,nbp_lon
226                phis(i,j)=phisfi_glo(ig0+i)
227                area(i,j)=areafi_glo(ig0+i)
228            enddo
229            ! handle redundant point in longitude
230            phis(nbp_lon+1,j)=phis(1,j)
231            area(nbp_lon+1,j)=area(1,j)
232            enddo
233        ENDIF
234
235        ! write "header" of file (longitudes, latitudes, geopotential, ...)
236        IF (klon_glo>1) THEN ! general 3D case
[3214]237            call iniwrite(nid,0,phis,area,nbp_lon+1,nbp_lat)
[3088]238        ELSE ! 1D model
[3214]239            call iniwrite(nid,0,phisfi_glo(1),areafi_glo(1),1,1)
[3088]240        ENDIF
241
242    endif ! of if (is_master)
243
244    else
245
246    if (is_master) then
247        ! only the master is required to do this
248        ! Open the NetCDF file
249        ierr = NF_OPEN(fichnom,NF_WRITE,nid)
250    endif ! of if (is_master)
251
252endif ! if (firstnom.eq.'1234567890')
253
254! Increment time index 'zitau' if it is the "fist call" (at given time level)
255! to writediagpem
256!------------------------------------------------------------------------
[3214]257if (nom == firstnom) zitau = zitau + dt_pem
[3088]258
259!--------------------------------------------------------
260! Write the variables to output file if it's time to do so
261!--------------------------------------------------------
262if (MOD(zitau+1,irythme) == 0.) then
263! Compute/write/extend 'Time' coordinate (date given in days)
264! (done every "first call" (at given time level) to writediagpem)
265! Note: date is incremented as 1 step ahead of physics time
266!--------------------------------------------------------
267    if (is_master) then
268        ! only the master is required to do this
269        if (nom.eq.firstnom) then
270        ! We have identified a "first call" (at given date)
271            ntime=ntime+1 ! increment # of stored time steps
272            ! compute corresponding date (in days and fractions thereof)
[3214]273            date = float(zitau + 1)
[3088]274            ! Get NetCDF ID of 'Time' variable
275            ierr= NF_INQ_VARID(nid,"Time",varid)
276            ! Write (append) the new date to the 'Time' array
277!#ifdef NC_DOUBLE
278!    ierr= NF_PUT_VARA_DOUBLE(nid,varid,[ntime],[1],[date])
279!#else
280            ierr= NF_PUT_VARA_REAL(nid,varid,[ntime],[1],[date])
281!#endif
282            if (ierr.ne.NF_NOERR) then
283                write(*,*) "***** PUT_VAR matter in writediagpem_nc"
284                write(*,*) "***** with time"
285                write(*,*) 'ierr=', ierr,": ",NF_STRERROR(ierr)
286!                call abort
287            endif
288
[3097]289            write(6,*)'WRITEDIAGPEM: date= ', date
[3088]290        endif ! of if (nom.eq.firstnom)
291    endif ! of if (is_master)
292
293!Case of a 3D variable
294!---------------------
295    if (dim == 3) then
296#ifdef CPP_PARA
297        ! Gather field on a "global" (without redundant longitude) array
298        call Gather(px,dx3_glop)
299!$OMP MASTER
300        if (is_mpi_root) then
301            call Grid1Dto2D_glo(dx3_glop,dx3_glo)
302            ! copy dx3_glo() to dx3(:) and add redundant longitude
303            dx3(1:nbp_lon,:,:)=dx3_glo(1:nbp_lon,:,:)
304            dx3(nbp_lon+1,:,:)=dx3(1,:,:)
305        endif
306!$OMP END MASTER
307!$OMP BARRIER
308#else
309!         Passage variable physique -->  variable dynamique
310!         recast (copy) variable from physics grid to dynamics grid
311        IF (klon_glo>1) THEN ! General case
312            DO l=1,nbp_lev
313                DO i=1,nbp_lon+1
314                    dx3(i,1,l)=px(1,l)
315                    dx3(i,nbp_lat,l)=px(ngrid,l)
316                ENDDO
317                DO j=2,nbp_lat-1
318                    ig0= 1+(j-2)*nbp_lon
319                    DO i=1,nbp_lon
320                        dx3(i,j,l)=px(ig0+i,l)
321                    ENDDO
322                    dx3(nbp_lon+1,j,l)=dx3(1,j,l)
323                ENDDO
324            ENDDO
325        ELSE ! 1D model case
326            dx3_1d(1,1:nbp_lev)=px(1,1:nbp_lev)
327        ENDIF
328#endif
329!       Ecriture du champs
330        if (is_master) then
331! only the master writes to output
332! name of the variable
333            ierr= NF_INQ_VARID(nid,nom,varid)
334            if (ierr /= NF_NOERR) then
335! corresponding dimensions
336                ierr = NF_INQ_DIMID(nid,"longitude",id(1))
337                ierr = NF_INQ_DIMID(nid,"latitude",id(2))
338                ierr = NF_INQ_DIMID(nid,"altitude",id(3))
339                ierr = NF_INQ_DIMID(nid,"Time",id(4))
340
341! Create the variable if it doesn't exist yet
[3097]342                write (*,*) "==========================="
343                write (*,*) "DIAGPEM: creating variable ",trim(nom)
[3088]344                call def_var(nid,nom,titre,unite,4,id,varid,ierr)
345
346            else
347                if (ntime==0) then
[3097]348                    write(*,*) "DIAGPEM Error: failed creating variable ",trim(nom)
[3088]349                    write(*,*) "it seems it already exists!"
350                    call abort_physic("writediagpem",trim(nom)//" already exists",1)
351                endif
352            endif
353
354            corner(1)=1
355            corner(2)=1
356            corner(3)=1
357            corner(4)=ntime
358
359            IF (klon_glo==1) THEN
360                edges(1)=1
361            ELSE
362                edges(1)=nbp_lon+1
363            ENDIF
364            edges(2)=nbp_lat
365            edges(3)=nbp_lev
366            edges(4)=1
367!#ifdef NC_DOUBLE
368!            ierr= NF_PUT_VARA_DOUBLE(nid,varid,corner,edges,dx3)
369!#else
370!            write(*,*)"test:  nid=",nid," varid=",varid
371!            write(*,*)"       corner()=",corner
372!            write(*,*)"       edges()=",edges
373!            write(*,*)"       dx3()=",dx3
374            IF (klon_glo>1) THEN ! General case
375                ierr= NF_PUT_VARA_REAL(nid,varid,corner,edges,dx3)
376            ELSE
377                ierr= NF_PUT_VARA_REAL(nid,varid,corner,edges,dx3_1d)
378            ENDIF
379!#endif
380
381            if (ierr.ne.NF_NOERR) then
382                write(*,*) "***** PUT_VAR problem in writediagpem"
383                write(*,*) "***** with dx3: ",trim(nom)
384                write(*,*) 'ierr=', ierr,": ",NF_STRERROR(ierr)
385                call abort_physic("writediagpem","failed writing "//trim(nom),1)
386            endif
387
388        endif !of if (is_master)
389
390!Case of a 2D variable
391!---------------------
392    else if (dim == 2) then
393
394#ifdef CPP_PARA
395        ! Gather field on a "global" (without redundant longitude) array
396        px2(:)=px(:,1)
397        call Gather(px2,dx2_glop)
398!$OMP MASTER
399        if (is_mpi_root) then
400            call Grid1Dto2D_glo(dx2_glop,dx2_glo)
401            ! copy dx2_glo() to dx2(:) and add redundant longitude
402            dx2(1:nbp_lon,:)=dx2_glo(1:nbp_lon,:)
403            dx2(nbp_lon+1,:)=dx2(1,:)
404        endif
405!$OMP END MASTER
406!$OMP BARRIER
407#else
408!         Passage variable physique -->  physique dynamique
409!         recast (copy) variable from physics grid to dynamics grid
410        IF (klon_glo>1) THEN ! General case
411            DO i=1,nbp_lon+1
412                dx2(i,1)=px(1,1)
413                dx2(i,nbp_lat)=px(ngrid,1)
414            ENDDO
415            DO j=2,nbp_lat-1
416                ig0= 1+(j-2)*nbp_lon
417                DO i=1,nbp_lon
418                    dx2(i,j)=px(ig0+i,1)
419                ENDDO
420                dx2(nbp_lon+1,j)=dx2(1,j)
421            ENDDO
422        ELSE ! 1D model case
423            dx2_1d=px(1,1)
424        ENDIF
425#endif
426
427        if (is_master) then
428        ! only the master writes to output
429!            write (*,*) 'In  writediagpem, on sauve:  ' , nom
430!            write (*,*) 'In  writediagpem. Estimated date = ' ,date
431            ierr= NF_INQ_VARID(nid,nom,varid)
432            if (ierr /= NF_NOERR) then
433! corresponding dimensions
434                ierr= NF_INQ_DIMID(nid,"longitude",id(1))
435                ierr= NF_INQ_DIMID(nid,"latitude",id(2))
436                ierr= NF_INQ_DIMID(nid,"Time",id(3))
437
438! Create the variable if it doesn't exist yet
[3097]439                write (*,*) "==========================="
440                write (*,*) "DIAGPEM: creating variable ",trim(nom)
[3088]441
442                call def_var(nid,nom,titre,unite,3,id,varid,ierr)
443
444            else
445                if (ntime==0) then
[3097]446                    write(*,*) "DIAGPEM Error: failed creating variable ",trim(nom)
[3088]447                    write(*,*) "it seems it already exists!"
448                    call abort_physic("writediagpem",trim(nom)//" already exists",1)
449                endif
450            endif
451
452            corner(1)=1
453            corner(2)=1
454            corner(3)=ntime
455            IF (klon_glo==1) THEN
456                edges(1)=1
457            ELSE
458                edges(1)=nbp_lon+1
459            ENDIF
460            edges(2)=nbp_lat
461            edges(3)=1
462
463
464!#ifdef NC_DOUBLE
465!           ierr = NF_PUT_VARA_DOUBLE (nid,varid,corner,edges,dx2)
466!#else
467            IF (klon_glo>1) THEN ! General case
468                ierr = NF_PUT_VARA_REAL(nid,varid,corner,edges,dx2)
469            ELSE
470                ierr = NF_PUT_VARA_REAL(nid,varid,corner,edges,[dx2_1d])
471            ENDIF
472!#endif
473
474            if (ierr.ne.NF_NOERR) then
475                write(*,*) "***** PUT_VAR matter in writediagpem"
476                write(*,*) "***** with dx2: ",trim(nom)
477                write(*,*) 'ierr=', ierr,": ",NF_STRERROR(ierr)
478                call abort_physic("writediagpem","failed writing "//trim(nom),1)
479            endif
480
481        endif !of if (is_master)
482
483!Case of a 1D variable (ie: a column)
484!---------------------------------------------------
485    else if (dim.eq.1) then
486        if (is_parallel) then
487            write(*,*) "writediagpem error: dim=1 not implemented ","in parallel mode. Problem for ",trim(nom)
488                call abort_physic("writediagpem","failed writing "//trim(nom),1)
489        endif
490!       Passage variable physique -->  physique dynamique
491!       recast (copy) variable from physics grid to dynamics grid
492        do l=1,nbp_lev
493            dx1(l)=px(1,l)
494        enddo
495
496        ierr= NF_INQ_VARID(nid,nom,varid)
497        if (ierr /= NF_NOERR) then
498! corresponding dimensions
499            ierr= NF_INQ_DIMID(nid,"altitude",id(1))
500            ierr= NF_INQ_DIMID(nid,"Time",id(2))
501
502! Create the variable if it doesn't exist yet
503
[3097]504            write (*,*) "==========================="
505            write (*,*) "DIAGPEM: creating variable ",trim(nom)
[3088]506
507            call def_var(nid,nom,titre,unite,2,id,varid,ierr)
508
509        else
510            if (ntime==0) then
[3097]511                write(*,*) "DIAGPEM Error: failed creating variable ",trim(nom)
[3088]512                write(*,*) "it seems it already exists!"
513                call abort_physic("writediagpem",trim(nom)//" already exists",1)
514            endif
515        endif
516
517        corner(1)=1
518        corner(2)=ntime
519        edges(1)=nbp_lev
520        edges(2)=1
521!#ifdef NC_DOUBLE
522!           ierr= NF_PUT_VARA_DOUBLE(nid,varid,corner,edges,dx1)
523!#else
524        ierr= NF_PUT_VARA_REAL(nid,varid,corner,edges,dx1)
525!#endif
526
527        if (ierr /= NF_NOERR) then
528            write(*,*) "***** PUT_VAR problem in writediagpem"
529            write(*,*) "***** with dx1: ",trim(nom)
530            write(*,*) 'ierr=', ierr,": ",NF_STRERROR(ierr)
531            call abort_physic("writediagpem","failed writing "//trim(nom),1)
532        endif
533
534!Case of a 0D variable (ie: a time-dependent scalar)
535!---------------------------------------------------
536    else if (dim == 0) then
537
538        dx0 = px (1,1)
539
540        if (is_master) then
541            ! only the master writes to output
542            ierr= NF_INQ_VARID(nid,nom,varid)
543            if (ierr /= NF_NOERR) then
544! corresponding dimensions
545                ierr= NF_INQ_DIMID(nid,"Time",id(1))
546
547! Create the variable if it doesn't exist yet
[3097]548                write (*,*) "==========================="
549                write (*,*) "DIAGPEM: creating variable ",trim(nom)
[3088]550                call def_var(nid,nom,titre,unite,1,id,varid,ierr)
551
552            else
553                if (ntime==0) then
[3097]554                    write(*,*) "DIAGPEM Error: failed creating variable ",trim(nom)
[3088]555                    write(*,*) "it seems it already exists!"
556                    call abort_physic("writediagpem",trim(nom)//" already exists",1)
557                endif
558            endif
559
560            corner(1)=ntime
561            edges(1)=1
562
563!#ifdef NC_DOUBLE
564!            ierr = NF_PUT_VARA_DOUBLE (nid,varid,[corner(1)],[edges(1)],[dx0])
565!#else
566            ierr= NF_PUT_VARA_REAL(nid,varid,[corner(1)],[edges(1)],[dx0])
567!#endif
568            if (ierr.ne.NF_NOERR) then
569                write(*,*) "***** PUT_VAR matter in writediagpem"
570                write(*,*) "***** with dx0: ",trim(nom)
571                write(*,*) 'ierr=', ierr,": ",NF_STRERROR(ierr)
572                call abort_physic("writediagpem","failed writing "//trim(nom),1)
573            endif
574        endif !of if (is_master)
575    endif ! of if (dim.eq.3) elseif(dim.eq.2)...
576endif ! of if ( MOD(zitau+1,irythme) .eq.0.)
577
578if (is_master) ierr= NF_CLOSE(nid)
579
[3181]580END SUBROUTINE writediagpem
[3088]581
[3214]582!=================================================================
[3171]583
[3214]584SUBROUTINE writediagsoilpem(ngrid,name,title,units,dimpx,px)
585
[3171]586! Write variable 'name' to NetCDF file 'diagsoil.nc'.
587! The variable may be 3D (lon,lat,depth) subterranean field,
588! a 2D (lon,lat) surface field, or a simple scalar (0D variable).
589!
590! Calls to 'writediagsoilpem' can originate from anywhere in the program;
591! An initialisation of variable 'name' is done if it is the first time
592! that this routine is called with given 'name'; otherwise data is appended
593! (yielding the sought time series of the variable)
594
595! Modifs: Aug.2010 Ehouarn: enforce outputs to be real*4
596
[3214]597use comsoil_h_PEM,      only: nsoilmx_PEM, inertiedat_PEM
598use geometry_mod,       only: cell_area
599use mod_phys_lmdz_para, only: is_mpi_root, is_master, gather
600use mod_grid_phy_lmdz,  only: klon_glo, Grid1Dto2D_glo, nbp_lon, nbp_lat
601use mod_grid_phy_lmdz,  only: grid_type, unstructured
602use time_evol_mod,      only: ecritpem, dt_pem
[3171]603
604implicit none
605
606include"netcdf.inc"
607
608! Arguments:
609integer,intent(in) :: ngrid ! number of (horizontal) points of physics grid
610! i.e. ngrid = 2+(jjm-1)*iim - 1/jjm
611character(len=*),intent(in) :: name ! 'name' of the variable
612character(len=*),intent(in) :: title ! 'long_name' attribute of the variable
613character(len=*),intent(in) :: units ! 'units' attribute of the variable
614integer,intent(in) :: dimpx ! dimension of the variable (3,2 or 0)
[3190]615real,dimension(ngrid,nsoilmx_PEM),intent(in) :: px ! variable
[3171]616
617! Local variables:
[3190]618real*4,dimension(nbp_lon+1,nbp_lat,nsoilmx_PEM) :: data3 ! to store 3D data
[3171]619real*4,dimension(nbp_lon+1,nbp_lat) :: data2 ! to store 2D data
620real*4 :: data0 ! to store 0D data
[3190]621real*4 :: data3_1d(1,nsoilmx_PEM) ! to store a profile in 1D model
[3171]622real*4 :: data2_1d ! to store surface value with 1D model
623integer :: i,j,l ! for loops
624integer :: ig0
625
626real*4,save :: date ! time counter (in elapsed days)
627
[3190]628real :: inertia((nbp_lon+1),nbp_lat,nsoilmx_PEM)
[3171]629real :: area((nbp_lon+1),nbp_lat)
630
[3190]631real :: inertiafi_glo(klon_glo,nsoilmx_PEM)
[3171]632real :: areafi_glo(klon_glo)
633
634integer,save :: isample ! sample rate at which data is to be written to output
635integer,save :: ntime=0 ! counter to internally store time steps
636character(len=20),save :: firstname="1234567890"
637integer,save :: zitau=0
638!$OMP THREADPRIVATE(date,isample,ntime,firstname,zitau)
639
640character(len=30) :: filename="diagsoilpem.nc"
641
642! NetCDF stuff:
643integer :: nid ! NetCDF output file ID
644integer :: varid ! NetCDF ID of a variable
645integer :: ierr ! NetCDF routines return code
646integer,dimension(4) :: id ! NetCDF IDs of the dimensions of the variable
647integer,dimension(4) :: edges,corners
648
649#ifdef CPP_PARA
650! Added to work in parallel mode
[3190]651real dx3_glop(klon_glo,nsoilmx_PEM)
652real dx3_glo(nbp_lon,nbp_lat,nsoilmx_PEM) ! to store a global 3D data set
[3171]653real dx2_glop(klon_glo)
654real dx2_glo(nbp_lon,nbp_lat)     ! to store a global 2D (surface) data set
655real px2(ngrid)
656#endif
657
658! 0. Do we ouput a diagsoil.nc file? If not just bail out now.
659
660! additional check: one can only output diagsoil.nc files
661! in lon-lat case (or 1D)
662if (grid_type==unstructured) then
663  write(*,*) "writediagsoil: Error !!!"
664  write(*,*) "diagsoil.nc outputs not possible on unstructured grids!!"
665  call abort_physic("writediagsoil","impossible on unstructured grid",1)
666endif
667
668! 1. Initialization step
669if (firstname.eq."1234567890") then
670  ! Store 'name' as 'firstname'
671  firstname=name
672  ! From now on, if 'name'.eq.'firstname', then it is a new time cycle
673
674  ! just to be sure, check that firstnom is large enough to hold nom
675  if (len_trim(firstname).lt.len_trim(name)) then
676    write(*,*) "writediagsoil: Error !!!"
677    write(*,*) "   firstname string not long enough!!"
678    write(*,*) "   increase its size to at least ",len_trim(name)
679    call abort_physic("writediagsoil","firstname too short",1)
680  endif
681 
682  ! Set output sample rate
[3214]683  isample = int(ecritpem) ! same as for diagpem outputs
[3171]684 
685  ! Create output NetCDF file
686  if (is_master) then
687   ierr=NF_CREATE(filename,NF_CLOBBER,nid)
688   if (ierr.ne.NF_NOERR) then
689    write(*,*)'writediagsoil: Error, failed creating file '//trim(filename)
690    call abort_physic("writediagsoil","failed creating"//trim(filename),1)
691   endif
692  endif
693
694#ifdef CPP_PARA
695   ! Gather inertiedat() soil thermal inertia on physics grid
[3190]696   call Gather(inertiedat_PEM,inertiafi_glo)
[3171]697   ! Gather cell_area() mesh area on physics grid
698   call Gather(cell_area,areafi_glo)
699#else
[3190]700         inertiafi_glo(:,:)=inertiedat_PEM(:,:)
[3171]701         areafi_glo(:)=cell_area(:)
702#endif
703
704  if (is_master) then
705   ! build inertia() and area()
706   if (klon_glo>1) then
707    do i=1,nbp_lon+1 ! poles
[3190]708     inertia(i,1,1:nsoilmx_PEM)=inertiafi_glo(1,1:nsoilmx_PEM)
709     inertia(i,nbp_lat,1:nsoilmx_PEM)=inertiafi_glo(klon_glo,1:nsoilmx_PEM)
[3171]710     ! for area, divide at the poles by nbp_lon
711     area(i,1)=areafi_glo(1)/nbp_lon
712     area(i,nbp_lat)=areafi_glo(klon_glo)/nbp_lon
713    enddo
714    do j=2,nbp_lat-1
715     ig0= 1+(j-2)*nbp_lon
716     do i=1,nbp_lon
[3190]717        inertia(i,j,1:nsoilmx_PEM)=inertiafi_glo(ig0+i,1:nsoilmx_PEM)
[3171]718        area(i,j)=areafi_glo(ig0+i)
719     enddo
720     ! handle redundant point in longitude
[3190]721     inertia(nbp_lon+1,j,1:nsoilmx_PEM)=inertia(1,j,1:nsoilmx_PEM)
[3171]722     area(nbp_lon+1,j)=area(1,j)
723    enddo
724   endif
725   
726   ! write "header" of file (longitudes, latitudes, geopotential, ...)
727   if (klon_glo>1) then ! general 3D case
728     call iniwritesoil(nid,ngrid,inertia,area,nbp_lon+1,nbp_lat)
729   else ! 1D model
730     call iniwritesoil(nid,ngrid,inertiafi_glo(1,:),areafi_glo(1),1,1)
731   endif
732
733  endif ! of if (is_master)
734 
735  ! set zitau to -1 to be compatible with zitau incrementation step below
736  zitau=-1
737 
738else
739  ! If not an initialization call, simply open the NetCDF file
740  if (is_master) then
741   ierr=NF_OPEN(filename,NF_WRITE,nid)
742  endif
743endif ! of if (firstname.eq."1234567890")
744
745! 2. Increment local time counter, if necessary
746if (name.eq.firstname) then
747  ! if we run across 'firstname', then it is a new time step
[3214]748  zitau = zitau + dt_pem
[3171]749endif
750
751! 3. Write data, if the time index matches the sample rate
752if (mod(zitau+1,isample).eq.0) then
753
754! 3.1 If first call at this date, update 'time' variable
755  if (name.eq.firstname) then
756    ntime=ntime+1
[3214]757    date = float(zitau + 1)
[3171]758   
759    if (is_master) then
760     ! Get NetCDF ID for "time"
761     ierr=NF_INQ_VARID(nid,"time",varid)
762     ! Add the current value of date to the "time" array
763!#ifdef NC_DOUBLE
764!     ierr=NF_PUT_VARA_DOUBLE(nid,varid,ntime,1,date)
765!#else
766     ierr=NF_PUT_VARA_REAL(nid,varid,[ntime],[1],[date])
767!#endif
768     if (ierr.ne.NF_NOERR) then
769      write(*,*)"writediagsoil: Failed writing date to time variable"
770      call abort_physic("writediagsoil","failed writing time",1)
771     endif
772    endif ! of if (is_master)
773  endif ! of if (name.eq.firstname)
774
775! 3.2 Write the variable to the NetCDF file
776if (dimpx.eq.3) then ! Case of a 3D variable
777  ! A. Recast data along 'dynamics' grid
778#ifdef CPP_PARA
779  ! gather field on a "global" (without redundant longitude) array
780  call Gather(px,dx3_glop)
781!$OMP MASTER
782  if (is_mpi_root) then
783    call Grid1Dto2D_glo(dx3_glop,dx3_glo)
784    ! copy dx3_glo() to dx3(:) and add redundant longitude
785    data3(1:nbp_lon,:,:)=dx3_glo(1:nbp_lon,:,:)
786    data3(nbp_lon+1,:,:)=data3(1,:,:)
787  endif
788!$OMP END MASTER
789!$OMP BARRIER
790#else
791  if (klon_glo>1) then ! General case
[3190]792   do l=1,nsoilmx_PEM
[3171]793    ! handle the poles
794    do i=1,nbp_lon+1
795      data3(i,1,l)=px(1,l)
796      data3(i,nbp_lat,l)=px(ngrid,l)
797    enddo
798    ! rest of the grid
799    do j=2,nbp_lat-1
800      ig0=1+(j-2)*nbp_lon
801      do i=1,nbp_lon
802        data3(i,j,l)=px(ig0+i,l)
803      enddo
804      data3(nbp_lon+1,j,l)=data3(1,j,l) ! extra (modulo) longitude
805    enddo
806   enddo
807  else ! 1D model case
[3190]808   data3_1d(1,1:nsoilmx_PEM)=px(1,1:nsoilmx_PEM)
[3171]809  endif
810#endif
811 
812  ! B. Write (append) the variable to the NetCDF file
813  if (is_master) then
814  ! B.1. Get the ID of the variable
815  ierr=NF_INQ_VARID(nid,name,varid)
816  if (ierr.ne.NF_NOERR) then
817    ! If we failed geting the variable's ID, we assume it is because
818    ! the variable doesn't exist yet and must be created.
819    ! Start by obtaining corresponding dimensions IDs
820    ierr=NF_INQ_DIMID(nid,"longitude",id(1))
821    ierr=NF_INQ_DIMID(nid,"latitude",id(2))
822    ierr=NF_INQ_DIMID(nid,"depth",id(3))
823    ierr=NF_INQ_DIMID(nid,"time",id(4))
824    ! Tell the world about it
825    write(*,*) "====================="
826    write(*,*) "writediagsoil: creating variable "//trim(name)
827    call def_var(nid,name,title,units,4,id,varid,ierr)
828  endif ! of if (ierr.ne.NF_NOERR)
829 
830  ! B.2. Prepare things to be able to write/append the variable
831  corners(1)=1
832  corners(2)=1
833  corners(3)=1
834  corners(4)=ntime
835 
836  if (klon_glo==1) then
837    edges(1)=1
838  else
839    edges(1)=nbp_lon+1
840  endif
841  edges(2)=nbp_lat
[3190]842  edges(3)=nsoilmx_PEM
[3171]843  edges(4)=1
844 
845  ! B.3. Write the slab of data
846!#ifdef NC_DOUBLE
847!  ierr=NF_PUT_VARA_DOUBLE(nid,varid,corners,edges,data3)
848!#else
849  if (klon_glo>1) then
850    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,data3)
851  else
852    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,data3_1d)
853  endif
854!#endif
855  if (ierr.ne.NF_NOERR) then
856    write(*,*) "writediagsoil: Error: Failed writing "//trim(name)//&
857               " to file "//trim(filename)//" at time",date
858  endif
859  endif ! of if (is_master)
860
861elseif (dimpx.eq.2) then ! Case of a 2D variable
862
863  ! A. Recast data along 'dynamics' grid
864#ifdef CPP_PARA
865  ! gather field on a "global" (without redundant longitude) array
866  px2(:)=px(:,1)
867  call Gather(px2,dx2_glop)
868!$OMP MASTER
869  if (is_mpi_root) then
870    call Grid1Dto2D_glo(dx2_glop,dx2_glo)
871    ! copy dx3_glo() to dx3(:) and add redundant longitude
872    data2(1:nbp_lon,:)=dx2_glo(1:nbp_lon,:)
873    data2(nbp_lon+1,:)=data2(1,:)
874  endif
875!$OMP END MASTER
876!$OMP BARRIER
877#else
878  if (klon_glo>1) then ! general case
879    ! handle the poles
880    do i=1,nbp_lon+1
881      data2(i,1)=px(1,1)
882      data2(i,nbp_lat)=px(ngrid,1)
883    enddo
884    ! rest of the grid
885    do j=2,nbp_lat-1
886      ig0=1+(j-2)*nbp_lon
887      do i=1,nbp_lon
888        data2(i,j)=px(ig0+i,1)
889      enddo
890      data2(nbp_lon+1,j)=data2(1,j) ! extra (modulo) longitude
891    enddo
892  else ! 1D model case
893    data2_1d=px(1,1)
894  endif
895#endif
896
897  ! B. Write (append) the variable to the NetCDF file
898  if (is_master) then
899  ! B.1. Get the ID of the variable
900  ierr=NF_INQ_VARID(nid,name,varid)
901  if (ierr.ne.NF_NOERR) then
902    ! If we failed geting the variable's ID, we assume it is because
903    ! the variable doesn't exist yet and must be created.
904    ! Start by obtaining corresponding dimensions IDs
905    ierr=NF_INQ_DIMID(nid,"longitude",id(1))
906    ierr=NF_INQ_DIMID(nid,"latitude",id(2))
907    ierr=NF_INQ_DIMID(nid,"time",id(3))
908    ! Tell the world about it
909    write(*,*) "====================="
910    write(*,*) "writediagsoil: creating variable "//trim(name)
911    call def_var(nid,name,title,units,3,id,varid,ierr)
912  endif ! of if (ierr.ne.NF_NOERR)
913
914  ! B.2. Prepare things to be able to write/append the variable
915  corners(1)=1
916  corners(2)=1
917  corners(3)=ntime
918 
919  if (klon_glo==1) then
920    edges(1)=1
921  else
922    edges(1)=nbp_lon+1
923  endif
924  edges(2)=nbp_lat
925  edges(3)=1
926 
927  ! B.3. Write the slab of data
928!#ifdef NC_DOUBLE
929!  ierr=NF_PUT_VARA_DOUBLE(nid,varid,corners,edges,data2)
930!#else
931  if (klon_glo>1) then ! General case
932    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,data2)
933  else
934    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,[data2_1d])
935  endif
936!#endif
937  if (ierr.ne.NF_NOERR) then
938    write(*,*) "writediagsoil: Error: Failed writing "//trim(name)//&
939               " to file "//trim(filename)//" at time",date
940  endif
941  endif ! of if (is_master)
942
943elseif (dimpx.eq.0) then ! Case of a 0D variable
944#ifdef CPP_PARA
945  write(*,*) "writediagsoil: dimps==0 case not implemented in // mode!!"
946  call abort_physic("writediagsoil","dimps==0 not implemented",1)
947#endif
948  ! A. Copy data value
949  data0=px(1,1)
950
951  ! B. Write (append) the variable to the NetCDF file
952  ! B.1. Get the ID of the variable
953  ierr=NF_INQ_VARID(nid,name,varid)
954  if (ierr.ne.NF_NOERR) then
955    ! If we failed geting the variable's ID, we assume it is because
956    ! the variable doesn't exist yet and must be created.
957    ! Start by obtaining corresponding dimensions IDs
958    ierr=NF_INQ_DIMID(nid,"time",id(1))
959    ! Tell the world about it
960    write(*,*) "====================="
961    write(*,*) "writediagsoil: creating variable "//trim(name)
962    call def_var(nid,name,title,units,1,id,varid,ierr)
963  endif ! of if (ierr.ne.NF_NOERR)
964
965  ! B.2. Prepare things to be able to write/append the variable
966  corners(1)=ntime
967 
968  edges(1)=1
969
970  ! B.3. Write the data
971!#ifdef NC_DOUBLE
972!  ierr=NF_PUT_VARA_DOUBLE(nid,varid,corners,edges,data0)
973!#else
974  ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,[data0])
975!#endif
976  if (ierr.ne.NF_NOERR) then
977    write(*,*) "writediagsoil: Error: Failed writing "//trim(name)//&
978               " to file "//trim(filename)//" at time",date
979  endif
980
981endif ! of if (dimpx.eq.3) elseif (dimpx.eq.2) ...
982endif ! of if (mod(zitau+1,isample).eq.0)
983
984! 4. Close the NetCDF file
985if (is_master) then
986  ierr=NF_CLOSE(nid)
987endif
988
[3214]989END SUBROUTINE writediagsoilpem
[3171]990
991
[3088]992END MODULE writediagpem_mod
993
Note: See TracBrowser for help on using the repository browser.