source: trunk/LMDZ.GENERIC/libf/phystd/dyn1d/kcm1d.F90 @ 2803

Last change on this file since 2803 was 2785, checked in by emillour, 3 years ago

Generic PCM:
Further seperation between dynamics and physics concerning tracers:
Tracer names are extracted from traceur.def via initracer.F90 and no
longer transfered from the dynamics to the physics
LT+EM

  • Property svn:executable set to *
File size: 15.1 KB
Line 
1program kcm1d
2
3  use infotrac, only: nqtot
4  use radinc_h,      only: NAERKIND
5  use radcommon_h,   only: L_NSPECTI, L_NSPECTV, sigma, glat
6  use watercommon_h, only: mH2O
7  use ioipsl_getincom, only: getin
8  use comsaison_h, only: mu0, fract, dist_star
9  use planete_mod
10  use callkeys_mod, only: pceil, tstrat, tracer, global1d
11  use inifis_mod, only: inifis
12  use comcstfi_mod
13  use mod_grid_phy_lmdz, only : regular_lonlat
14  use regular_lonlat_mod, only: init_regular_lonlat
15  use physics_distribution_mod, only: init_physics_distribution
16  use regular_lonlat_mod, only: init_regular_lonlat
17  use mod_interface_dyn_phys, only: init_interface_dyn_phys
18  use geometry_mod, only: init_geometry
19  use dimphy, only : init_dimphy
20
21  implicit none
22
23  !==================================================================
24  !     
25  !     Purpose
26  !     -------
27  !     Run the universal model radiative transfer once in a 1D column.
28  !     Useful for climate evolution studies etc.
29  !     
30  !     It can be compiled with a command like (e.g. for 25 layers):
31  !                                  "makegcm -p std -d 25 kcm1d"
32  !     It requires the files "callphys.def", "gases.def"
33  !     "traceur.def", and "run.def" with a line "INCLUDEDEF=callphys.def"
34  !
35  !     Authors
36  !     -------
37  !     - R. Wordsworth
38  !     - updated by M. Turbet (June 2017)
39  !
40  !==================================================================
41
42#include "dimensions.h"
43!#include "dimphys.h"
44
45  ! --------------------------------------------------------------
46  !  Declarations
47  ! --------------------------------------------------------------
48
49  integer nlayer,nlevel,nq
50  integer ilay,ilev,iq,iw,iter
51  real play(llm)     ! Pressure at the middle of the layers [Pa]
52  real zlay(llm)     ! Altitude at middle of the layers [km]
53  real plev(llm+1)   ! Intermediate pressure levels [Pa]
54  real temp(llm)     ! temperature at the middle of the layers [K]
55  real,allocatable :: q(:,:)   ! tracer mixing ratio [kg/kg]
56  real,allocatable :: vmr(:,:) ! tracer mixing ratio [mol/mol]
57  real,allocatable :: qsurf(:)        ! tracer surface budget [kg/kg] ????
58  real psurf,psurf_n,tsurf     
59
60  real emis, albedo, albedo_equivalent
61  real albedo_wv(1,L_NSPECTV)
62
63  real muvar(llm+1)
64
65  real dtsw(llm) ! heating rate (K/s) due to SW
66  real dtlw(llm) ! heating rate (K/s) due to LW
67  real fluxsurf_lw   ! incident LW flux to surf (W/m2)
68  real fluxtop_lw    ! outgoing LW flux to space (W/m2)
69  real fluxsurf_sw   ! incident SW flux to surf (W/m2)
70  real fluxsurfabs_sw ! absorbed SW flux by the surf (W/m2)
71  real fluxabs_sw    ! SW flux absorbed by planet (W/m2)
72  real fluxtop_dn    ! incident top of atmosphere SW flux (W/m2)
73
74  ! not used
75  real cloudfrac(llm)
76  real totcloudfrac
77  real tau_col
78
79  real dTstrat
80  real aerosol(llm,naerkind) ! aerosol tau (kg/kg)
81  real OLR_nu(1,L_NSPECTI)
82  real OSR_nu(1,L_NSPECTV)
83  real Eatmtot
84
85  integer ierr
86  logical firstcall,lastcall
87
88  character*20,allocatable :: nametrac(:)   ! name of the tracer (no need for adv trac common)
89 
90  real :: latitude(1), longitude(1), cell_area(1), phisfi(1)
91 
92  !     added by JVO and YJ to read modern traceur.def
93  character(len=500) :: line ! to store a line of text
94  LOGICAL :: moderntracdef=.false. ! JVO, YJ : modern traceur.def
95
96  ! --------------
97  ! Initialisation
98  ! --------------
99
100  pi=2.E+0*asin(1.E+0)
101
102  cloudfrac(:)  = 0.0
103  totcloudfrac  = 0.0
104
105
106  nlayer=llm
107  nlevel=nlayer+1
108
109  !! this is defined in comsaison_h
110  ALLOCATE(mu0(1))
111  ALLOCATE(fract(1))
112  ALLOCATE(glat(1))
113
114  !  Load parameters from "run.def"
115  ! -------------------------------
116
117  ! check if 'kcm1d.def' file is around (otherwise reading parameters
118  ! from callphys.def via getin() routine won't work.)
119  open(90,file='kcm1d.def',status='old',form='formatted',&
120       iostat=ierr)
121  if (ierr.ne.0) then
122     write(*,*) 'Cannot find required file "kcm1d.def"'
123     write(*,*) '  (which should contain some input parameters'
124     write(*,*) '   along with the following line:'
125     write(*,*) '   INCLUDEDEF=callphys.def'
126     write(*,*) '   )'
127     write(*,*) ' ... might as well stop here ...'
128     stop
129  else
130     close(90)
131  endif
132 
133! now, run.def is needed anyway. so we create a dummy temporary one
134! for ioipsl to work. if a run.def is already here, stop the
135! program and ask the user to do a bit of cleaning
136  open(90,file='run.def',status='old',form='formatted',&
137       iostat=ierr)
138  if (ierr.eq.0) then
139     close(90)
140     write(*,*) 'There is already a run.def file.'
141     write(*,*) 'This is not compatible with 1D runs.'
142     write(*,*) 'Please remove the file and restart the run.'
143     write(*,*) 'Runtime parameters are supposed to be in kcm1d.def'
144     stop
145  else
146     call system('touch run.def')
147     call system("echo 'INCLUDEDEF=callphys.def' >> run.def")
148     call system("echo 'INCLUDEDEF=kcm1d.def' >> run.def")
149  endif
150   
151! check if we are going to run with or without tracers
152  write(*,*) "Run with or without tracer transport ?"
153  tracer=.false. ! default value
154  call getin("tracer",tracer)
155  write(*,*) " tracer = ",tracer
156
157
158
159  ! Tracer initialisation
160  ! ---------------------
161  if (tracer) then
162     ! load tracer names from file 'traceur.def'
163     open(90,file='traceur.def',status='old',form='formatted',&
164          iostat=ierr)
165     if (ierr.eq.0) then
166        write(*,*) "kcm1d: Reading file traceur.def"
167        ! read number of tracers:
168        !! - Modif. by JVO and YJ for modern planetary traceur.def ---------------
169        READ(90,'(A)') line
170        IF (trim(line).ne.'#ModernTrac-v1') THEN ! Test modern traceur.def
171           READ(line,*,iostat=ierr) nq ! Try standard traceur.def
172        ELSE
173           moderntracdef = .true.
174           DO
175             READ(90,'(A)',iostat=ierr) line
176             IF (ierr.eq.0) THEN
177               IF (index(line,'#').ne.1) THEN ! Allows arbitary number of comments lines in the header
178                 READ(line,*,iostat=ierr) nq
179                 EXIT
180               ENDIF
181             ELSE ! If pb, or if reached EOF without having found nbtr
182                write(*,*) "rcm1d: error reading number of tracers"
183                write(*,*) "   (first line of traceur.def) "
184                stop
185             ENDIF
186           ENDDO
187        ENDIF ! if modern or standard traceur.def
188        if (ierr.ne.0) then
189           write(*,*) "kcm1d: error reading number of tracers"
190           write(*,*) "   (first line of traceur.def) "
191           stop
192        endif
193        nqtot=nq
194        ! allocate arrays which depend on number of tracers
195        allocate(nametrac(nq))
196        allocate(q(nlayer,nq))
197        allocate(vmr(nlayer,nq))
198        allocate(qsurf(nq))
199
200        do iq=1,nq
201           ! minimal version, just read in the tracer names, 1 per line
202           read(90,*,iostat=ierr) nametrac(iq)
203           write(*,*) 'tracer here is', nametrac(iq)
204           if (ierr.ne.0) then
205              write(*,*) 'kcm1d: error reading tracer names...'
206              stop
207           endif
208        enddo !of do iq=1,nq
209        close(90)
210     endif
211
212     call initracer(1,nq)
213
214  endif
215 
216
217
218
219
220  psurf_n=100000. ! default value for psurf
221  print*,'Dry surface pressure (Pa)?'
222  call getin("psurf",psurf_n)
223  write(*,*) " psurf = ",psurf_n
224
225! OK. now that run.def has been read once -- any variable is in memory.
226! so we can dump the dummy run.def
227  call system("rm -rf run.def")
228
229  tsurf=300.0 ! default value for tsurf
230  print*,'Surface temperature (K)?'
231  call getin("tref",tsurf)
232  write(*,*) " tsurf = ",tsurf
233
234  g=10.0 ! default value for g
235  print*,'Gravity ?'
236  call getin("g",g)
237  write(*,*) " g = ",g
238  glat(1)=g
239
240  periastr = 1.0
241  apoastr  = 1.0
242  print*,'Periastron (AU)?'
243  call getin("periastr",periastr)
244  write(*,*) "periastron = ",periastr
245  dist_star = periastr
246  fract     = 0.5
247  print*,'Apoastron (AU)?'
248  call getin("apoastr",apoastr)
249  write(*,*) "apoastron = ",apoastr
250
251  albedo=0.2 ! default value for albedo
252  print*,'Albedo of bare ground?'
253  call getin("albedo",albedo)
254  write(*,*) " albedo = ",albedo
255  do iw=1,L_NSPECTV
256     albedo_wv(1,iw)=albedo
257  enddo
258
259  emis=1.0 ! default value for emissivity
260  PRINT *,'Emissivity of bare ground ?'
261  call getin("emis",emis)
262  write(*,*) " emis = ",emis
263
264  pceil=100.0 ! Pascals
265  PRINT *,'Ceiling pressure (Pa) ?'
266  call getin("pceil",pceil)
267  write(*,*) " pceil = ", pceil
268
269!!! GEOGRAPHICAL INITIALIZATIONS
270     !!! AREA. useless in 1D
271  cell_area(1)=1.E+0 !JL+EM to have access to the area in the diagfi.nc files.
272     !!! GEOPOTENTIAL. useless in 1D because control by surface pressure
273  phisfi(1)=0.E+0
274     !!! LATITUDE. can be set.
275  latitude=0 ! default value for latitude
276  PRINT *,'latitude (in degrees) ?'
277  call getin("latitude",latitude)
278  write(*,*) " latitude = ",latitude
279  latitude=latitude*pi/180.E+0
280     !!! LONGITUDE. useless in 1D.
281  longitude=0.E+0
282  longitude=longitude*pi/180.E+0
283
284  rad=6400000.
285  !rad = -99999.
286  !PRINT *,'PLANETARY RADIUS in m ?'
287  !call getin("rad",rad)
288  ! Planetary  radius is needed to compute shadow of the rings
289  !IF (rad.eq.-99999. .and. rings_shadow .eqv. .true.) THEN
290  !   PRINT *,"STOP. I NEED rad IN RCM1D.DEF."
291  !   STOP
292  !ELSE
293  !   PRINT *,"--> rad = ",rad
294  !ENDIF
295
296
297
298  call init_physics_distribution(regular_lonlat,4,1,1,1,nlayer,1)
299  call init_interface_dyn_phys
300  CALL init_regular_lonlat(1,1,longitude,latitude,(/0.,0./),(/0.,0./))
301  call init_geometry(1,longitude,latitude,(/0.,0.,0.,0./),(/0.,0.,0.,0./),cell_area)
302  call init_dimphy(1,nlayer) ! Initialize dimphy module
303
304!!! CALL INIFIS
305!!! - read callphys.def
306!!! - calculate sine and cosine of longitude and latitude
307!!! - calculate mugaz and cp
308!!! NB: some operations are being done dummily in inifis in 1D
309!!! - physical constants: nevermind, things are done allright below
310!!! - physical frequency: nevermind, in inifis this is a simple print
311
312  cpp=1.d-7 !JL because we divide by cpp in inifis, there may be a more elegant solution
313  CALL inifis(1,llm,nq,0,86400.0,1,1.0,latitude,longitude,cell_area,rad,g,r,cpp)
314
315  if(.not.global1d)then
316     print*,'Error, kcm1d must have global1d=.true. in kcm1d.def!'
317     stop
318  end if
319
320  !write(*,*) 'BASE 1'
321  !write(*,*) 1,llm,nq,0,86400.0,1,1.0,latitude,longitude,cell_area,rad,g,r,cpp
322
323  do iq=1,nq
324     do ilay=1,nlayer
325        q(ilay,iq) = 0.
326     enddo
327  enddo
328 
329  do iq=1,nq
330     qsurf(iq) = 0.
331  enddo
332
333  firstcall = .true.
334  lastcall  = .false.
335
336  iter    = 1
337  Tstrat  = 150.0
338  dTstrat = 1000.0
339
340  ! ---------
341  ! Run model
342  ! ---------
343  !do
344  psurf = psurf_n
345
346     !    Create vertical profiles
347  call kcmprof_fn(nlayer,psurf,qsurf(1),tsurf,    &
348       tstrat,play,plev,zlay,temp,q(:,1),muvar(1))
349         
350
351  !write(*,*) 'BASE 2'
352  !write(*,*) nlayer,psurf,qsurf(1),tsurf,    &
353  !           tstrat
354  !write(*,*) play
355  !write(*,*) plev
356  !write(*,*) zlay
357  !write(*,*) temp
358  !write(*,*) q(:,1),muvar(1)
359
360         
361               
362     call iniaerosol()
363     
364
365     
366
367     !    Run radiative transfer
368     call callcorrk(1,nlayer,q,nq,qsurf,                  &
369          albedo_wv,albedo_equivalent,                    &
370          emis,mu0,plev,play,temp,                        &
371          tsurf,fract,dist_star,aerosol,muvar,            &
372          dtlw,dtsw,fluxsurf_lw,fluxsurf_sw,              &
373          fluxsurfabs_sw,fluxtop_lw,                      &
374          fluxabs_sw,fluxtop_dn,OLR_nu,OSR_nu,tau_col,    &
375          cloudfrac,totcloudfrac,.false.,firstcall,lastcall)
376
377     !write(*,*) 'BASE 3'
378     !write(*,*) 1,nlayer,'A',q,'B',nq,'C',qsurf,                      &
379     !     albedo_wv,'D',albedo_equivalent,'E',                    &
380     !     emis,'F',mu0,'G',plev,'H',play,'I',temp,'J',                        &
381     !     tsurf,'K',fract,'L',dist_star,'M',aerosol,'N',muvar,'O',            &
382     !     dtlw,'P',dtsw,'Q',fluxsurf_lw,'R',fluxsurf_sw,'S',              &
383     !     fluxsurfabs_sw,'T',fluxtop_lw,'U',                      &
384     !     fluxabs_sw,'V',fluxtop_dn,'W',OLR_nu,'X',OSR_nu,'Y',tau_col,'Z',    &
385     !     cloudfrac,'A1',totcloudfrac,'A2',.false.,'A3',firstcall,'A4',lastcall
386
387
388
389
390
391
392
393     !    Iterate stratospheric temperature
394     print*,'Tstrat = ',Tstrat
395     dTstrat = Tstrat
396     !Tstrat  = Tsurf*(0.2786*(psurf/100000.)**(-1.123))**0.25
397     ! skin temperature (gray approx.) using analytic pure H2 expression
398     !Tstrat  = (fluxabs_sw/(2*sigma))**0.25 ! skin temperature (gray approx.)
399     Tstrat  = (fluxtop_lw/(2*sigma))**0.25 ! skin temperature (gray approx.)
400     dTstrat = dTstrat-Tstrat
401
402     !if(abs(dTstrat).lt.1.0)then
403     !   print*,'dTstrat = ',dTstrat
404     !   exit
405     !endif
406
407     !iter=iter+1
408     !if(iter.eq.100)then
409     !   print*,'Stratosphere failed to converge after'
410     !   print*,'100 iteration, aborting run.'
411     !   call abort
412     !endif
413
414  !end do
415
416
417  ! Run radiative transfer one last time to get OLR,OSR
418  firstcall=.false.
419  lastcall=.true.
420  call callcorrk(1,nlayer,q,nq,qsurf,                          &
421       albedo_wv,albedo_equivalent,emis,mu0,plev,play,temp,    &
422       tsurf,fract,dist_star,aerosol,muvar,                    &
423       dtlw,dtsw,fluxsurf_lw,fluxsurf_sw,fluxsurfabs_sw,       &
424       fluxtop_lw, fluxabs_sw,fluxtop_dn,OLR_nu,OSR_nu,        &
425       tau_col,                                                &
426       cloudfrac,totcloudfrac,.false.,firstcall,lastcall)
427
428
429     !write(*,*) 'BASE 4'
430     !write(*,*) 1,nlayer,'A',q,'B',nq,'C',qsurf,                      &
431     !     albedo_wv,'D',albedo_equivalent,'E',                    &
432     !     emis,'F',mu0,'G',plev,'H',play,'I',temp,'J',                        &
433     !     tsurf,'K',fract,'L',dist_star,'M',aerosol,'N',muvar,'O',            &
434     !     dtlw,'P',dtsw,'Q',fluxsurf_lw,'R',fluxsurf_sw,'S',              &
435     !     fluxsurfabs_sw,'T',fluxtop_lw,'U',                      &
436     !     fluxabs_sw,'V',fluxtop_dn,'W',OLR_nu,'X',OSR_nu,'Y',tau_col,'Z',    &
437     !     cloudfrac,'A1',totcloudfrac,'A2',.false.,'A3',firstcall,'A4',lastcall
438
439
440
441
442
443
444
445  ! Calculate total atmospheric energy
446  Eatmtot=0.0
447  !  call calcenergy_kcm(nlayer,tsurf,temp,play,plev,qsurf,&
448  !     q(:,1),muvar,Eatmtot)
449
450  ! ------------------------
451  ! Save data to ascii files
452  ! ------------------------
453
454  print*,'Saving profiles...'
455  open(115,file='profpres.out',form='formatted')
456  open(116,file='proftemp.out',form='formatted')
457  open(117,file='profztab.out',form='formatted')
458  open(118,file='profqvar.out',form='formatted')
459  open(119,file='profvvar.out',form='formatted')
460
461  write(115,*) psurf
462  write(116,*) tsurf
463  write(117,*) 0.0
464  write(118,*) qsurf(1)
465  write(119,*) qsurf(1)*(muvar(1)/mH2O)
466  do ilay=1,nlayer
467     vmr(ilay,1) = q(ilay,1)*(muvar(ilay+1)/mH2O)
468     write(115,*) play(ilay)
469     write(116,*) temp(ilay)
470     write(117,*) zlay(ilay)
471     write(118,*) q(ilay,1)
472     write(119,*) vmr(ilay,1)
473  enddo
474  close(115)
475  close(116)
476  close(117)
477  close(118)
478  close(119)
479
480  print*, tsurf,psurf,fluxtop_dn,fluxabs_sw,fluxtop_lw
481
482  print*,'Saving scalars...'
483  open(116,file='surf_vals.out')
484  write(116,*) tsurf,psurf,fluxtop_dn,         &
485       fluxabs_sw,fluxtop_lw
486  close(116)
487  open(111,file='ene_vals.out')
488  write(111,*) tsurf,psurf,Eatmtot,Tstrat
489  close(111)
490
491  print*,'Saving spectra...'
492  open(117,file='OLRnu.out')
493  do iw=1,L_NSPECTI
494     write(117,*) OLR_nu(1,iw)
495  enddo
496  close(117)
497
498  open(127,file='OSRnu.out')
499  do iw=1,L_NSPECTV
500     write(127,*) OSR_nu(1,iw)
501  enddo
502  close(127) 
503
504end program kcm1d
Note: See TracBrowser for help on using the repository browser.