source: codes/icosagcm/branches/SATURN_DYNAMICO/LMDZ.COMMON/libf/phystd/radsponge.F90 @ 310

Last change on this file since 310 was 310, checked in by millour, 10 years ago

Add the possibility to have a sponge acting on the temperature
in the physics, using flag "callradsponge=.true.". The sponge
vertical extention is the same as the sponge layer in the dynamics.
EM

File size: 4.9 KB
Line 
1subroutine radsponge(ngrid,nlayer,pplay,pplev,temp,pdt,dtphys,dtradsponge)
2! add a (vertical) sponge effect on temperature to damp oscillations
3! near the model top (topmost
4! Quenching is modeled as: A(t)=Am+A0exp(-lambda*t)
5! where Am is the zonal average of the field (or zero), and lambda the inverse
6! of the characteristic quenching/relaxation time scale
7! Thus, assuming Am to be time-independent, field at time t+dt is given by:
8! A(t+dt)=A(t)-(A(t)-Am)*(1-exp(-lambda*dt))
9
10use ioipsl_getincom_p, only: getin_p
11use mod_phys_lmdz_para, only : is_master
12
13implicit none
14
15integer,intent(in) :: ngrid ! number of atmospheric columns
16integer,intent(in) :: nlayer ! number of atmospheric layers
17real,intent(in) :: pplay(ngrid,nlayer) ! mid-layer pressure (Pa)
18real,intent(in) :: pplev(ngrid,nlayer+1) ! interlayer pressure (Pa)
19real,intent(in) :: temp(ngrid,nlayer) ! temperature (K)
20real,intent(in) :: pdt(ngrid,nlayer) ! tendecies on temperature from previous processes (K/s)
21real,intent(in) :: dtphys ! physics time step (s)
22real,intent(out) :: dtradsponge(ngrid,nlayer) ! tendencies on temperature from sponge
23
24! local variables:
25logical,save :: firstcall=.true.
26!$OMP THREADPRIVATE(firstcall)
27integer,save :: iflag_sponge   !0 --> for no sponge
28                               !1 --> for sponge over 4 topmost layers
29                               !2 --> for sponge from top to ~1% of top layer pressure
30                               !3 --> for sponge over last nb_sponge_layers
31real,save :: tau_sponge !inverse of charactericstic relaxation time scale at the topmost layer (Hz)
32real,save :: nb_sponge_layers ! number of layers over which the sponge extends
33!$OMP THREADPRIVATE(iflag_sponge,tau_sponge,nb_sponge_layers)
34integer,save :: nlayer0 ! layer down to which sponge is applied
35real,allocatable,save :: rdamp(:) ! quenching coefficient
36real,allocatable,save :: lambda(:) ! inverse or quenching time scale (Hz)
37real,allocatable,save :: mass(:) ! g*mass (per m2) of atmospheric layer
38real,save :: spongemass ! (pseudo-) mass of atmosphere over the entire sponge layer
39
40real :: temp_cur(ngrid,nlayer) ! temperature (K)
41real :: mean_temp(ngrid) ! mean temperature towards which to relax
42
43integer :: i,k
44
45if (firstcall) then
46  ! load sponge parameters
47  iflag_sponge=0 ! default: no sponge
48  call getin_p("iflag_sponge",iflag_sponge)
49  tau_sponge=1.E-4 ! default value
50  call getin_p("tau_sponge",tau_sponge)
51  if (iflag_sponge==3) then
52    call getin_p("nb_sponge_layers",nb_sponge_layers)
53  endif
54
55!$OMP MASTER
56  allocate(rdamp(nlayer))
57  allocate(lambda(nlayer))
58  allocate(mass(nlayer))
59 
60  if (iflag_sponge == 1) then
61! sponge quenching over the topmost 4 atmospheric layers
62    nb_sponge_layers=4
63    nlayer0=nlayer-3
64    lambda(:)=0.
65    lambda(nlayer)=tau_sponge
66    lambda(nlayer-1)=tau_sponge/2.
67    lambda(nlayer-2)=tau_sponge/4.
68    lambda(nlayer-3)=tau_sponge/8.
69  else if (iflag_sponge == 2) then
70! sponge quenching over topmost layers down to pressures which are
71! higher than 100 times the topmost layer pressure
72    do k=nlayer,1,-1
73      lambda(k)=tau_sponge*max(pplay(1,nlayer)/pplay(1,k)-0.01,0.)
74      if (lambda(k).ne.0.) nlayer0=k
75    enddo
76  else if (iflag_sponge == 3) then
77    nlayer0=nlayer-nb_sponge_layers+1
78    lambda(:)=0
79    do k=nlayer,nlayer0,-1
80      lambda(k)=tau_sponge/(2.**(nlayer-k))
81    enddo
82  else
83    write(*,*) "radsponge: bad value for iflag_sponge:",iflag_sponge
84    stop
85  endif
86
87  rdamp(:)=1.-exp(-lambda(:)*dtphys)
88 
89  ! compute (pseudo-) atmospheric mass of each layer
90  ! (here we assume that they won't vay with time,
91  ! which is always the case near model top)
92  do k=1,nlayer
93    mass(k)=pplev(1,k)-pplev(1,k+1)
94  enddo
95  spongemass=0
96  do k=nlayer0,nlayer
97    spongemass=spongemass+mass(k)
98  enddo
99 
100  if (is_master) then
101    write(*,*) "radsponge: nlayer0=",nlayer0," spongemass=",spongemass
102    write(*,*) " layer    lambda       rdamp        mass"
103    do k=nlayer0,nlayer
104      write(*,'(i3,3x,3(1pe14.7,1x))') k,lambda(k),rdamp(k),mass(k)
105    enddo
106  endif
107!$OMP END MASTER
108!$OMP BARRIER
109 
110  firstcall=.false.
111endif ! of if (firstcall)
112
113
114! 1. compute current temperature and average teperature toward which to relax
115
116temp_cur(:,:)=temp(:,:)+dtphys*pdt(:,:)
117
118! compute mean temperature as a mass-weighed average
119mean_temp(1:ngrid)=0
120do k=nlayer0,nlayer
121  mean_temp(1:ngrid)=mean_temp(1:ngrid)+temp_cur(1:ngrid,k)*mass(k)
122enddo
123mean_temp(1:ngrid)=mean_temp(1:ngrid)/spongemass
124
125! 2. Temperature tendency due to sponge
126dtradsponge(:,:)=0
127do k=nlayer0,nlayer
128  ! A(t+dt)-A(t)=-(A(t)-Am)*(1-exp(-lambda*dt))
129  dtradsponge(1:ngrid,k)=-(temp_cur(1:ngrid,k)-mean_temp(1:ngrid))*rdamp(k)
130enddo
131! Ehouarn debug:
132!write(*,*)"radsponge: mean_temp(:)=",mean_temp(:)
133!write(*,*)" layer    temp     temp_cur     dtradsponge"
134!do k=nlayer0,nlayer
135!  write(*,'(i3,3x,3(1pe14.7,1x))') k,temp(1,k),temp_cur(1,k),dtradsponge(1,k)
136!enddo
137
138! return dtradsponge as a tendency in  K/s
139dtradsponge(1:ngrid,nlayer0:nlayer)=dtradsponge(1:ngrid,nlayer0:nlayer)/dtphys
140
141end subroutine radsponge
Note: See TracBrowser for help on using the repository browser.