SURFEX  V8_0
Surfex V8_0 release
 All Classes Files Functions Variables
soil_heatdif.F90
Go to the documentation of this file.
1 !SFX_LIC Copyright 1994-2014 CNRS, Meteo-France and Universite Paul Sabatier
2 !SFX_LIC This is part of the SURFEX software governed by the CeCILL-C licence
3 !SFX_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt
4 !SFX_LIC for details. version 1.
5 ! #########
6  SUBROUTINE soil_heatdif(PTSTEP,PDZG,PDZDIF,PSOILCONDZ, &
7  psoilhcapz,pct,pterm1,pterm2, &
8  ptdeep_a,ptdeep_b,ptg,pdeep_flux,&
9  pflux_cor )
10 ! ############################################################################
11 !
12 !!**** *SOIL_HEATDIF*
13 !
14 !! PURPOSE
15 !! -------
16 ! This subroutine solves the 1-d diffusion of 'PTG' using a
17 ! layer averaged set of equations which are time differenced
18 ! using the backward-difference scheme (implicit).
19 ! The eqs are solved rapidly by taking advantage of the
20 ! fact that the matrix is tridiagonal. This is a very
21 ! general routine and can be used for the 1-d diffusion of any
22 ! quantity as long as the diffusity is not a function of the
23 ! quantity being diffused. Aaron Boone 8-98. Soln to the eq:
24 !
25 ! dQ d dQ
26 ! c -- = -- k --
27 ! dt dx dx
28 !
29 ! where k = k(x) (thermal conductivity), c = c(x) (heat capacity)
30 ! Diffusivity is k/c
31 !
32 !
33 !!** METHOD
34 !! ------
35 !
36 ! Direct calculation
37 !
38 !! EXTERNAL
39 !! --------
40 !
41 ! None
42 !!
43 !! IMPLICIT ARGUMENTS
44 !! ------------------
45 !!
46 !! USE MODD_PARAMETERS
47 !! USE MODI_TRIDIAG_GROUND
48 !!
49 !! REFERENCE
50 !! ---------
51 !!
52 !! Boone (2000)
53 !! Boone et al. (2000)
54 !!
55 !! AUTHOR
56 !! ------
57 !! A. Boone * Meteo-France *
58 !!
59 !! MODIFICATIONS
60 !! -------------
61 !! Original 16/02/00 Boone
62 !! Modif 08/2011 B. Decharme : Optimization
63 !! Modif 10/2014 B. Decharme : Use harmonic mean to compute
64 !! interfacial thermal conductivities
65 !-------------------------------------------------------------------------------
66 !
67 !* 0. DECLARATIONS
68 ! ------------
69 !
70 USE modd_surf_par, ONLY : xundef
71 !
72 USE modi_tridiag_ground
73 !
74 !
75 USE yomhook ,ONLY : lhook, dr_hook
76 USE parkind1 ,ONLY : jprb
77 !
78 IMPLICIT NONE
79 !
80 !
81 REAL, INTENT(IN) :: ptstep ! Model time step (s)
82 !
83 REAL, DIMENSION(:), INTENT(IN) :: pct, pterm1, pterm2, ptdeep_a, ptdeep_b
84 ! PCT = thermal inertia [(m2 K)/J]
85 ! PTERM1 = coefficient of linearization
86 ! of surface energy budget
87 ! PTERM2 = coefficient of linearization
88 ! of surface energy budget
89 ! PTDEEP_A = Deep soil temperature
90 ! coefficient depending on flux
91 ! PTDEEP_B = Deep soil temperature (prescribed)
92 ! which models heating/cooling from
93 ! below the diurnal wave penetration
94 ! (surface temperature) depth. If it
95 ! is FLAGGED as undefined, then the zero
96 ! flux lower BC is applied.
97 ! Tdeep = PTDEEP_B + PTDEEP_A * PDEEP_FLUX
98 ! (with PDEEP_FLUX in W/m2)
99 !
100 REAL, DIMENSION(:,:), INTENT(IN) :: psoilcondz, psoilhcapz, pflux_cor
101 ! PSOILCONDZ = soil thermal conductivity [W/(K m)]
102 ! PSOILHCAPZ = soil heat capacity [J/(m3 K)]
103 ! PFLUX_COR = correction flux to close energy budget (W/m2)
104 !
105 REAL, DIMENSION(:,:), INTENT(IN) :: pdzdif, pdzg
106 ! PDZDIF = distance between consecuative layer mid-points
107 ! PDZG = soil layers thicknesses
108 !
109 REAL, DIMENSION(:,:), INTENT(INOUT) :: ptg
110 ! PTG = soil temperature (K)
111 !
112 REAL, DIMENSION(:), INTENT(OUT) :: pdeep_flux ! Heat flux at bottom of ISBA (W/m2)
113 !
114 !
115 !* 0.2 declarations of local variables
116 !
117 INTEGER :: jj, jl
118 !
119 INTEGER :: ini, inlvld ! Number of point and grid layers
120 !
121 REAL, DIMENSION(SIZE(PTG,1),SIZE(PTG,2)) :: ztgm, zdterm, zcterm, &
122  zfrcv, zamtrx, zbmtrx, &
123  zcmtrx
124 !
125 REAL :: zwork1, zwork2
126 !
127 REAL(KIND=JPRB) :: zhook_handle
128 !
129 !-------------------------------------------------------------------------------
130 !
131 ! Initialize local variables:
132 !
133 IF (lhook) CALL dr_hook('SOIL_HEATDIF',0,zhook_handle)
134 zdterm(:,:) = 0.0
135 zcterm(:,:) = 0.0
136 zfrcv(:,:) = 0.0
137 zamtrx(:,:) = 0.0
138 zbmtrx(:,:) = 0.0
139 zcmtrx(:,:) = 0.0
140 ztgm(:,:) = ptg(:,:)
141 !
142 ini = SIZE(ptg(:,:),1)
143 inlvld = SIZE(ptg(:,:),2)
144 !
145 !-------------------------------------------------------------------------------
146 !
147 ! Calculate tri-diagonal matrix coefficients:
148 !
149 DO jl=1,inlvld
150  DO jj=1,ini
151  IF(jl<inlvld)THEN
152  zwork1 = pdzg(jj,jl )/(2.0*pdzdif(jj,jl)*psoilcondz(jj,jl ))
153  zwork2 = pdzg(jj,jl+1)/(2.0*pdzdif(jj,jl)*psoilcondz(jj,jl+1))
154  ELSE
155  zwork1 = pdzg(jj,jl)/(2.0*pdzdif(jj,jl)*psoilcondz(jj,jl))
156  zwork2 = 0.0
157  ENDIF
158  zdterm(jj,jl)=1.0/(pdzdif(jj,jl)*(zwork1+zwork2))
159  zcterm(jj,jl)= psoilhcapz(jj,jl)*pdzg(jj,jl)/ptstep
160  ENDDO
161 ENDDO
162 !
163 ! - - -------------------------------------------------
164 !
165 ! Upper BC
166 !
167 zamtrx(:,1) = 0.0
168 zbmtrx(:,1) = 1./(pct(:)*ptstep)
169 zcmtrx(:,1) = -pterm2(:)*zbmtrx(:,1)
170 zfrcv(:,1) = pterm1(:)*zbmtrx(:,1)
171 !
172 ! Interior Grid
173 !
174 DO jl=2,inlvld-1
175  DO jj=1,ini
176  zamtrx(jj,jl) = -zdterm(jj,jl-1)
177  zbmtrx(jj,jl) = zcterm(jj,jl) + zdterm(jj,jl-1) + zdterm(jj,jl)
178  zcmtrx(jj,jl) = -zdterm(jj,jl)
179  zfrcv(jj,jl) = zcterm(jj,jl)*ztgm(jj,jl)+pflux_cor(jj,jl)
180  ENDDO
181 ENDDO
182 !
183 ! Lower BC: 2 currently accounted for, Either zero flux
184 ! or a fixed temperature 'TDEEP'
185 !
186 zamtrx(:,inlvld) = -zdterm(:,inlvld-1)
187 zcmtrx(:,inlvld) = 0.0
188 !
189 
190 !ZDEEP_FLUX=ZDTERM(:,INLVLD)*(ZTGM(:,INLVLD)-ZTDEEP(:))
191 !ZTDEEP=PTDEEP_A*ZDEEP_FLUX+PTDEEP_B
192 !
193 !ZDEEP_FLUX=ZDTERM(:,INLVLD)*(ZTGM(:,INLVLD)-PTDEEP_A*ZDEEP_FLUX-PTDEEP_B)
194 !ZDEEP_FLUX=ZDTERM(:,INLVLD)*(ZTGM(:,INLVLD)-PTDEEP_B)/(1.+ZDTERM(:,INLVLD)*PTDEEP_A)
195 !
196 !
197 WHERE(ptdeep_b(:) /= xundef)
198 ! ZBMTRX(:,INLVLD) = ZCTERM(:,INLVLD) + ZDTERM(:,INLVLD-1) + ZDTERM(:,INLVLD)
199 ! ZFRCV(:,INLVLD) = ZCTERM(:,INLVLD)*ZTGM(:,INLVLD) + ZDTERM(:,INLVLD)*PTDEEP(:)
200  zbmtrx(:,inlvld) = zcterm(:,inlvld) + zdterm(:,inlvld-1) &
201  + zdterm(:,inlvld)/(1.+zdterm(:,inlvld)*ptdeep_a)
202  zfrcv(:,inlvld) = zcterm(:,inlvld)*ztgm(:,inlvld) &
203  + zdterm(:,inlvld)*ptdeep_b(:)/(1.+zdterm(:,inlvld)*ptdeep_a) &
204  + pflux_cor(:,inlvld)
205 ELSEWHERE
206  zbmtrx(:,inlvld) = zcterm(:,inlvld) + zdterm(:,inlvld-1)
207  zfrcv(:,inlvld) = zcterm(:,inlvld)*ztgm(:,inlvld)+pflux_cor(:,inlvld)
208 END WHERE
209 !
210 ! - - -------------------------------------------------
211 !
212 ! Compute ZTGM (solution vector)
213 ! used for systems of equations involving tridiagonal
214 ! matricies.
215 !
216  CALL tridiag_ground(zamtrx,zbmtrx,zcmtrx,zfrcv,ztgm)
217 !
218 !
219 ! Update values in time:
220 !
221 ptg(:,:) = ztgm(:,:)
222 !
223 !* Deep soil Flux
224 !
225 pdeep_flux(:) = 0.
226 WHERE(ptdeep_b(:) /= xundef)
227  pdeep_flux=zdterm(:,inlvld)*(ztgm(:,inlvld)-ptdeep_b)/(1.+zdterm(:,inlvld)*ptdeep_a)
228 END WHERE
229 !
230 
231 IF (lhook) CALL dr_hook('SOIL_HEATDIF',1,zhook_handle)
232 !
233 !
234 !
235 END SUBROUTINE soil_heatdif
subroutine tridiag_ground(PA, PB, PC, PY, PX)
subroutine soil_heatdif(PTSTEP, PDZG, PDZDIF, PSOILCONDZ, PSOILHCAPZ, PCT, PTERM1, PTERM2, PTDEEP_A, PTDEEP_B, PTG, PDEEP_FLUX, PFLUX_COR)
Definition: soil_heatdif.F90:6