Skip to content

Commit cf1d482

Browse files
authored
Merge pull request #11 from natgeo-wong/main
Merging natgeo-wong changes to KuangLab
2 parents de214be + 3febe93 commit cf1d482

14 files changed

+1582
-121
lines changed

forcing.f90

Lines changed: 95 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,17 @@ subroutine forcing
1111

1212
integer i,j,k,n,nn,m,iz,iday0,iday
1313
real coef, radtend, dayy
14-
real tt(nzm,2),qq(nzm,2),uu(nzm,2),vv(nzm,2),ww(nzm,2),pp
14+
real tt(nzm,2),qq(nzm,2),uu(nzm,2),vv(nzm,2),ww(nzm,2),tp(nzm,2),pp(nzm,2)
15+
real tpm(nzm)
1516
real ratio1, ratio2, ratio_t1, ratio_t2
1617
logical zgrid, pgrid
1718

1819
! linear response perturbation (Song Qiyu, 2022)
1920
real, save :: delt_t, delt_q ! Layer by layer perturbation
2021

22+
! ktrop index for tropopause
23+
integer :: ktrop
24+
2125
call t_startf ('forcing')
2226

2327

@@ -63,11 +67,12 @@ subroutine forcing
6367
coef = (z(iz)-zsnd(i-1,m))/(zsnd(i,m)-zsnd(i-1,m))
6468
tt(iz,n)=tsnd(i-1,m)+(tsnd(i,m)-tsnd(i-1,m))*coef
6569
if(pgrid) then
66-
pp=psnd(i-1,m)+(psnd(i,m)-psnd(i-1,m))*coef
67-
tt(iz,n)=tt(iz,n)/((1000./pp)**(rgas/cp))
70+
pp(iz,n)=psnd(i-1,m)+(psnd(i,m)-psnd(i-1,m))*coef
71+
tt(iz,n)=tt(iz,n)/((1000./pp(iz,n))**(rgas/cp))
6872
else
6973
tt(iz,n)=tt(iz,n)/prespotb(iz)
7074
endif
75+
tp(iz,n)=tsnd(i-1,m)+(tsnd(i,m)-tsnd(i-1,m))*coef
7176
qq(iz,n)=qsnd(i-1,m)+(qsnd(i,m)-qsnd(i-1,m))*coef
7277
uu(iz,n)=usnd(i-1,m)+(usnd(i,m)-usnd(i-1,m))*coef
7378
vv(iz,n)=vsnd(i-1,m)+(vsnd(i,m)-vsnd(i-1,m))*coef
@@ -78,11 +83,12 @@ subroutine forcing
7883
do i = 2,nzsnd
7984
if(pres(iz).ge.psnd(i,m)) then
8085
coef = (pres(iz)-psnd(i-1,m))/(psnd(i,m)-psnd(i-1,m))
81-
tt(iz,n)=tsnd(i-1,m)+(tsnd(i,m)-tsnd(i-1,m))*coef
82-
tt(iz,n)=tt(iz,n)/prespotb(iz)
86+
tt(iz,n)=tsnd(i-1,m)+(tsnd(i,m)-tsnd(i-1,m))*coef/prespotb(iz)
87+
tp(iz,n)=tsnd(i-1,m)+(tsnd(i,m)-tsnd(i-1,m))*coef
8388
qq(iz,n)=qsnd(i-1,m)+(qsnd(i,m)-qsnd(i-1,m))*coef
8489
uu(iz,n)=usnd(i-1,m)+(usnd(i,m)-usnd(i-1,m))*coef
8590
vv(iz,n)=vsnd(i-1,m)+(vsnd(i,m)-vsnd(i-1,m))*coef
91+
pp(iz,n)=psnd(i-1,m)+(psnd(i,m)-psnd(i-1,m))*coef
8692
goto 11
8793
endif
8894
end do
@@ -107,11 +113,13 @@ subroutine forcing
107113

108114
do k=1,nzm
109115
tg0(k)=tt(k,1)+(tt(k,2)-tt(k,1))*coef
116+
tp0(k)=tp(k,1)+(tp(k,2)-tp(k,1))*coef
110117
qg0(k)=qq(k,1)+(qq(k,2)-qq(k,1))*coef
111118
qg0(k)=qg0(k)*1.e-3
112119
! Note that ug0 and vg0 maybe reset if dolargescale is true)
113120
ug0(k)=uu(k,1)+(uu(k,2)-uu(k,1))*coef - ug
114121
vg0(k)=vv(k,1)+(vv(k,2)-vv(k,1))*coef - vg
122+
pg0(k)=pp(k,1)+(pp(k,2)-pp(k,1))*coef - vg
115123
end do
116124

