/[lmdze]/trunk/phylmd/Interface_surf/soil.f90
ViewVC logotype

Contents of /trunk/phylmd/Interface_surf/soil.f90

Parent Directory Parent Directory | Revision Log Revision Log


Revision 346 - (show annotations)
Mon Dec 9 20:15:29 2019 UTC (4 years, 5 months ago) by guez
File size: 7403 byte(s)
Rename block to `my_block` in procedure `CLOUDS_GNO` because block is
a Fortran keyword.

Remove computation of palpbla in procedure sw. It was not used nor
output. (Not used nor output either in LMDZ.)

In procedure physiq, define `d_[uv]_con` and add them to `[uv]_seri`
only if `conv_Emanuel`. Thus, we do not need to initialize
`d_[uv]_con` to 0, we do not have to save them and we do not add 0 to
`[uv]_seri`.

In procedure physiq, no need to initialize rnebcon to 0, it is defined
by phyetat0 afterwards.

Check that `iflag_cldcon` is between - 2 and 3.

1 module soil_m
2
3 IMPLICIT NONE
4
5 private fz
6
7 contains
8
9 SUBROUTINE soil(nisurf, snow, tsurf, tsoil, soilcap, soilflux)
10
11 ! From LMDZ4/libf/phylmd/soil.F, version 1.1.1.1, 2004/05/19
12
13 ! Author: Frederic Hourdin, January 30th, 1992
14
15 ! Object: computation of the soil temperature evolution, the heat
16 ! capacity per unit surface and the surface conduction flux
17
18 ! Method: implicit time integration
19
20 ! Consecutive ground temperatures are related by:
21 ! T(k + 1) = C(k) + D(k) * T(k) (equation 1)
22 ! The coefficients C and D are computed at the t - dt time-step.
23 ! Structure of the procedure:
24 ! 1) new temperatures are computed using equation 1
25 ! 2) C and D coefficients are computed from the new temperature
26 ! profile for the t + dt time-step
27 ! 3) the coefficients A and B are computed where the diffusive
28 ! fluxes at the t + dt time-step is given by
29 ! Fdiff = A + B Ts(t + dt)
30 ! or
31 ! Fdiff = F0 + Soilcap (Ts(t + dt) - Ts(t)) / dt
32 ! with
33 ! F0 = A + B (Ts(t))
34 ! Soilcap = B * dt
35
36 ! Libraries:
37 use jumble, only: new_unit
38
39 use comconst, only: dtphys
40 USE dimphy, only: klon
41 USE dimsoil, only: nsoilmx
42 USE indicesol, only: nbsrf, is_lic, is_oce, is_sic, is_ter
43 USE suphec_m, only: rtt
44
45 INTEGER, intent(in):: nisurf ! surface type index
46 REAL, intent(in):: snow(:) ! (knon)
47 REAL, intent(in):: tsurf(:) ! (knon) surface temperature at time-step t (K)
48
49 real, intent(inout):: tsoil(:, :) ! (knon, nsoilmx)
50 ! temperature inside the ground (K), layer 1 nearest to the surface
51
52 REAL, intent(out):: soilcap(:) ! (knon)
53 ! specific heat per unit surface (W m-2 s K-1)
54
55 REAL, intent(out):: soilflux(:) ! (knon)
56 ! surface diffusive flux from ground (W m-2)
57
58 ! Local:
59 INTEGER knon, ig, jk, unit
60 REAL zdz2(nsoilmx)
61 real z1(size(tsurf), nbsrf) ! (knon, nbsrf)
62 REAL min_period ! in s
63 real dalph_soil ! rapport entre les \'epaisseurs de 2 couches successives
64 REAL ztherm_i(size(tsurf)) ! (knon)
65 REAL, save:: dz1(nsoilmx), dz2(nsoilmx)
66 REAL, save:: zc(klon, nsoilmx, nbsrf), zd(klon, nsoilmx, nbsrf)
67 REAL, save:: lambda
68 LOGICAL:: firstsurf(nbsrf) = .TRUE.
69 REAL, parameter:: isol = 2000., isno = 2000., iice = 2000.
70 REAL rk, fz1, rk1, rk2 ! depths
71
72 !-----------------------------------------------------------------------
73
74 knon = size(tsurf)
75
76 ! Calcul de l'inertie thermique. On initialise \`a iice m\^eme
77 ! au-dessus d'un point de mer pour le cas o\`u le point de mer
78 ! deviendrait point de glace au pas suivant. On corrige si on a un
79 ! point de terre avec ou sans glace.
80
81 select case (nisurf)
82 case (is_sic)
83 DO ig = 1, knon
84 IF (snow(ig) > 0.) then
85 ztherm_i(ig) = isno
86 else
87 ztherm_i(ig) = iice
88 end IF
89 END DO
90 case (is_lic)
91 DO ig = 1, knon
92 IF (snow(ig) > 0.) then
93 ztherm_i(ig) = isno
94 else
95 ztherm_i(ig) = iice
96 end IF
97 END DO
98 case (is_ter)
99 DO ig = 1, knon
100 IF (snow(ig) > 0.) then
101 ztherm_i(ig) = isno
102 else
103 ztherm_i(ig) = isol
104 end IF
105 END DO
106 case (is_oce)
107 DO ig = 1, knon
108 ztherm_i(ig) = iice
109 END DO
110 case default
111 PRINT *, 'soil: unexpected subscript value:', nisurf
112 STOP 1
113 END select
114
115 IF (firstsurf(nisurf)) THEN
116 ! ground levels
117 ! grnd=z / l where l is the skin depth of the diurnal cycle:
118
119 min_period = 1800.
120 dalph_soil = 2.
121 call new_unit(unit)
122 OPEN(unit, FILE = 'soil.def', STATUS = 'old', action = "read", &
123 position = 'rewind', ERR = 9999)
124 READ(unit, fmt = *) min_period
125 READ(unit, fmt = *) dalph_soil
126 PRINT *, 'Discretization for the soil model'
127 PRINT *, 'First level e-folding depth', min_period, ' dalph', &
128 dalph_soil
129 CLOSE(unit)
130 9999 CONTINUE
131
132 ! La premi\`ere couche repr\'esente un dixi\`eme de cycle diurne :
133 fz1 = sqrt(min_period / 3.14)
134
135 DO jk = 1, nsoilmx
136 rk1 = jk
137 rk2 = jk - 1
138 dz2(jk) = fz(rk1, dalph_soil, fz1) - fz(rk2, dalph_soil, fz1)
139 END DO
140
141 DO jk = 1, nsoilmx - 1
142 rk1 = jk + .5
143 rk2 = jk - .5
144 dz1(jk) = 1. / (fz(rk1, dalph_soil, fz1) - fz(rk2, dalph_soil, fz1))
145 END DO
146
147 lambda = fz(.5, dalph_soil, fz1) * dz1(1)
148 PRINT *, 'full layers, intermediate layers (seconds)'
149
150 DO jk = 1, nsoilmx
151 rk = jk
152 rk1 = jk + .5
153 rk2 = jk - .5
154 PRINT *, 'fz=', fz(rk1, dalph_soil, fz1) * fz(rk2, dalph_soil, fz1) &
155 * 3.14, fz(rk, dalph_soil, fz1) * fz(rk, dalph_soil, fz1) * 3.14
156 END DO
157
158 firstsurf(nisurf) = .FALSE.
159 ELSE
160 ! Computation of the soil temperatures using the Zc and Zd
161 ! coefficient computed at the previous time-step:
162
163 ! Surface temperature:
164 DO ig = 1, knon
165 tsoil(ig, 1) = (lambda * zc(ig, 1, nisurf) + tsurf(ig)) &
166 / (lambda * (1. - zd(ig, 1, nisurf)) + 1.)
167 END DO
168
169 ! Other temperatures:
170 DO jk = 1, nsoilmx - 1
171 DO ig = 1, knon
172 tsoil(ig, jk + 1) = zc(ig, jk, nisurf) &
173 + zd(ig, jk, nisurf) * tsoil(ig, jk)
174 END DO
175 END DO
176 END IF
177
178 ! Computation of the Zc and Zd coefficient for the next step:
179
180 IF (nisurf==is_sic) THEN
181 DO ig = 1, knon
182 tsoil(ig, nsoilmx) = rtt - 1.8
183 END DO
184 END IF
185
186 DO jk = 1, nsoilmx
187 zdz2(jk) = dz2(jk) / dtphys
188 END DO
189
190 DO ig = 1, knon
191 z1(ig, nisurf) = zdz2(nsoilmx) + dz1(nsoilmx - 1)
192 zc(ig, nsoilmx - 1, nisurf) = zdz2(nsoilmx) * tsoil(ig, nsoilmx) / &
193 z1(ig, nisurf)
194 zd(ig, nsoilmx - 1, nisurf) = dz1(nsoilmx - 1) / z1(ig, nisurf)
195 END DO
196
197 DO jk = nsoilmx - 1, 2, - 1
198 DO ig = 1, knon
199 z1(ig, nisurf) = 1. / (zdz2(jk) + dz1(jk - 1) &
200 + dz1(jk) * (1. - zd(ig, jk, nisurf)))
201 zc(ig, jk - 1, nisurf) = (tsoil(ig, jk) * zdz2(jk) &
202 + dz1(jk) * zc(ig, jk, nisurf)) * z1(ig, nisurf)
203 zd(ig, jk - 1, nisurf) = dz1(jk - 1) * z1(ig, nisurf)
204 END DO
205 END DO
206
207 ! Computation of the surface diffusive flux from ground and
208 ! calorific capacity of the ground:
209
210 DO ig = 1, knon
211 soilflux(ig) = ztherm_i(ig) * dz1(1) * (zc(ig, 1, nisurf) &
212 + (zd(ig, 1, nisurf) - 1.) * tsoil(ig, 1))
213 soilcap(ig) = ztherm_i(ig) * (dz2(1) &
214 + dtphys * (1. - zd(ig, 1, nisurf)) * dz1(1))
215 z1(ig, nisurf) = lambda * (1. - zd(ig, 1, nisurf)) + 1.
216 soilcap(ig) = soilcap(ig) / z1(ig, nisurf)
217 soilflux(ig) = soilflux(ig) + soilcap(ig) * (tsoil(ig, 1) &
218 * z1(ig, nisurf) - lambda * zc(ig, 1, nisurf) - tsurf(ig)) / dtphys
219 END DO
220
221 END SUBROUTINE soil
222
223 !****************************************************************
224
225 pure real function fz(rk, dalph_soil, fz1)
226
227 real, intent(in):: rk
228
229 real, intent(in):: dalph_soil
230 ! rapport entre les \'epaisseurs de 2 couches successives
231
232 real, intent(in):: fz1 ! depth
233
234 !-----------------------------------------
235
236 fz = fz1 * (dalph_soil**rk - 1.) / (dalph_soil - 1.)
237
238 end function fz
239
240 end module soil_m

  ViewVC Help
Powered by ViewVC 1.1.21