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

Last change on this file since 3552 was 3532, checked in by jbclement, 5 weeks ago

PEM:
Removing unecessary module/subroutine "interpol_TI_PEM2PCM.F90" + Few small corrections/cleanings.
JBC

File size: 34.4 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
[3512]53use time_evol_mod,      only: ecritpem
[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!------------------------------------------------------------------------
[3498]257if (nom == firstnom) zitau = zitau + 1
[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
[3345]296        IF (klon_glo>1) THEN ! General case
[3088]297#ifdef CPP_PARA
298        ! Gather field on a "global" (without redundant longitude) array
299        call Gather(px,dx3_glop)
300!$OMP MASTER
301        if (is_mpi_root) then
302            call Grid1Dto2D_glo(dx3_glop,dx3_glo)
303            ! copy dx3_glo() to dx3(:) and add redundant longitude
304            dx3(1:nbp_lon,:,:)=dx3_glo(1:nbp_lon,:,:)
305            dx3(nbp_lon+1,:,:)=dx3(1,:,:)
306        endif
307!$OMP END MASTER
308!$OMP BARRIER
309#else
310!         Passage variable physique -->  variable dynamique
311!         recast (copy) variable from physics grid to dynamics grid
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
[3345]325#endif
[3088]326        ELSE ! 1D model case
327            dx3_1d(1,1:nbp_lev)=px(1,1:nbp_lev)
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
[3345]394        IF (klon_glo>1) THEN ! General case
[3088]395#ifdef CPP_PARA
396        ! Gather field on a "global" (without redundant longitude) array
397        px2(:)=px(:,1)
398        call Gather(px2,dx2_glop)
399!$OMP MASTER
400        if (is_mpi_root) then
401            call Grid1Dto2D_glo(dx2_glop,dx2_glo)
402            ! copy dx2_glo() to dx2(:) and add redundant longitude
403            dx2(1:nbp_lon,:)=dx2_glo(1:nbp_lon,:)
404            dx2(nbp_lon+1,:)=dx2(1,:)
405        endif
406!$OMP END MASTER
407!$OMP BARRIER
408#else
409!         Passage variable physique -->  physique dynamique
410!         recast (copy) variable from physics grid to dynamics grid
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
[3345]422#endif
[3088]423        ELSE ! 1D model case
424            dx2_1d=px(1,1)
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
[3339]586! Write variable 'name' to NetCDF file 'diagsoilpem.nc'.
[3171]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
[3345]597use comsoil_h_PEM,      only: mlayer_PEM, nsoilmx_PEM, inertiedat_PEM
[3214]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
[3512]602use time_evol_mod,      only: ecritpem
[3345]603use iniwritesoil_mod,   only: iniwritesoil
[3171]604
605implicit none
606
607include"netcdf.inc"
608
609! Arguments:
610integer,intent(in) :: ngrid ! number of (horizontal) points of physics grid
611! i.e. ngrid = 2+(jjm-1)*iim - 1/jjm
612character(len=*),intent(in) :: name ! 'name' of the variable
613character(len=*),intent(in) :: title ! 'long_name' attribute of the variable
614character(len=*),intent(in) :: units ! 'units' attribute of the variable
615integer,intent(in) :: dimpx ! dimension of the variable (3,2 or 0)
[3190]616real,dimension(ngrid,nsoilmx_PEM),intent(in) :: px ! variable
[3171]617
618! Local variables:
[3190]619real*4,dimension(nbp_lon+1,nbp_lat,nsoilmx_PEM) :: data3 ! to store 3D data
[3171]620real*4,dimension(nbp_lon+1,nbp_lat) :: data2 ! to store 2D data
621real*4 :: data0 ! to store 0D data
[3190]622real*4 :: data3_1d(1,nsoilmx_PEM) ! to store a profile in 1D model
[3171]623real*4 :: data2_1d ! to store surface value with 1D model
624integer :: i,j,l ! for loops
625integer :: ig0
626
627real*4,save :: date ! time counter (in elapsed days)
628
[3190]629real :: inertia((nbp_lon+1),nbp_lat,nsoilmx_PEM)
[3171]630real :: area((nbp_lon+1),nbp_lat)
631
[3190]632real :: inertiafi_glo(klon_glo,nsoilmx_PEM)
[3171]633real :: areafi_glo(klon_glo)
634
635integer,save :: isample ! sample rate at which data is to be written to output
636integer,save :: ntime=0 ! counter to internally store time steps
637character(len=20),save :: firstname="1234567890"
638integer,save :: zitau=0
639!$OMP THREADPRIVATE(date,isample,ntime,firstname,zitau)
640
641character(len=30) :: filename="diagsoilpem.nc"
642
643! NetCDF stuff:
644integer :: nid ! NetCDF output file ID
645integer :: varid ! NetCDF ID of a variable
646integer :: ierr ! NetCDF routines return code
647integer,dimension(4) :: id ! NetCDF IDs of the dimensions of the variable
648integer,dimension(4) :: edges,corners
649
650#ifdef CPP_PARA
651! Added to work in parallel mode
[3190]652real dx3_glop(klon_glo,nsoilmx_PEM)
653real dx3_glo(nbp_lon,nbp_lat,nsoilmx_PEM) ! to store a global 3D data set
[3171]654real dx2_glop(klon_glo)
655real dx2_glo(nbp_lon,nbp_lat)     ! to store a global 2D (surface) data set
656real px2(ngrid)
657#endif
658
[3339]659! 0. Do we ouput a diagsoilpem.nc file? If not just bail out now.
[3171]660
[3339]661! additional check: one can only output diagsoilpem.nc files
[3171]662! in lon-lat case (or 1D)
663if (grid_type==unstructured) then
[3339]664  write(*,*) "writediagsoilpem: Error !!!"
665  write(*,*) "diagsoilpem.nc outputs not possible on unstructured grids!!"
666  call abort_physic("writediagsoilpem","impossible on unstructured grid",1)
[3171]667endif
668
669! 1. Initialization step
670if (firstname.eq."1234567890") then
671  ! Store 'name' as 'firstname'
672  firstname=name
673  ! From now on, if 'name'.eq.'firstname', then it is a new time cycle
674
675  ! just to be sure, check that firstnom is large enough to hold nom
676  if (len_trim(firstname).lt.len_trim(name)) then
[3339]677    write(*,*) "writediagsoilpem: Error !!!"
[3171]678    write(*,*) "   firstname string not long enough!!"
679    write(*,*) "   increase its size to at least ",len_trim(name)
[3339]680    call abort_physic("writediagsoilpem","firstname too short",1)
[3171]681  endif
[3532]682
[3171]683  ! Set output sample rate
[3214]684  isample = int(ecritpem) ! same as for diagpem outputs
[3532]685
[3171]686  ! Create output NetCDF file
687  if (is_master) then
688   ierr=NF_CREATE(filename,NF_CLOBBER,nid)
689   if (ierr.ne.NF_NOERR) then
[3339]690    write(*,*)'writediagsoilpem: Error, failed creating file '//trim(filename)
691    call abort_physic("writediagsoilpem","failed creating"//trim(filename),1)
[3171]692   endif
693  endif
694
695#ifdef CPP_PARA
[3345]696   ! Gather inertiedat_PEM() soil thermal inertia on physics grid
[3190]697   call Gather(inertiedat_PEM,inertiafi_glo)
[3171]698   ! Gather cell_area() mesh area on physics grid
699   call Gather(cell_area,areafi_glo)
700#else
[3190]701         inertiafi_glo(:,:)=inertiedat_PEM(:,:)
[3171]702         areafi_glo(:)=cell_area(:)
703#endif
704
705  if (is_master) then
706   ! build inertia() and area()
707   if (klon_glo>1) then
708    do i=1,nbp_lon+1 ! poles
[3190]709     inertia(i,1,1:nsoilmx_PEM)=inertiafi_glo(1,1:nsoilmx_PEM)
710     inertia(i,nbp_lat,1:nsoilmx_PEM)=inertiafi_glo(klon_glo,1:nsoilmx_PEM)
[3171]711     ! for area, divide at the poles by nbp_lon
712     area(i,1)=areafi_glo(1)/nbp_lon
713     area(i,nbp_lat)=areafi_glo(klon_glo)/nbp_lon
714    enddo
715    do j=2,nbp_lat-1
716     ig0= 1+(j-2)*nbp_lon
717     do i=1,nbp_lon
[3190]718        inertia(i,j,1:nsoilmx_PEM)=inertiafi_glo(ig0+i,1:nsoilmx_PEM)
[3171]719        area(i,j)=areafi_glo(ig0+i)
720     enddo
721     ! handle redundant point in longitude
[3190]722     inertia(nbp_lon+1,j,1:nsoilmx_PEM)=inertia(1,j,1:nsoilmx_PEM)
[3171]723     area(nbp_lon+1,j)=area(1,j)
724    enddo
725   endif
[3532]726
[3171]727   ! write "header" of file (longitudes, latitudes, geopotential, ...)
728   if (klon_glo>1) then ! general 3D case
[3345]729     call iniwritesoil(nid,ngrid,inertia,area,nbp_lon+1,nbp_lat,nsoilmx_PEM,mlayer_PEM)
[3171]730   else ! 1D model
[3345]731     call iniwritesoil(nid,ngrid,inertiafi_glo(1,:),areafi_glo(1),1,1,nsoilmx_PEM,mlayer_PEM)
[3171]732   endif
733
734  endif ! of if (is_master)
[3532]735
[3171]736  ! set zitau to -1 to be compatible with zitau incrementation step below
737  zitau=-1
[3532]738
[3171]739else
740  ! If not an initialization call, simply open the NetCDF file
741  if (is_master) then
742   ierr=NF_OPEN(filename,NF_WRITE,nid)
743  endif
744endif ! of if (firstname.eq."1234567890")
745
746! 2. Increment local time counter, if necessary
747if (name.eq.firstname) then
748  ! if we run across 'firstname', then it is a new time step
[3512]749  zitau = zitau + 1
[3171]750endif
751
752! 3. Write data, if the time index matches the sample rate
753if (mod(zitau+1,isample).eq.0) then
754
755! 3.1 If first call at this date, update 'time' variable
756  if (name.eq.firstname) then
757    ntime=ntime+1
[3214]758    date = float(zitau + 1)
[3532]759
[3171]760    if (is_master) then
761     ! Get NetCDF ID for "time"
762     ierr=NF_INQ_VARID(nid,"time",varid)
763     ! Add the current value of date to the "time" array
764!#ifdef NC_DOUBLE
765!     ierr=NF_PUT_VARA_DOUBLE(nid,varid,ntime,1,date)
766!#else
767     ierr=NF_PUT_VARA_REAL(nid,varid,[ntime],[1],[date])
768!#endif
769     if (ierr.ne.NF_NOERR) then
[3339]770      write(*,*)"writediagsoilpem: Failed writing date to time variable"
[3532]771      call abort_physic("writediagsoilpem","failed writing time",1)
[3171]772     endif
773    endif ! of if (is_master)
774  endif ! of if (name.eq.firstname)
775
776! 3.2 Write the variable to the NetCDF file
777if (dimpx.eq.3) then ! Case of a 3D variable
778  ! A. Recast data along 'dynamics' grid
[3345]779  if (klon_glo>1) then ! General case
[3171]780#ifdef CPP_PARA
781  ! gather field on a "global" (without redundant longitude) array
782  call Gather(px,dx3_glop)
783!$OMP MASTER
784  if (is_mpi_root) then
785    call Grid1Dto2D_glo(dx3_glop,dx3_glo)
786    ! copy dx3_glo() to dx3(:) and add redundant longitude
787    data3(1:nbp_lon,:,:)=dx3_glo(1:nbp_lon,:,:)
788    data3(nbp_lon+1,:,:)=data3(1,:,:)
789  endif
790!$OMP END MASTER
791!$OMP BARRIER
792#else
[3190]793   do l=1,nsoilmx_PEM
[3171]794    ! handle the poles
795    do i=1,nbp_lon+1
796      data3(i,1,l)=px(1,l)
797      data3(i,nbp_lat,l)=px(ngrid,l)
798    enddo
799    ! rest of the grid
800    do j=2,nbp_lat-1
801      ig0=1+(j-2)*nbp_lon
802      do i=1,nbp_lon
803        data3(i,j,l)=px(ig0+i,l)
804      enddo
805      data3(nbp_lon+1,j,l)=data3(1,j,l) ! extra (modulo) longitude
806    enddo
807   enddo
[3345]808#endif
[3171]809  else ! 1D model case
[3190]810   data3_1d(1,1:nsoilmx_PEM)=px(1,1:nsoilmx_PEM)
[3171]811  endif
[3532]812
[3171]813  ! B. Write (append) the variable to the NetCDF file
814  if (is_master) then
815  ! B.1. Get the ID of the variable
816  ierr=NF_INQ_VARID(nid,name,varid)
817  if (ierr.ne.NF_NOERR) then
818    ! If we failed geting the variable's ID, we assume it is because
819    ! the variable doesn't exist yet and must be created.
820    ! Start by obtaining corresponding dimensions IDs
821    ierr=NF_INQ_DIMID(nid,"longitude",id(1))
822    ierr=NF_INQ_DIMID(nid,"latitude",id(2))
823    ierr=NF_INQ_DIMID(nid,"depth",id(3))
824    ierr=NF_INQ_DIMID(nid,"time",id(4))
825    ! Tell the world about it
826    write(*,*) "====================="
[3339]827    write(*,*) "writediagsoilpem: creating variable "//trim(name)
[3171]828    call def_var(nid,name,title,units,4,id,varid,ierr)
829  endif ! of if (ierr.ne.NF_NOERR)
[3532]830
[3171]831  ! B.2. Prepare things to be able to write/append the variable
832  corners(1)=1
833  corners(2)=1
834  corners(3)=1
835  corners(4)=ntime
[3532]836
[3171]837  if (klon_glo==1) then
838    edges(1)=1
839  else
840    edges(1)=nbp_lon+1
841  endif
842  edges(2)=nbp_lat
[3190]843  edges(3)=nsoilmx_PEM
[3171]844  edges(4)=1
[3532]845
[3171]846  ! B.3. Write the slab of data
847!#ifdef NC_DOUBLE
848!  ierr=NF_PUT_VARA_DOUBLE(nid,varid,corners,edges,data3)
849!#else
850  if (klon_glo>1) then
851    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,data3)
852  else
853    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,data3_1d)
854  endif
855!#endif
856  if (ierr.ne.NF_NOERR) then
[3339]857    write(*,*) "writediagsoilpem: Error: Failed writing "//trim(name)//&
[3171]858               " to file "//trim(filename)//" at time",date
859  endif
860  endif ! of if (is_master)
861
862elseif (dimpx.eq.2) then ! Case of a 2D variable
863
864  ! A. Recast data along 'dynamics' grid
[3345]865  if (klon_glo>1) then ! General case
[3171]866#ifdef CPP_PARA
867  ! gather field on a "global" (without redundant longitude) array
868  px2(:)=px(:,1)
869  call Gather(px2,dx2_glop)
870!$OMP MASTER
871  if (is_mpi_root) then
872    call Grid1Dto2D_glo(dx2_glop,dx2_glo)
873    ! copy dx3_glo() to dx3(:) and add redundant longitude
874    data2(1:nbp_lon,:)=dx2_glo(1:nbp_lon,:)
875    data2(nbp_lon+1,:)=data2(1,:)
876  endif
877!$OMP END MASTER
878!$OMP BARRIER
879#else
880    ! handle the poles
881    do i=1,nbp_lon+1
882      data2(i,1)=px(1,1)
883      data2(i,nbp_lat)=px(ngrid,1)
884    enddo
885    ! rest of the grid
886    do j=2,nbp_lat-1
887      ig0=1+(j-2)*nbp_lon
888      do i=1,nbp_lon
889        data2(i,j)=px(ig0+i,1)
890      enddo
891      data2(nbp_lon+1,j)=data2(1,j) ! extra (modulo) longitude
892    enddo
[3345]893#endif
[3171]894  else ! 1D model case
895    data2_1d=px(1,1)
896  endif
897
898  ! B. Write (append) the variable to the NetCDF file
899  if (is_master) then
900  ! B.1. Get the ID of the variable
901  ierr=NF_INQ_VARID(nid,name,varid)
902  if (ierr.ne.NF_NOERR) then
903    ! If we failed geting the variable's ID, we assume it is because
904    ! the variable doesn't exist yet and must be created.
905    ! Start by obtaining corresponding dimensions IDs
906    ierr=NF_INQ_DIMID(nid,"longitude",id(1))
907    ierr=NF_INQ_DIMID(nid,"latitude",id(2))
908    ierr=NF_INQ_DIMID(nid,"time",id(3))
909    ! Tell the world about it
910    write(*,*) "====================="
[3339]911    write(*,*) "writediagsoilpem: creating variable "//trim(name)
[3171]912    call def_var(nid,name,title,units,3,id,varid,ierr)
913  endif ! of if (ierr.ne.NF_NOERR)
914
915  ! B.2. Prepare things to be able to write/append the variable
916  corners(1)=1
917  corners(2)=1
918  corners(3)=ntime
[3532]919
[3171]920  if (klon_glo==1) then
921    edges(1)=1
922  else
923    edges(1)=nbp_lon+1
924  endif
925  edges(2)=nbp_lat
926  edges(3)=1
[3532]927
[3171]928  ! B.3. Write the slab of data
929!#ifdef NC_DOUBLE
930!  ierr=NF_PUT_VARA_DOUBLE(nid,varid,corners,edges,data2)
931!#else
932  if (klon_glo>1) then ! General case
933    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,data2)
934  else
935    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,[data2_1d])
936  endif
937!#endif
938  if (ierr.ne.NF_NOERR) then
[3339]939    write(*,*) "writediagsoilpem: Error: Failed writing "//trim(name)//&
[3171]940               " to file "//trim(filename)//" at time",date
941  endif
942  endif ! of if (is_master)
943
944elseif (dimpx.eq.0) then ! Case of a 0D variable
945#ifdef CPP_PARA
[3339]946  write(*,*) "writediagsoilpem: dimps==0 case not implemented in // mode!!"
947  call abort_physic("writediagsoilpem","dimps==0 not implemented",1)
[3171]948#endif
949  ! A. Copy data value
950  data0=px(1,1)
951
952  ! B. Write (append) the variable to the NetCDF file
953  ! B.1. Get the ID of the variable
954  ierr=NF_INQ_VARID(nid,name,varid)
955  if (ierr.ne.NF_NOERR) then
956    ! If we failed geting the variable's ID, we assume it is because
957    ! the variable doesn't exist yet and must be created.
958    ! Start by obtaining corresponding dimensions IDs
959    ierr=NF_INQ_DIMID(nid,"time",id(1))
960    ! Tell the world about it
961    write(*,*) "====================="
[3339]962    write(*,*) "writediagsoilpem: creating variable "//trim(name)
[3171]963    call def_var(nid,name,title,units,1,id,varid,ierr)
964  endif ! of if (ierr.ne.NF_NOERR)
965
966  ! B.2. Prepare things to be able to write/append the variable
967  corners(1)=ntime
[3532]968
[3171]969  edges(1)=1
970
971  ! B.3. Write the data
972!#ifdef NC_DOUBLE
973!  ierr=NF_PUT_VARA_DOUBLE(nid,varid,corners,edges,data0)
974!#else
975  ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,[data0])
976!#endif
977  if (ierr.ne.NF_NOERR) then
[3339]978    write(*,*) "writediagsoilpem: Error: Failed writing "//trim(name)//&
[3171]979               " to file "//trim(filename)//" at time",date
980  endif
981
982endif ! of if (dimpx.eq.3) elseif (dimpx.eq.2) ...
983endif ! of if (mod(zitau+1,isample).eq.0)
984
985! 4. Close the NetCDF file
986if (is_master) then
987  ierr=NF_CLOSE(nid)
988endif
989
[3214]990END SUBROUTINE writediagsoilpem
[3171]991
[3088]992END MODULE writediagpem_mod
Note: See TracBrowser for help on using the repository browser.