117125
! ---------------------------------------------------------------
@@ -226,6 +234,88 @@ subroutine forcing
226234
end do
227235
end if
228236

237+
!-------------------------------------------------------------------------------
238+
! Kuang Lab Addition
239+
! Save reference copy of large-scale vertical velocity before modification
240+
! by WTG or scaling techniques, similar to Blossey's version of SAM
241+
wsub_ref(1:nzm) = wsub(1:nzm)
242+
243+
if(dodgw) then
244+
245+
if(wtgscale_time.gt.0) then
246+
twtgmax = (nstop * dt - timelargescale) * wtgscale_time
247+
twtg = time-timelargescale
248+
if(twtg.gt.twtgmax) then
249+
am_wtg_time = am_wtg
250+
else
251+
am_wtg_time = am_wtg * twtgmax / twtg
252+
endif
253+
else
254+
am_wtg_time = am_wtg
255+
endif
256+
257+
if (dowtg_blossey_etal_JAMES2009) call wtg_james2009(nzm, &
258+
100.*pres, tg0, qg0, tabs0, qv0, qn0+qp0, &
259+
fcor, lambda_wtg, am_wtg_time, am_wtg_exp, o_wtg, ktrop)
260+
if (dowtg_decompdgw) then
261+
call wtg_james2009(nzm, &
262+
100.*pres, tg0, qg0, tabs0, qv0, qn0+qp0, &
263+
fcor, lambda_wtg, am_wtg_time, am_wtg_exp, owtgr, ktrop)
264+
call wtg_decompdgw(masterproc, &
265+
nzm, nz, z, 100.*pg0, tg0, qg0, tabs0, qv0, qn0+qp0, &
266+
lambda_wtg, am_wtg_time, wtgscale_vertmodenum, wtgscale_vertmodescl, &
267+
o_wtg, wwtgc, ktrop)
268+
end if
269+
270+
! convert from omega in Pa/s to wsub in m/s
271+
w_wtg(1:nzm) = -o_wtg(1:nzm)/rho(1:nzm)/ggr
272+
if (dowtg_decompdgw) wwtgr(1:nzm) = -owtgr(1:nzm)/rho(1:nzm)/ggr
273+
274+
end if
275+
276+
if (dotgr) then
277+
278+
if(wtgscale_time.gt.0) then
279+
twtgmax = (nstop * dt - timelargescale) * wtgscale_time
280+
twtg = time-timelargescale
281+
if(twtg.gt.twtgmax) then
282+
tau_wtg_time = tau_wtg
283+
else
284+
tau_wtg_time = tau_wtg * twtg / twtgmax
285+
endif
286+
else
287+
tau_wtg_time = tau_wtg
288+
endif
289+
290+
do k = 1,nzm
291+
tpm(k) = tabs0(k) * prespot(k)
292+
end do
293+
294+
if (dowtg_raymondzeng_QJRMS2005) call wtg_qjrms2005(masterproc, nzm, nz, z, &
295+
tp0, tpm, tabs0, tau_wtg_time, dowtgLBL, boundstatic, &
296+
dthetadz_min, w_wtg, wwtgr)
297+
if (dowtg_hermanraymond_JAMES2014) call wtg_james2014(masterproc, nzm, nz, z, &
298+
tp0, tpm, tabs0, tau_wtg_time, dowtgLBL, boundstatic, &
299+
dthetadz_min, wtgscale_vertmodepwr, w_wtg, wwtgr, wwtgc)
300+
if (dowtg_decomptgr) call wtg_decomptgr(masterproc, nzm, nz, z, &
301+
tp0, tpm, tabs0, tau_wtg_time, &
302+
wtgscale_vertmodenum, wtgscale_vertmodescl, &
303+
dowtgLBL, boundstatic, dthetadz_min, w_wtg, wwtgr, wwtgc)
304+
305+
! convert from omega in Pa/s to wsub in m/s
306+
o_wtg(1:nzm) = -w_wtg(1:nzm)*rho(1:nzm)*ggr
307+
owtgr(1:nzm) = -wwtgr(1:nzm)*rho(1:nzm)*ggr
308+
309+
end if
310+
311+
if (dotgr.OR.dodgw) then
312+
313+
! add to reference large-scale vertical velocity.
314+
wsub(1:nzm) = wsub(1:nzm) + w_wtg(1:nzm)
315+
dosubsidence = .true.
316+
317+
end if
318+
229319
if(dosubsidence) call subsidence()
230320

