source: trunk/LMDZ.COMMON/libf/dyn3d_common/dynetat0.F90 @ 3556

Last change on this file since 3556 was 2439, checked in by emillour, 4 years ago

Common dynamics:
Add a check that input fields (read from start.nc file) indeed have
matching values along the longitude end points when they should,
and if not correct field at longitude index iimp1 to match value
at longitude index 1.
EM

File size: 15.5 KB
RevLine 
[1]1!
2! $Id $
3!
[1508]4SUBROUTINE dynetat0(fichnom,vcov,ucov,teta,q,masse,ps,phis,time0)
[1]5
[1508]6      USE infotrac, only: tname, nqtot, zone_num, iso_indnum,&
7                          iso_num, phase_num, alpha_ideal, iqiso, &
8                          ok_isotopes, iqpere, tnat
9      use netcdf, only: nf90_open,NF90_NOWRITE,nf90_noerr,nf90_strerror, &
10                        nf90_get_var, nf90_inq_varid, nf90_inq_dimid, &
11                        nf90_inquire_dimension,nf90_close
[841]12
[1107]13      use control_mod, only : planet_type, timestart
[1422]14      USE comvert_mod, ONLY: pa,preff
[1508]15      USE comconst_mod, ONLY: im,jm,lllm,daysec,dtvr, &
16                        rad,omeg,g,cpp,kappa,pi
[1422]17      USE logic_mod, ONLY: fxyhypb,ysinus
18      USE serre_mod, ONLY: clon,clat,grossismx,grossismy
[1508]19      USE temps_mod, ONLY: annee_ref,day_ref,itau_dyn, &
20                        start_time,day_ini,hour_ini
[1422]21      USE ener_mod, ONLY: etot0,ptot0,ztot0,stot0,ang0
[841]22
[1]23      IMPLICIT NONE
24
[1508]25!=======================================================================
26!
27! Read initial confitions file
28!
29!=======================================================================
[1]30
[1508]31  include "dimensions.h"
32  include "paramet.h"
33  include "comgeom2.h"
34  include "iniprint.h"
[1]35
[1508]36!===============================================================================
37! Arguments:
38  CHARACTER(LEN=*), INTENT(IN) :: fichnom          !--- FILE NAME
39  REAL, INTENT(OUT) ::  vcov(iip1,jjm, llm)        !--- V COVARIANT WIND
40  REAL, INTENT(OUT) ::  ucov(iip1,jjp1,llm)        !--- U COVARIANT WIND
41  REAL, INTENT(OUT) ::  teta(iip1,jjp1,llm)        !--- POTENTIAL TEMP.
42  REAL, INTENT(OUT) ::     q(iip1,jjp1,llm,nqtot)  !--- TRACERS
43  REAL, INTENT(OUT) :: masse(iip1,jjp1,llm)        !--- MASS PER CELL
44  REAL, INTENT(OUT) ::    ps(iip1,jjp1)            !--- GROUND PRESSURE
45  REAL, INTENT(OUT) ::  phis(iip1,jjp1)            !--- GEOPOTENTIAL
46  REAL,INTENT(OUT) :: time0
47!===============================================================================
48!   Local Variables
49  CHARACTER(LEN=256) :: msg, var, modname
50  INTEGER,PARAMETER :: length=100
51  INTEGER :: iq, fID, vID, idecal
52  REAL :: tab_cntrl(length) ! array containing run parameters
53  INTEGER :: ierr
54  CHARACTER(len=12) :: start_file_type="earth" ! default start file type
[1]55
[1508]56  REAL,ALLOCATABLE :: time(:) ! times stored in start
57  INTEGER :: timelen ! number of times stored in the file
58  INTEGER :: indextime ! index of selected time
59  !REAL  hour_ini ! fraction of day of stored date. Equivalent of day_ini, but 0=<hour_ini<1
[1]60
[1508]61  INTEGER :: edges(4),corner(4)
62  INTEGER :: i
[1]63
[1508]64!-----------------------------------------------------------------------
65  modname="dynetat0"
[841]66
[1508]67!  Open initial state NetCDF file
68  var=fichnom
69  CALL err(NF90_OPEN(var,NF90_NOWRITE,fID),"open",var)
70!
71  CALL get_var1("controle",tab_cntrl)
[1107]72
[841]73      !!! AS: idecal is a hack to be able to read planeto starts...
74      !!!     .... while keeping everything OK for LMDZ EARTH
75      if ((planet_type.eq."generic").or.(planet_type.eq."mars")) then
76          write(lunout,*)'dynetat0 : Planeto-like start file'
[907]77          start_file_type="planeto"
[841]78          idecal = 4
79          annee_ref  = 2000
80      else
[1850]81          if (planet_type.eq."titan") then
82             ! Titan inherited Earth-like start files with idecal=5
83             write(lunout,*)'dynetat0 : Titan start file'
84          else
85             write(lunout,*)'dynetat0 : Earth-like start file'
86          endif
[841]87          idecal = 5
88          annee_ref  = tab_cntrl(5)
89      endif
90
91
[1]92      im         = tab_cntrl(1)
93      jm         = tab_cntrl(2)
94      lllm       = tab_cntrl(3)
[907]95      if (start_file_type.eq."earth") then
96        day_ref    = tab_cntrl(4)
97      else
98        day_ini    = tab_cntrl(4)
99        day_ref=0
100      endif
[841]101      rad        = tab_cntrl(idecal+1)
102      omeg       = tab_cntrl(idecal+2)
103      g          = tab_cntrl(idecal+3)
104      cpp        = tab_cntrl(idecal+4)
105      kappa      = tab_cntrl(idecal+5)
106      daysec     = tab_cntrl(idecal+6)
107      dtvr       = tab_cntrl(idecal+7)
108      etot0      = tab_cntrl(idecal+8)
109      ptot0      = tab_cntrl(idecal+9)
110      ztot0      = tab_cntrl(idecal+10)
111      stot0      = tab_cntrl(idecal+11)
112      ang0       = tab_cntrl(idecal+12)
113      pa         = tab_cntrl(idecal+13)
114      preff      = tab_cntrl(idecal+14)
[1508]115!
[841]116      clon       = tab_cntrl(idecal+15)
117      clat       = tab_cntrl(idecal+16)
118      grossismx  = tab_cntrl(idecal+17)
119      grossismy  = tab_cntrl(idecal+18)
[1508]120!
[841]121      IF ( tab_cntrl(idecal+19).EQ.1. )  THEN
[1508]122        fxyhypb  = .TRUE.
123!        dzoomx   = tab_cntrl(25)
124!        dzoomy   = tab_cntrl(26)
125!        taux     = tab_cntrl(28)
126!        tauy     = tab_cntrl(29)
[1]127      ELSE
[1508]128        fxyhypb = .FALSE.
129        ysinus  = .FALSE.
130        IF( tab_cntrl(idecal+22).EQ.1. ) ysinus = .TRUE.
[1]131      ENDIF
132
[1107]133      if (planet_type=="mars") then ! so far this is only for Mars
134        hour_ini = tab_cntrl(29)
135      else
136        hour_ini=0
137      endif
138
[907]139      if (start_file_type.eq."earth") then
140        day_ini = tab_cntrl(30)
141        itau_dyn = tab_cntrl(31)
142        start_time = tab_cntrl(32)
143      else
144        day_ini=tab_cntrl(4)
145        itau_dyn=0
146        start_time=0
147      endif
[1508]148!   .................................................................
149!
150!
151  WRITE(lunout,*)trim(modname)//': rad,omeg,g,cpp,kappa ', &
152                     rad,omeg,g,cpp,kappa
[1]153
[1508]154  CALL check_dim(im,iim,'im','iim')
155  CALL check_dim(jm,jjm,'jm','jjm')
156  CALL check_dim(llm,lllm,'llm','lllm')
[1]157
[1508]158  CALL get_var1("rlonu",rlonu)
159  CALL get_var1("rlatu",rlatu)
160  CALL get_var1("rlonv",rlonv)
161  CALL get_var1("rlatv",rlatv)
[1]162
[1508]163  CALL get_var2("cu"   ,cu)
164  CALL get_var2("cv"   ,cv)
[1]165
[1508]166  CALL get_var2("aire" ,aire)
167  CALL get_var2("phisinit",phis)
[1]168
[1107]169! read time axis
[1508]170      ierr = nf90_inq_varid (fID, "temps", vID)
[1107]171      IF (ierr .NE. nf90_noerr) THEN
172        write(lunout,*)"dynetat0: Le champ <temps> est absent"
173        write(lunout,*)"dynetat0: J essaie <Time>"
[1508]174        ierr = nf90_inq_varid (fID, "Time", vID)
[1107]175        IF (ierr .NE. nf90_noerr) THEN
176           write(lunout,*)"dynetat0: Le champ <Time> est absent"
177           write(lunout,*)trim(nf90_strerror(ierr))
[1300]178           CALL ABORT_gcm("dynetat0", "", 1)
[1107]179        ENDIF
180        ! Get the length of the "Time" dimension
[1508]181        ierr = nf90_inq_dimid(fID,"Time",vID)
182        ierr = nf90_inquire_dimension(fID,vID,len=timelen)
[1107]183        allocate(time(timelen))
184        ! Then look for the "Time" variable
[1508]185        ierr  =nf90_inq_varid(fID,"Time",vID)
186        ierr = nf90_get_var(fID, vID, time)
[1107]187        IF (ierr .NE. nf90_noerr) THEN
188           write(lunout,*)"dynetat0: Lecture echouee <Time>"
189           write(lunout,*)trim(nf90_strerror(ierr))
[1300]190           CALL ABORT_gcm("dynetat0", "", 1)
[1107]191        ENDIF
192      ELSE   
193        ! Get the length of the "temps" dimension
[1508]194        ierr = nf90_inq_dimid(fID,"temps",vID)
195        ierr = nf90_inquire_dimension(fID,vID,len=timelen)
[1107]196        allocate(time(timelen))
197        ! Then look for the "temps" variable
[1508]198        ierr = nf90_inq_varid (fID, "temps", vID)
199        ierr = nf90_get_var(fID, vID, time)
[1107]200        IF (ierr .NE. nf90_noerr) THEN
201           write(lunout,*)"dynetat0: Lecture echouee <temps>"
202           write(lunout,*)trim(nf90_strerror(ierr))
[1300]203           CALL ABORT_gcm("dynetat0", "", 1)
[1107]204        ENDIF
[1]205      ENDIF
[1107]206
207! select the desired time
208      IF (timestart .lt. 0) THEN  ! default: we use the last time value
209        indextime = timelen
210      ELSE  ! else we look for the desired value in the time axis
211       indextime = 0
212        DO i=1,timelen
213          IF (abs(time(i) - timestart) .lt. 0.01) THEN
214             indextime = i
215             EXIT
216          ENDIF
217        ENDDO
218        IF (indextime .eq. 0) THEN
[1508]219          write(lunout,*)"Time", timestart," is not in " &
220                                            //trim(fichnom)//"!!"
[1107]221          write(lunout,*)"Stored times are:"
222          DO i=1,timelen
223             PRINT*, time(i)
224          ENDDO
[1300]225          CALL ABORT_gcm("dynetat0", "", 1)
[1107]226        ENDIF
227      ENDIF
228
229      if (planet_type=="mars") then
230        ! In start the absolute date is day_ini + hour_ini + time
231        ! For now on, in the GCM dynamics, it is day_ini + time0
232        time0 = time(indextime) + hour_ini
233        day_ini = day_ini + INT(time0)
234        time0 = time0 - INT(time0) ! time0 devient le nouveau hour_ini
235        hour_ini = time0
236      else
237        time0 = time(indextime)
238      endif
239     
[1508]240      PRINT*, "dynetat0: Selected time ",time(indextime), &
241              " at index ",indextime
[1107]242     
243      DEALLOCATE(time)
244
245! read vcov
[1508]246  CALL get_var3v_t("vcov",vcov,indextime)
[1]247
[1107]248! read ucov
[1508]249  CALL get_var3u_t("ucov",ucov,indextime)
[1]250 
[1107]251! read teta (same corner/edges as ucov)
[1508]252  CALL get_var3u_t("teta",teta,indextime)
[1]253
[1107]254! read tracers (same corner/edges as ucov)
[1508]255  corner(1)=1
256  corner(2)=1
257  corner(3)=1
258  corner(4)=indextime
259  edges(1)=iip1
260  edges(2)=jjp1
261  edges(3)=llm
262  edges(4)=1
263  IF(nqtot.GE.1) THEN
[1]264      DO iq=1,nqtot
[1508]265        ierr= nf90_inq_varid(fID,tname(iq),vID)
[1107]266        IF (ierr .NE. nf90_noerr) THEN
[2337]267           write(lunout,*)TRIM(modname)//": Tracer <"//TRIM(tname(iq))//"> is missing"
[1508]268           write(lunout,*)"         It is hence initialized to zero"
[776]269           q(:,:,:,iq)=0.
[1508]270           IF (planet_type=="earth") THEN
271            !--- CRisi: for isotops, theoretical initialization using very simplified
272            !           Rayleigh distillation las.
273            IF(ok_isotopes.AND.iso_num(iq)>0) THEN
274             IF(zone_num(iq)==0) q(:,:,:,iq)=q(:,:,:,iqpere(iq))*tnat(iso_num(iq))    &
275             &             *(q(:,:,:,iqpere(iq))/30.e-3)**(alpha_ideal(iso_num(iq))-1)
276             IF(zone_num(iq)==1) q(:,:,:,iq)=q(:,:,:,iqiso(iso_indnum(iq),phase_num(iq)))
277            END IF
278           ENDIF
[1]279        ELSE
[1508]280           ierr=nf90_get_var(fID,vID,q(:,:,:,iq),corner,edges)
[1107]281          IF (ierr .NE. nf90_noerr) THEN
[1508]282            write(lunout,*)"dynetat0: Lecture echouee pour " &
283                                      //trim(tname(iq))
[1107]284            write(lunout,*)trim(nf90_strerror(ierr))
[1300]285            CALL ABORT_gcm("dynetat0", "", 1)
[1]286          ENDIF
287        ENDIF
288      ENDDO
[1508]289  ENDIF
[1]290
[1107]291!read masse (same corner/edges as ucov)
[1508]292  CALL get_var3u_t("masse",masse,indextime)
[1]293
[1508]294!read ps
295  CALL get_var2_t("ps",ps,indextime)
[1]296
[1508]297  CALL err(NF90_CLOSE(fID),"close",fichnom)
[1]298
[1508]299  if (planet_type/="mars") then
300    day_ini=day_ini+INT(time0) ! obsolete stuff ; 0<time<1 anyways
301    time0=time0-INT(time0)
302  endif
[1]303
304
[1508]305  CONTAINS
306
307SUBROUTINE check_dim(n1,n2,str1,str2)
308  INTEGER,          INTENT(IN) :: n1, n2
309  CHARACTER(LEN=*), INTENT(IN) :: str1, str2
310  CHARACTER(LEN=256) :: s1, s2
311  IF(n1/=n2) THEN
312    s1='value of '//TRIM(str1)//' ='
313    s2=' read in starting file differs from parametrized '//TRIM(str2)//' ='
[1824]314    WRITE(msg,'(10x,a,i4,2x,a,i4)')TRIM(s1),n1,TRIM(s2),n2
[1508]315    CALL ABORT_gcm(TRIM(modname),TRIM(msg),1)
316  END IF
317END SUBROUTINE check_dim
318
319
320SUBROUTINE get_var1(var,v)
321  CHARACTER(LEN=*), INTENT(IN)  :: var
322  REAL,             INTENT(OUT) :: v(:)
323  CALL err(NF90_INQ_VARID(fID,var,vID),"inq",var)
324  CALL err(NF90_GET_VAR(fID,vID,v),"get",var)
325END SUBROUTINE get_var1
326
327
328SUBROUTINE get_var2(var,v)
329  CHARACTER(LEN=*), INTENT(IN)  :: var
330  REAL,             INTENT(OUT) :: v(:,:)
[2439]331  INTEGER :: j
[1508]332  CALL err(NF90_INQ_VARID(fID,var,vID),"inq",var)
333  CALL err(NF90_GET_VAR(fID,vID,v),"get",var)
[2439]334  ! Check that if on iip1 points along the longitude
335  ! values indeed perfectly match at end points
336  if (size(v,1)==iip1) then
337    do j=1,size(v,2)
338      if (v(1,j).ne.v(iip1,j)) then
339        ! tell the world
340        write(*,*) "Warning: longitudinal modulo discrepency for ",trim(var)
341        write(*,*) "j=",j," v(1,j)=",v(1,j)," v(iip1,j)=",v(iip1,j)
342        ! copy over value from v(1,j) to v(iip1,j)
343        write(*,*) "setting v(iip1,j)=v(1,j)"
344        v(iip1,j)=v(1,j)
345      endif ! of if (v(1,j).ne.v(iip1,j))
346    enddo ! of do j=1,size(v,2)
347  endif ! of if (size(v,1)==iip1)
[1508]348END SUBROUTINE get_var2
349
350SUBROUTINE get_var2_t(var,v,indextime)
351  CHARACTER(LEN=*), INTENT(IN)  :: var
352  REAL,             INTENT(OUT) :: v(:,:)
353  INTEGER, INTENT(IN) :: indextime
[2439]354  INTEGER :: j
[1508]355  corner(1)=1
356  corner(2)=1
357  corner(3)=indextime
358  edges(1)=iip1
359  edges(2)=jjp1
360  edges(3)=1
361  CALL err(NF90_INQ_VARID(fID,var,vID),"inq",var)
362  CALL err(NF90_GET_VAR(fID,vID,v,corner,edges),"get",var)
[2439]363  ! Check that if on iip1 points along the longitude
364  ! values indeed perfectly match at end points
365  if (size(v,1)==iip1) then
366    do j=1,size(v,2)
367      if (v(1,j).ne.v(iip1,j)) then
368        ! tell the world
369        write(*,*) "Warning: longitudinal modulo discrepency for ",trim(var)
370        write(*,*) "j=",j," v(1,j)=",v(1,j)," v(iip1,j)=",v(iip1,j)
371        ! copy over value from v(1,j) to v(iip1,j)
372        write(*,*) "setting v(iip1,j)=v(1,j)"
373        v(iip1,j)=v(1,j)
374      endif ! of if (v(1,j).ne.v(iip1,j))
375    enddo ! of do j=1,size(v,2)
376  endif ! of if (size(v,1)==iip1)
[1508]377END SUBROUTINE get_var2_t
378
379
380SUBROUTINE get_var3(var,v) ! on U grid
381  CHARACTER(LEN=*), INTENT(IN)  :: var
382  REAL,             INTENT(OUT) :: v(:,:,:)
383  CALL err(NF90_INQ_VARID(fID,var,vID),"inq",var)
384  CALL err(NF90_GET_VAR(fID,vID,v),"get",var)
385END SUBROUTINE get_var3
386
387SUBROUTINE get_var3u_t(var,v,indextime) ! on U grid
388  CHARACTER(LEN=*), INTENT(IN)  :: var
389  REAL,             INTENT(OUT) :: v(:,:,:)
390  INTEGER, INTENT(IN) :: indextime
[2439]391  INTEGER :: j,k
[1508]392  corner(1)=1
393  corner(2)=1
394  corner(3)=1
395  corner(4)=indextime
396  edges(1)=iip1
397  edges(2)=jjp1
398  edges(3)=llm
399  edges(4)=1
400  CALL err(NF90_INQ_VARID(fID,var,vID),"inq",var)
401  CALL err(NF90_GET_VAR(fID,vID,v,corner,edges),"get",var)
[2439]402  ! Check that values indeed perfectly match at end points along longitude
403  do k=1,llm
404    do j=1,jjp1
405      if (v(1,j,k).ne.v(iip1,j,k)) then
406        ! tell the world
407        write(*,*) "Warning: longitudinal modulo discrepency for ",trim(var)
408        write(*,*) "j=",j," k=",k
409        write(*,*) " v(1,j,k)=",v(1,j,k)," v(iip1,j,k)=",v(iip1,j,k)
410        ! copy over value from v(1,j,k) to v(iip1,j,k)
411        write(*,*) "setting v(iip1,j,k)=v(1,j,k)"
412        v(iip1,j,k)=v(1,j,k)
413      endif ! of if (v(1,j,k).ne.v(iip1,j,k))
414    enddo ! of do j=1,jjp1
415  enddo ! of do k=1,llm
[1508]416END SUBROUTINE get_var3u_t
417
418SUBROUTINE get_var3v_t(var,v,indextime) ! on V grid
419  CHARACTER(LEN=*), INTENT(IN)  :: var
420  REAL,             INTENT(OUT) :: v(:,:,:)
421  INTEGER, INTENT(IN) :: indextime
[2439]422  INTEGER :: j,k
[1508]423  corner(1)=1
424  corner(2)=1
425  corner(3)=1
426  corner(4)=indextime
427  edges(1)=iip1
428  edges(2)=jjm
429  edges(3)=llm
430  edges(4)=1
431  CALL err(NF90_INQ_VARID(fID,var,vID),"inq",var)
432  CALL err(NF90_GET_VAR(fID,vID,v,corner,edges),"get",var)
[2439]433  ! Check that values indeed perfectly match at end points along longitude
434  do k=1,llm
435    do j=1,jjm
436      if (v(1,j,k).ne.v(iip1,j,k)) then
437        ! tell the world
438        write(*,*) "Warning: longitudinal modulo discrepency for ",trim(var)
439        write(*,*) "j=",j," k=",k
440        write(*,*) " v(1,j,k)=",v(1,j,k)," v(iip1,j,k)=",v(iip1,j,k)
441        ! copy over value from v(1,j,k) to v(iip1,j,k)
442        write(*,*) "setting v(iip1,j,k)=v(1,j,k)"
443        v(iip1,j,k)=v(1,j,k)
444      endif ! of if (v(1,j,k).ne.v(iip1,j,k))
445    enddo ! of do j=1,jjm
446  enddo ! of do k=1,llm
[1508]447END SUBROUTINE get_var3v_t
448
449SUBROUTINE err(ierr,typ,nam)
450  INTEGER,          INTENT(IN) :: ierr   !--- NetCDF ERROR CODE
451  CHARACTER(LEN=*), INTENT(IN) :: typ    !--- TYPE OF OPERATION
452  CHARACTER(LEN=*), INTENT(IN) :: nam    !--- FIELD/FILE NAME
453  IF(ierr==NF90_NoERR) RETURN
454  SELECT CASE(typ)
455    CASE('inq');   msg="Field <"//TRIM(nam)//"> is missing"
456    CASE('get');   msg="Reading failed for <"//TRIM(nam)//">"
457    CASE('open');  msg="File opening failed for <"//TRIM(nam)//">"
458    CASE('close'); msg="File closing failed for <"//TRIM(nam)//">"
459  END SELECT
460  CALL ABORT_gcm(TRIM(modname),TRIM(msg),ierr)
461END SUBROUTINE err
462
463END SUBROUTINE dynetat0
Note: See TracBrowser for help on using the repository browser.