source: LMDZ5/branches/Cold_pool_death/libf/phylmd/Cold_pool_death/cold_pool_death_m.F90 @ 3899

Last change on this file since 3899 was 3899, checked in by lguez, 3 years ago

Old work on cold pool death.

File size: 4.6 KB
Line 
1module cold_pool_death_m
2
3  implicit none
4
5contains
6
7  subroutine cold_pool_death(z_cp0, r0, h0, eps_cp, beta, av_thvu_constant, &
8       k_star, av_thvu, rate_uns, theta_vs, theta_v_uns, c_dw, av_rho, &
9       return_code, wake_lifetime, wake_final_radius, wake_final_height, t, &
10       yp, dydt_p, nbad)
11
12    use cold_pool_death_condition_m, only: cold_pool_death_condition, &
13         delta_death
14    use derivs_m, only: derivs
15    use derivs_param, only: set_module_var
16    use numer_rec_95, only: rkqs, odeint_all_points
17
18    real, intent(in):: z_cp0 ! initial height of cold pool, in m
19    real, intent(in):: r0 ! initial radius of cold pool, in m
20    real, intent(in):: h0 ! initial height of environmental boundary layer, in m
21
22    real, intent(in):: eps_cp
23    ! entrainment coefficient at the border of the cold pool
24
25    real, intent(in):: beta ! entrainment at the top of the mixed layer
26    logical, intent(in):: av_thvu_constant
27    real, intent(in):: k_star
28
29    real, intent(in):: av_thvu ! average on cold pool height
30    ! of virtual potential temperature outside the cold pool, in K
31
32    real, intent(in):: rate_uns
33    ! mass rate in one unsaturated downdraft, in kg s-1
34
35    real, intent(in):: theta_vs
36    ! virtual potential temperature at the surface, in K
37
38    real, intent(in):: theta_v_uns
39    ! virtual potential temperature of the unsaturated downdraft, in K
40
41    real, intent(in):: C_dw ! drag coefficient under cold pools, in m s-1
42    real, intent(in):: av_rho ! average mass density in the cold pool, in kg m-3
43    integer, intent(out):: return_code
44    REAL, intent(out):: wake_lifetime ! in s
45    REAL, intent(out):: wake_final_radius, wake_final_height ! in m
46    real, allocatable, intent(out), optional:: t(:) ! (n) time, in s
47
48    real, allocatable, intent(out), optional:: yp(:, :) ! (5, n)
49    ! yp(:, i) is (/theta_v_cp, z_cp, r, av_thvu, h/) at date t(i)
50
51    real, allocatable, intent(out), optional:: dydt_p(:, :) ! (5, n)
52    ! time derivative of yp, in units of yp per s
53
54    integer, intent(out), optional:: nbad
55    ! number of bad (but retried and fixed) steps taken
56
57    ! Local:
58
59    integer n
60    real delta_1 ! delta theta_v at t(n - 1)
61    real delta_2 ! delta theta_v at t(n)
62    real w ! weight of interpolation between t(n - 1) and t(n)
63    real, parameter:: max_lifetime = 86400. * 30. ! in s
64
65    real, allocatable:: t_local(:) ! (n) t
66    real, allocatable:: yp_local(:, :) ! (5, n) yp
67
68    !----------------------------------------------------------
69
70    if (rate_uns < 0) then
71       ! No cold pool
72       wake_lifetime = - 4.
73       wake_final_radius = - 4.
74       wake_final_height = - 4.
75       return_code = 0
76    else if (theta_vs < av_thvu) then
77       ! Cold pool temperature would not converge to environment temperature
78       wake_lifetime = - 3.
79       wake_final_radius = - 3.
80       wake_final_height = - 3.
81       return_code = 0
82    else
83       if (theta_v_uns >= av_thvu) then
84          ! Bad vertical profile
85          wake_lifetime = - 2.
86          wake_final_radius = - 2.
87          wake_final_height = - 2.
88          return_code = 0
89       else
90          call set_module_var(eps_cp, beta, av_thvu_constant, k_star, &
91               theta_vs, rate_uns, av_rho, theta_v_uns, c_dw)
92          call odeint_all_points(derivs, rkqs, t_local, yp_local, return_code, &
93               (/theta_v_uns, z_cp0, r0, av_thvu, h0/), nbad, dydt_p, &
94               x1 = 0., x2 = max_lifetime, eps = 1e-5, dmin = 0., &
95               stop_condition = cold_pool_death_condition)
96          n = size(t_local)
97
98          if (n == 1) then
99             ! Dead-born
100             wake_lifetime = - 1.
101             wake_final_radius = - 1.
102             wake_final_height = - 1.
103          else if (cold_pool_death_condition(yp_local(:, n))) then
104             ! From the last two integration points, linearly interpolate to
105             ! delta theta_v = delta_death to find wake_lifetime:
106             delta_1 = yp_local(1, n - 1) - yp_local(4, n - 1)
107             delta_2 = yp_local(1, n) - yp_local(4, n)
108             w = (delta_death - delta_1) / (delta_2 - delta_1)
109             wake_lifetime = w * t_local(n) + (1. - w) * t_local(n - 1)
110             wake_final_radius = w * yp_local(3, n) &
111                  + (1. - w) * yp_local(3, n - 1)
112             wake_final_height = w * yp_local(2, n) &
113                  + (1. - w) * yp_local(2, n - 1)
114          else
115             ! Cold pool did not die.
116             wake_lifetime = - 5.
117             wake_final_radius = - 5.
118             wake_final_height = - 5.
119          end if
120
121          if (present(t)) t = t_local
122          if (present(yp)) yp = yp_local
123       end if
124    end if
125
126  end subroutine cold_pool_death
127
128end module cold_pool_death_m
Note: See TracBrowser for help on using the repository browser.