231321
end if

hbuf_conditionals_init.f90

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,50 @@
11
subroutine hbuf_conditionals_init(count,trcount)
22
use vars, only: ncondavg, condavgname, condavglongname
33
use rad, only: do_output_clearsky_heating_profiles
4+
use params, only: dodgw, dotgr, dowtg_decomp, dowtg_decompdgw, dowtg_decomptgr, &
5+
dowtg_raymondzeng_QJRMS2005, dowtg_hermanraymond_JAMES2014
46
implicit none
57

68
! Initialize the list of UW statistics variables written in statistics.f90
79
integer count,trcount, n
810

11+
call add_to_namelist(count,trcount,'TBIAS', &
12+
'Absolute temperature bias (model-OBS)','K',0)
13+
call add_to_namelist(count,trcount,'QBIAS', &
14+
'Water vapor mass mixing ratio bias (model-OBS)','g/kg',0)
15+
916
if(do_output_clearsky_heating_profiles) then
1017
call add_to_namelist(count,trcount,'RADQRCLW', &
1118
'Clearsky longwave heating rate','K/d',0)
1219
call add_to_namelist(count,trcount,'RADQRCSW', &
1320
'Clearsky shortwave heating rate','K/d',0)
1421
end if
1522

23+
if(dodgw.OR.dotgr) then
24+
call add_to_namelist(count,trcount,'WWTG', &
25+
'Large-scale W induced by weak temperature gradient approx','m/s',0)
26+
call add_to_namelist(count,trcount,'OWTG', &
27+
'Large-scale Omega induced by weak temperature gradient approx','Pa/s',0)
28+
call add_to_namelist(count,trcount,'WOBSREF', &
29+
'Reference Large-scale W Before Modifications by WTG/Scaling','m/s',0)
30+
end if
31+
32+
if(dowtg_raymondzeng_QJRMS2005) then
33+
call add_to_namelist(count,trcount,'WWTGRAW', &
34+
'Raw (Non-Adjusted) Component of the WTG Vertical Velocity','m/s',0)
35+
call add_to_namelist(count,trcount,'OWTGRAW', &
36+
'Raw (Non-Adjusted) Component of the WTG Pressure Velocity','Pa/s',0)
37+
end if
38+
39+
if(dowtg_hermanraymond_JAMES2014.OR.dowtg_decomp) then
40+
call add_to_namelist(count,trcount,'WTGCOEF', &
41+
'Coefficients of Vertical Modes for Decomposed WTG Velocities',' ',0)
42+
call add_to_namelist(count,trcount,'WWTGRAW', &
43+
'Raw (Non-Adjusted) Component of the WTG Vertical Velocity','m/s',0)
44+
call add_to_namelist(count,trcount,'OWTGRAW', &
45+
'Raw (Non-Adjusted) Component of the WTG Pressure Velocity','Pa/s',0)
46+
end if
47+
1648
!bloss: setup to add an arbitrary number of conditional statistics
1749
do n = 1,ncondavg
1850

main.f90

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ program crm
99
use tracers
1010
use movies, only: init_movies
1111
use params, only: dompiensemble
12+
use simple_ocean, only: set_sst
1213
implicit none
1314

1415
integer k, icyc, nn, nstatsteps
@@ -60,6 +61,7 @@ program crm
6061
call micro_init() !initialize microphysics
6162
nstep = 0
6263
day0 = day
64+
if((.not.SLM.and..not.dosfcforcing).AND.nrestart_resetsst) call set_sst()
6365
else
6466
print *,'Error: confused by value of NRESTART'
6567
call task_abort()

params.f90

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ module params
134134
real:: bubble_dtemp = 0.
135135
real:: bubble_dq = 0.
136136

137-
!!!!! The following are added by Kuang Lab at Harvard !!!!!
137+
!=====================================================
138+
! Kuang-Lab Additions Begin Here
138139

139140
! Options
140141
logical:: dompiensemble = .false. ! Subdomains defined in domains.f90 are run separately
@@ -147,12 +148,66 @@ module params
147148
real:: qperturbA = 1.
148149

