1 | subroutine 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 | |
---|
10 | use ioipsl_getincom_p, only: getin_p |
---|
11 | use mod_phys_lmdz_para, only : is_master |
---|
12 | |
---|
13 | implicit none |
---|
14 | |
---|
15 | integer,intent(in) :: ngrid ! number of atmospheric columns |
---|
16 | integer,intent(in) :: nlayer ! number of atmospheric layers |
---|
17 | real,intent(in) :: pplay(ngrid,nlayer) ! mid-layer pressure (Pa) |
---|
18 | real,intent(in) :: pplev(ngrid,nlayer+1) ! interlayer pressure (Pa) |
---|
19 | real,intent(in) :: temp(ngrid,nlayer) ! temperature (K) |
---|
20 | real,intent(in) :: pdt(ngrid,nlayer) ! tendecies on temperature from previous processes (K/s) |
---|
21 | real,intent(in) :: dtphys ! physics time step (s) |
---|
22 | real,intent(out) :: dtradsponge(ngrid,nlayer) ! tendencies on temperature from sponge |
---|
23 | |
---|
24 | ! local variables: |
---|
25 | logical,save :: firstcall=.true. |
---|
26 | !$OMP THREADPRIVATE(firstcall) |
---|
27 | integer,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 |
---|
31 | real,save :: tau_sponge !inverse of charactericstic relaxation time scale at the topmost layer (Hz) |
---|
32 | real,save :: nb_sponge_layers ! number of layers over which the sponge extends |
---|
33 | !$OMP THREADPRIVATE(iflag_sponge,tau_sponge,nb_sponge_layers) |
---|
34 | integer,save :: nlayer0 ! layer down to which sponge is applied |
---|
35 | real,allocatable,save :: rdamp(:) ! quenching coefficient |
---|
36 | real,allocatable,save :: lambda(:) ! inverse or quenching time scale (Hz) |
---|
37 | real,allocatable,save :: mass(:) ! g*mass (per m2) of atmospheric layer |
---|
38 | real,save :: spongemass ! (pseudo-) mass of atmosphere over the entire sponge layer |
---|
39 | |
---|
40 | real :: temp_cur(ngrid,nlayer) ! temperature (K) |
---|
41 | real :: mean_temp(ngrid) ! mean temperature towards which to relax |
---|
42 | |
---|
43 | integer :: i,k |
---|
44 | |
---|
45 | if (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. |
---|
111 | endif ! of if (firstcall) |
---|
112 | |
---|
113 | |
---|
114 | ! 1. compute current temperature and average teperature toward which to relax |
---|
115 | |
---|
116 | temp_cur(:,:)=temp(:,:)+dtphys*pdt(:,:) |
---|
117 | |
---|
118 | ! compute mean temperature as a mass-weighed average |
---|
119 | mean_temp(1:ngrid)=0 |
---|
120 | do k=nlayer0,nlayer |
---|
121 | mean_temp(1:ngrid)=mean_temp(1:ngrid)+temp_cur(1:ngrid,k)*mass(k) |
---|
122 | enddo |
---|
123 | mean_temp(1:ngrid)=mean_temp(1:ngrid)/spongemass |
---|
124 | |
---|
125 | ! 2. Temperature tendency due to sponge |
---|
126 | dtradsponge(:,:)=0 |
---|
127 | do 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) |
---|
130 | enddo |
---|
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 |
---|
139 | dtradsponge(1:ngrid,nlayer0:nlayer)=dtradsponge(1:ngrid,nlayer0:nlayer)/dtphys |
---|
140 | |
---|
141 | end subroutine radsponge |
---|