FV3 Bundle
dcmip_initial_conditions_test_4_v3.f90
Go to the documentation of this file.
2 
3  !=======================================================================
4  !
5  ! Functions for setting up idealized and perturbed initial conditions
6  ! for the Jablonowski-Williamson baroclinic instability with invariant
7  ! tracers (Jablonowski and Williamson, QJ 2006).
8  !
9  ! Options:
10  ! moist 1 for the moist baroclinic instability
11  ! 0 for the dry baroclinic instability test
12  ! X scale factor of the Earth
13  !
14  ! Given a point specified by:
15  ! lon longitude (radians)
16  ! lat latitude (radians)
17  ! p/z pressure (Pa)/height (m)
18  ! zcoords 1 if z is specified, 0 if p is specified
19  !
20  ! the functions will return:
21  ! p pressure if z is specified and zcoords = 1 (Pa)
22  ! u zonal wind (m s^-1)
23  ! v meridional wind (m s^-1)
24  ! w vertical velocity (m s^-1)
25  ! t temperature (K)
26  ! phis surface geopotential (m^2 s^-2)
27  ! ps surface pressure (Pa)
28  ! rho density (kg m^-3)
29  ! q specific humidity (kg/kg)
30  ! q1 potential temperature tracer (K)
31  ! q2 absolute value of Ertel's potential vorticity (EPV) tracer,
32  ! in PVU units for X=1: PVU = 10^-6 K m^2 kg^-1 s^-1,
33  !
34  ! Authors: Paul Ullrich, Christiane Jablonowski, James Kent
35  ! (University of Michigan, dcmip@ucar.edu)
36  ! version 3
37  ! corrected on July/20/2012
38  !
39  ! Change Log:
40  ! version 2 (v2), June/8/2012
41  ! (1) correction of a typo (removal of 1/a) in the dthetadphi equation
42  ! (2) initialization of q2 with the absolute value of EPV
43  ! version 3 (v3), July/20/2012
44  ! - newly added if construct prevents division by zero in relative vorticity (zeta)
45  ! calculation in case the perturbation center point, its antipode, or the north or
46  ! south poles are part of the computational grid
47  !=======================================================================
48 
49  IMPLICIT NONE
50 
51 !=======================================================================
52 ! use physical constants
53 !=======================================================================
54 
55  REAL(8), PARAMETER :: &
56  a = 6371220.0d0, & ! Reference Earth's Radius (m)
57  rd = 287.0d0, & ! Ideal gas const dry air (J kg^-1 K^1)
58  g = 9.80616d0, & ! Gravity (m s^2)
59  cp = 1004.5d0, & ! Specific heat capacity (J kg^-1 K^1)
60  pi = 4.d0*atan(1.d0), & ! pi
61  kappa = 2.d0/7.d0, & ! Ratio of Rd to cp
62  omega = 7.29212d-5 ! Reference rotation rate of the Earth (s^-1)
63 
64 !=======================================================================
65 ! additional constants
66 !=======================================================================
67 
68  REAL(8), PARAMETER :: &
69  p0 = 100000.0d0, & ! surface pressure (Pa)
70  deg2rad = pi/180.d0 ! Conversion factor of degrees to radians
71 
72 !-----------------------------------------------------------------------
73 ! steady-state and baroclinic wave tuning parameter
74 !-----------------------------------------------------------------------
75  REAL(8), PARAMETER :: &
76  eta_tropo = 0.2d0 , & ! tropopause level
77  u0 = 35.d0 , & ! 35 m/s
78  t0 = 288.d0 , & ! horizontal mean T at surface
79  eta0 = 0.252d0 , & ! center of jets (hybrid)
80  !
81  radius = 10.d0, & ! reciprocal radius of the perturbation without 'a'
82  perturbation_amplitude = 1.d0, & ! amplitude of u perturbation 1 m/s
83  perturbation_longitude = 20.d0, & ! longitudinal position, 20E
84  perturbation_latitude = 40.d0, & ! latitudinal position, 40N
85  eta_sfc = 1.d0, & ! hybrid value at surface
86  delta_t = 480000.d0, & ! in K, for T mean calculation
87  gamma = 0.005d0, & ! lapse rate
88  !
90  a_omega = a*omega, &
91  exponent = rd*gamma/g, &
92  q0 = 0.021d0, & ! maximum specific humidity in kg/kg
93  lat_hw = 2.d0*pi/9.d0, & ! halfwidth for q: 40 degrees in radians
94  p_hw = 34000.d0 ! halfwidth for q: 34000 Pa
95 
96 CONTAINS
97 
98  SUBROUTINE test4_baroclinic_wave (moist,X,lon,lat,p,z,zcoords,u,v,w,t,phis,ps,rho,q,q1,q2)
99 
100  IMPLICIT NONE
101 
102 !-----------------------------------------------------------------------
103 ! input/output params parameters at given location
104 !-----------------------------------------------------------------------
105  INTEGER, INTENT(IN) :: moist ! Moist (1) or non-moist (0) test case
106 
107  REAL(8), INTENT(IN) :: &
108  lon, & ! Longitude (radians)
109  lat, & ! Latitude (radians)
110  z, & ! Height (m)
111  X ! Scale factor, not used in this version since unscaled EPV is selected
112 
113  REAL(8), INTENT(INOUT) :: p ! Pressure (Pa)
114 
115  INTEGER, INTENT(IN) :: zcoords ! 0 or 1 see below
116 
117  REAL(8), INTENT(OUT) :: &
118  u, & ! Zonal wind (m s^-1)
119  v, & ! Meridional wind (m s^-1)
120  w, & ! Vertical Velocity (m s^-1)
121  t, & ! Temperature (K)
122  phis, & ! Surface Geopotential (m^2 s^-2)
123  ps, & ! Surface Pressure (Pa)
124  rho, & ! density (kg m^-3)
125  q, & ! Specific Humidity (kg/kg)
126  q1, & ! Tracer q1 - Potential temperature (kg/kg)
127  q2 ! Tracer q2 - Ertel's potential vorticity (kg/kg)
128 
129  REAL(8) :: eta
130 
131 !-----------------------------------------------------------------------
132 ! initialize PS (surface pressure)
133 !-----------------------------------------------------------------------
134  ps = p0 ! constant
135 
136 !-----------------------------------------------------------------------
137 ! calculate eta
138 !-----------------------------------------------------------------------
139  if (zcoords .eq. 0) then
140  eta = p / ps
141  else
142  eta = eta_from_z(lon,lat,z)
143  p = eta * ps
144  end if
145 
146 !-----------------------------------------------------------------------
147 ! initialize wind field with perturbation
148 !-----------------------------------------------------------------------
149  u = u_wind(lon,lat,eta,.true.)
150  v = v_wind(lon,lat,eta,.true.)
151  w = 0.d0
152 
153 !-----------------------------------------------------------------------
154 ! initialize temperature field (virtual temperature for moist conditions)
155 !-----------------------------------------------------------------------
156  t = temperature(lon,lat,eta)
157 
158 !-----------------------------------------------------------------------
159 ! initialize surface geopotential
160 !-----------------------------------------------------------------------
161  phis = surface_geopotential(lon,lat)
162 
163 !-----------------------------------------------------------------------
164 ! initialize density from ideal gas law, t is the virtual temperature in the moist case
165 !-----------------------------------------------------------------------
166  rho = p/(t*rd)
167 
168 !-----------------------------------------------------------------------
169 ! tracer q (specific humidity), moist or dry, and dry temperature
170 !-----------------------------------------------------------------------
171  if (moist == 1) then
172  q = q0 * exp(-(lat/lat_hw)**4) * exp(-((eta-1.d0)*p0/p_hw)**2) ! moist
173  t = t/(1.d0+0.608d0*q) ! convert virtual temperature to temperature
174  else
175  q = 0.d0 ! dry
176  endif
177 
178 !-----------------------------------------------------------------------
179 ! tracer q1, potential temperature
180 !-----------------------------------------------------------------------
181  q1 = theta(lon,lat,eta)
182 
183 !-----------------------------------------------------------------------
184 ! tracer q2, absolute value of EPV
185 !-----------------------------------------------------------------------
186  q2 = abs(epv(lon,lat,eta)) * x ! the value of |EPV| scales with X
187 !
188 ! The absolute value of Ertel's potential vorticity
189 ! is selected to avoid the negative EPV values in the
190 ! Southern Hemisphere. Such negative values might interfere with positive-definite
191 ! constraints in the tracer advection algorithm.
192 
193  end subroutine test4_baroclinic_wave
194 
195 
196 !********************************************************************
197 ! Temperature = mean + perturbation temperature
198 !********************************************************************
199  REAL(8) FUNCTION temperature(lon,lat,eta)
200  IMPLICIT NONE
201  REAL(8), INTENT(IN) :: lon, lat, eta
202 
203  temperature = t_mean(eta) + t_deviation(lon,lat,eta)
204 
205  END FUNCTION temperature
206 
207 
208 
209 !***********************************************************************************************
210 ! Horizontally averaged temperature
211 !***********************************************************************************************
212  REAL(8) FUNCTION t_mean(eta)
213  IMPLICIT NONE
214  REAL(8), INTENT(IN) :: eta
215 
216  if (eta .ge. eta_tropo) then
217  t_mean = t0*eta**exponent ! mean temperature at each level
218  else
219  t_mean = t0*eta**exponent + delta_t*(eta_tropo-eta)**5
220  endif
221  END FUNCTION t_mean
222 
223 
224 
225 !***********************************************************************************************
226 ! Temperature deviation from the horizontal mean
227 !***********************************************************************************************
228  REAL(8) FUNCTION t_deviation(lon,lat,eta)
229  IMPLICIT NONE
230  REAL(8), INTENT(IN) :: eta, lon, lat
231  REAL(8) :: factor, phi_vertical
232 
233  factor = eta*pi*u0/rd
234  phi_vertical = (eta - eta0) * 0.5d0*pi
235 
236  t_deviation = factor * 1.5d0 * sin(phi_vertical) * (cos(phi_vertical))**0.5d0 * &
237  ((-2.d0*(sin(lat))**6 * ((cos(lat))**2 + 1.d0/3.d0) + 10.d0/63.d0)* &
238  u0 * (cos(phi_vertical))**1.5d0 + &
239  (8.d0/5.d0*(cos(lat))**3 * ((sin(lat))**2 + 2.d0/3.d0) - pi/4.d0)*a_omega*0.5d0 )
240  END FUNCTION t_deviation
241 
242 
243 
244 !**************************************************************************
245 ! Surface geopotential
246 !**************************************************************************
247  REAL(8) FUNCTION surface_geopotential(lon,lat)
248  IMPLICIT NONE
249  REAL(8), INTENT(IN) :: lon, lat
250  REAL(8) :: cos_tmp
251 
252  cos_tmp = u0 * (cos((eta_sfc-eta0)*pi*0.5d0))**1.5d0
253 
254  surface_geopotential = ((-2.d0*(sin(lat))**6 * ((cos(lat))**2 + 1.d0/3.d0) + 10.d0/63.d0)*cos_tmp &
255  + (8.d0/5.d0*(cos(lat))**3 * ((sin(lat))**2 + 2.d0/3.d0) - pi/4.d0)*a_omega)*cos_tmp
256 
257  END FUNCTION surface_geopotential
258 
259 !**************************************************************************
260 ! 3D geopotential
261 !**************************************************************************
262  REAL(8) FUNCTION geopotential(lon,lat,eta)
263  IMPLICIT NONE
264  REAL(8), INTENT(IN) :: lon, lat, eta
265  REAL(8) :: cos_tmp
266 
267  cos_tmp = u0 * (cos((eta-eta0)*pi*0.5d0))**1.5d0
268 
269  geopotential = ((-2.d0*(sin(lat))**6 * ((cos(lat))**2 + 1.d0/3.d0) + 10.d0/63.d0)*cos_tmp &
270  + (8.d0/5.d0*(cos(lat))**3 * ((sin(lat))**2 + 2.d0/3.d0) - pi/4.d0)*a_omega)*cos_tmp
271 
273 
274  END FUNCTION geopotential
275 
276 !**************************************************************************
277 ! mean geopotential
278 !**************************************************************************
279  REAL(8) FUNCTION horiz_mean_geopotential(eta)
280  IMPLICIT NONE
281  REAL(8), INTENT(IN) :: eta
282  REAL(8) :: delta_phi
283 
284  horiz_mean_geopotential = t0 * g / gamma * (1.0d0 - eta**(rd * gamma / g))
285 
286  if (eta < eta_tropo) then
287  delta_phi = rd * delta_t * ( &
288  (log(eta/eta_tropo) + 137.d0/60.d0) * eta_tropo**5 &
289  - 5.d0 * eta_tropo**4 * eta &
290  + 5.d0 * eta_tropo**3 * eta**2 &
291  - 10.d0/3.d0 * eta_tropo**2 * eta**3 &
292  + 5.d0/4.d0 * eta_tropo * eta**4 &
293  - 1.d0/5.d0 * eta**5)
294 
296  end if
297 
298  END FUNCTION horiz_mean_geopotential
299 
300 !********************************************************************
301 ! u wind component
302 !********************************************************************
303  REAL(8) FUNCTION u_wind(lon,lat,eta,lperturb)
304  IMPLICIT NONE
305  REAL(8), INTENT(IN) :: lon,lat,eta
306  LOGICAL, INTENT(IN) :: lperturb ! if .true. perturbation is added
307  REAL(8) :: phi_vertical, sin_tmp, cos_tmp, r, u_perturb
308  REAL(8) :: perturb_lon, perturb_lat
309 
310 
311 !---------------
312 ! unperturbed u wind
313 !---------------
314  phi_vertical = (eta - eta0) *0.5d0*pi
315  u_wind = (cos(phi_vertical))**1.5d0 * 4.d0 * u0 * (sin(lat))**2 * (cos(lat))**2
316 
317 !---------------
318 ! if needed (lperturb == .TRUE.) add a Gaussian hill perturbation
319 !---------------
320  IF (lperturb) THEN
321 
322  ! center of perturbation, convert from degrees to radians
323  perturb_lon = perturbation_longitude*deg2rad
324  perturb_lat = perturbation_latitude*deg2rad
325 
326  sin_tmp = sin(perturb_lat)*sin(lat)
327  cos_tmp = cos(perturb_lat)*cos(lat)
328 
329  r = acos( sin_tmp + cos_tmp*cos(lon-perturb_lon) ) ! great circle distance without radius 'a'
330  u_perturb = perturbation_amplitude*exp(- (r*radius)**2 ) ! perturbation_amplitude determines strength
331  u_wind = u_perturb + u_wind ! perturbation + unperturbed u wind
332  ENDIF
333 
334  END FUNCTION u_wind
335 
336 
337 
338 
339 !********************************************************************
340 ! v wind component
341 !********************************************************************
342  REAL(8) FUNCTION v_wind(lon,lat,eta,lperturb)
343  IMPLICIT NONE
344  REAL(8), INTENT(IN) :: lon,lat,eta
345  LOGICAL, INTENT(IN) :: lperturb
346 
347  v_wind = 0.0d0
348 
349  END FUNCTION v_wind
350 
351 !********************************************************************
352 ! Calculate eta from height
353 !********************************************************************
354  REAL(8) FUNCTION eta_from_z(lon,lat,z)
355  IMPLICIT NONE
356  REAL(8), INTENT(IN) :: lon, lat, z
357  REAL(8) :: eta_new, f, df
358  INTEGER :: iter
359 
360  REAL(8), PARAMETER :: &
361  initial_eta = 1.0d-7, &
362  convergence = 1.0d-13
363 
364  eta_from_z = initial_eta
365 
366  do iter=0, 25
367  f = - g * z + geopotential(lon,lat,eta_from_z)
368  df = - rd / eta_from_z * temperature(lon,lat,eta_from_z)
369 
370  eta_new = eta_from_z - f / df
371 
372  if (abs(eta_from_z - eta_new) < convergence) then
373  exit
374  end if
375 
376  eta_from_z = eta_new
377  enddo
378 
379  END FUNCTION eta_from_z
380 
381 !********************************************************************
382 ! Tracers
383 !********************************************************************
384 !-----------------------------------------------------------------------
385 ! Potential temperature
386 !-----------------------------------------------------------------------
387  REAL(8) FUNCTION theta(lon,lat,eta)
388  IMPLICIT NONE
389  REAL(8), INTENT(IN) :: eta, lon, lat
390  REAL(8) :: eta_nu, cos_tmp, y
391 
392  eta_nu = (eta-eta0)*pi*0.5d0
393  cos_tmp = u0 * (cos(eta_nu))**1.5d0
394 
395  y = (-2.d0*(sin(lat))**6 * ((cos(lat))**2 + 1.d0/3.d0) + 10.d0/63.d0)*2.d0*cos_tmp &
396  + (8.d0/5.d0*(cos(lat))**3 * ((sin(lat))**2 + 2.d0/3.d0) - pi/4.d0)*a_omega
397 
398  theta = t_mean(eta) * eta**(-kappa) + 3.d0/4.d0*pi*u0/rd * eta**(1.d0-kappa) &
399  * sin(eta_nu) * sqrt(cos(eta_nu)) * y
400 
401  END FUNCTION theta
402 
403 !-----------------------------------------------------------------------
404 ! Ertel's potential vorticity
405 !-----------------------------------------------------------------------
406  REAL(8) FUNCTION epv(lon,lat,eta)
407  IMPLICIT NONE
408  REAL(8), INTENT(IN) :: eta, lon, lat
409  REAL(8) :: perturb_lon, perturb_lat
410  REAL(8) :: eta_nu, cos_tmp, y, r, zeta, k, dk, f
411  REAL(8) :: dudeta, dmeanthetadeta, dthetadeta
412  REAL(8) :: dthetadphi1, dthetadphi2, dthetadphi
413  REAL(8) :: epsilon
414 
415  ! center of perturbation, convert from degrees to radians
416  perturb_lon = perturbation_longitude*deg2rad
417  perturb_lat = perturbation_latitude*deg2rad
418 
419  ! initialize epsilon, used to judge the distance of a point to prescribed points
420  epsilon = 1.d-6
421 
422  eta_nu = (eta-eta0)*pi*0.5d0
423  cos_tmp = u0 * (cos(eta_nu))**1.5d0
424 
425  y = (-2.d0*(sin(lat))**6 * ((cos(lat))**2 + 1.d0/3.d0) + 10.d0/63.d0)*2.d0*cos_tmp &
426  + (8.d0/5.d0*(cos(lat))**3 * ((sin(lat))**2 + 2.d0/3.d0) - pi/4.d0)*a_omega
427 
428  ! great circle distance without radius 'a'
429  k = sin(perturb_lat)*sin(lat) + cos(perturb_lat)*cos(lat)*cos(lon-perturb_lon)
430  dk = sin(perturb_lat)*cos(lat) - cos(perturb_lat)*sin(lat)*cos(lon-perturb_lon)
431  r = acos(k)
432 
433  ! relative vorticity
434 
435  ! version v3 (7/20/2012):
436  ! if construct prevents DIVISION BY ZERO in zeta calculation
437 
438  if (abs(lat-perturb_lat).le.epsilon .and. abs(lon-perturb_lon).le.epsilon) then ! grid point is at center position
439  zeta = -4.d0/a*cos_tmp*sin(lat)*cos(lat)*(2.d0-5.d0*(sin(lat))**2) + perturbation_amplitude/a*tan(lat)
440 
441  else if ( (abs(lat+perturb_lat).le.epsilon .and. abs(lon-(perturb_lon+pi)).le.epsilon) & ! antipode
442  .or. abs(lat-pi*0.5d0).le.epsilon & ! north pole
443  .or. abs(lat+pi*0.5d0).le.epsilon) then ! south pole
444  zeta = -4.d0/a*cos_tmp*sin(lat)*cos(lat)*(2.d0-5.d0*(sin(lat))**2)
445 
446  else ! all other positions
447  zeta = -4.d0/a*cos_tmp*sin(lat)*cos(lat)*(2.d0-5.d0*(sin(lat))**2) &
448  + perturbation_amplitude/a*exp(- (r*radius)**2 ) &
449  * (tan(lat) - 2.d0*radius**2*acos(k)*dk/sqrt(1.d0-k**2))
450  endif
451 
452  ! derivative of u with respect to eta
453  dudeta = -u0*(sin(2.d0*lat))**2*3.d0*pi/4.d0*sqrt(cos(eta_nu))*sin(eta_nu)
454 
455  ! derivative of mean theta with respect to eta
456  dmeanthetadeta = t0*(rd*gamma/g - kappa)*eta**(rd*gamma/g-kappa-1.d0)
457 
458  if (eta < eta_tropo) then
459  dmeanthetadeta = dmeanthetadeta &
460  - delta_t * ( &
461  5.d0*(eta_tropo - eta)**4*eta**(-kappa) &
462  + kappa * (eta_tropo - eta)**5 * eta**(-kappa-1.d0))
463  end if
464 
465  ! derivative of theta with respect to eta
466  dthetadeta = dmeanthetadeta &
467  + 3.d0/4.d0*pi*u0/rd*(1.d0-kappa)*eta**(-kappa)*sin(eta_nu)*sqrt(cos(eta_nu))*y &
468  + 3.d0/8.d0*pi*pi/rd*eta**(1.d0-kappa)*cos_tmp*y &
469  - 3.d0/16.d0*pi*pi*u0/rd*eta**(1.d0-kappa)*(sin(eta_nu))**2*(cos(eta_nu))**(-0.5d0)*y &
470  - 9.d0/8.d0*pi*pi*u0*u0/rd*eta**(1.d0-kappa)*(sin(eta_nu))**2*cos(eta_nu) &
471  * (-2.d0*(sin(lat))**6*((cos(lat))**2+1.d0/3.d0) + 10.d0/63.d0)
472 
473  ! derivative of theta with respect to phi
474  dthetadphi1 = 2.d0*cos_tmp &
475  * (- 12.d0*cos(lat)*(sin(lat))**5*((cos(lat))**2+1.d0/3.d0) &
476  + 4.d0*cos(lat)*(sin(lat))**7)
477 
478  dthetadphi2 = a_omega &
479  * (-24.d0/5.d0*sin(lat)*(cos(lat))**2*((sin(lat))**2+2.d0/3.d0) &
480  + 16.d0/5.d0*(cos(lat))**4*sin(lat))
481 
482 ! corrected on June/6/2012
483  dthetadphi = 3.d0/4.d0*pi*u0/rd*eta**(1.d0-kappa)*sin(eta_nu)*sqrt(cos(eta_nu)) &
484  * (dthetadphi1 + dthetadphi2)
485 
486  ! Coriolis parameter
487  f = 2.d0 * omega * sin(lat)
488 
489  ! EPV, unscaled since real-Earth 'a' and 'Omega' were used, EPV will be scaled in calling routine
490  epv = g/p0*(-dudeta*dthetadphi/a - (zeta+f) * dthetadeta)
491 
492  END FUNCTION epv
493 
real(8) function u_wind(lon, lat, eta, lperturb)
subroutine test4_baroclinic_wave(moist, X, lon, lat, p, z, zcoords, u, v, w, t, phis, ps, rho, q, q1, q2)
real(8) function v_wind(lon, lat, eta, lperturb)
real, parameter, public pi
Ratio of circle circumference to diameter [N/A].
Definition: constants.F90:74