149150
! Radiative tendencies as per Pauluis & Garner [2006]
151+
! Added by Nathanael Wong on 2023/07/05
150152
logical :: doradtendency = .false.
151153
real :: troptend = 1.5 ! Convective tendency in Pauluis & Garner [2006]
152154

153155
! Option to fix wind speed used in calculation of bulk surface fluxes
154156
! Taken from Peter Blossey's version of SAM
157+
! Added by Nathanael Wong on 2023/07/05
155158
logical :: dobulksfcflx = .false.
156159
real :: bulksfcflx_u = 0.
157160

161+
! Damped Gravity Wave and Temperature Gradient Relaxation Implementations
162+
! Added by Nathanael Wong on 2023/07/05
163+
logical :: dodgw = .false.
164+
logical :: dotgr = .false.
165+
logical :: dowtg_decomp = .false.
166+
real :: wtgscale_time = 0. ! period over which theta relaxation timescale scales from infinity to ttheta_wtg. Express as fraction of time over which WTG large-scale forcing is implemented. So if WTG/Large-scale is turned on for 100 days, twtg_scale = 1/4 means that the scaling up to WTG occurs over 25 days.
167+
168+
logical :: dowtg_blossey_etal_JAMES2009 = .false.
169+
logical :: dowtg_raymondzeng_QJRMS2005 = .false.
170+
logical :: dowtg_hermanraymond_JAMES2014 = .false.
171+
logical :: dowtg_decompdgw = .false.
172+
logical :: dowtg_decomptgr = .false.
173+
174+
real :: am_wtg = 1. ! momentum damping rate in 1/d -- note must be non-zero.
175+
real :: am_wtg_exp = 0. ! exponent of p/p0 in momentum damping rate.
176+
real :: lambda_wtg = 650.e3 ! quarter wavelength in m. default = 650.e3 (=650 km).
177+
178+
real :: tau_wtg = 1. ! Relaxation timescale (in hours) for WTG Approximation of Raymond and Zeng [2005]
179+
logical :: dowtgLBL = .false.
180+
logical :: boundstatic = .true. ! Restrict the static stability lower bound to prevent unrealistically large values of w_wtg
181+
real :: dthetadz_min = 1.e-3 ! if boundstatic = .true., what is the minimum bound? Default from Raymond & Zeng [2005] is 1.e-3 K/km
182+
real :: wtgscale_vertmodepwr = 1. ! Spectral decomposition power, default is 1 as per Herman and Raymond [2014]
183+
184+
integer :: wtgscale_vertmodenum = 2! number of vertical modes
185+
real, dimension(2) :: wtgscale_vertmodescl = (/1., 1./) ! strength scaling for vertical modes (number of items = wtgscale_vertmodenum)
186+
187+
! Specify a "island" within which SST is allowed to vary
188+
! If dosstisland = .false. and dodynamicocean = .true. the entire domain SST varies
189+
logical :: dosstislands = .false. ! specify an island within which SST is allowed to vary
190+
real :: sstislands_oceanmld = 0. ! "ocean" slab depth, if 0, ocean SST is constant
191+
real :: sstislands_landmld = 0. ! "island" slab depth, set to depth_slab_ocean if 0
192+
193+
! Specify round islands using formula. If readlsm = true, then lsm file will override this
194+
real :: sstislands_radius = 0. ! "island" radii in meters
195+
integer :: sstislands_nrow = 1. ! number of island rows
196+
integer :: sstislands_ncol = 1. ! number of island columns
197+
real :: sstislands_sep = 0. ! spacing between island centers, should be at least 2*sstisland_radius
198+
199+
! Alternatively, specify a file to read the land-sea mask data
200+
! File is a binary file, with variables in this order:
201+
! (1) nx_lsm, which is an integer specifying number of x points
202+
! (2) ny_lsm, which is an integer specifying number of y points
203+
! (3) lsm, which is an array of 1s and 0s, with 0s denoting ocean and 1s denoting land
204+
logical :: readlsm = .false. ! read land-sea mask from file
205+
character(80) :: lsmfile = ""
206+
207+
! If nrestart = 2 and dodynamicocean = false, if nrestart_resetsst = true, set all sst back to tabs_s
208+
logical :: nrestart_resetsst = .false.
209+
210+
! Kuang-Lab Additions End Here
211+
!=====================================================
212+
158213
end module params

0 commit comments

Comments
 (0)