/[lmdze]/trunk/Sources/phylmd/Interface_surf/soil.f
ViewVC logotype

Diff of /trunk/Sources/phylmd/Interface_surf/soil.f

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/libf/phylmd/soil.f revision 3 by guez, Wed Feb 27 13:16:39 2008 UTC trunk/Sources/phylmd/Interface_surf/soil.f revision 221 by guez, Thu Apr 20 14:44:47 2017 UTC
# Line 1  Line 1 
1  !  module soil_m
 ! $Header: /home/cvsroot/LMDZ4/libf/phylmd/soil.F,v 1.1.1.1 2004/05/19 12:53:09 lmdzadmin Exp $  
 !  
       SUBROUTINE soil(ptimestep, indice, knon, snow, ptsrf, ptsoil,  
      s          pcapcal, pfluxgrd)  
       use dimens_m  
       use indicesol  
       use dimphy  
       use dimsoil  
       use YOMCST  
       IMPLICIT NONE  
   
 c=======================================================================  
 c  
 c   Auteur:  Frederic Hourdin     30/01/92  
 c   -------  
 c  
 c   objet:  computation of : the soil temperature evolution  
 c   ------                   the surfacic heat capacity "Capcal"  
 c                            the surface conduction flux pcapcal  
 c  
 c  
 c   Method: implicit time integration  
 c   -------  
 c   Consecutive ground temperatures are related by:  
 c           T(k+1) = C(k) + D(k)*T(k)  (1)  
 c   the coefficients C and D are computed at the t-dt time-step.  
 c   Routine structure:  
 c   1)new temperatures are computed  using (1)  
 c   2)C and D coefficients are computed from the new temperature  
 c     profile for the t+dt time-step  
 c   3)the coefficients A and B are computed where the diffusive  
 c     fluxes at the t+dt time-step is given by  
 c            Fdiff = A + B Ts(t+dt)  
 c     or     Fdiff = F0 + Capcal (Ts(t+dt)-Ts(t))/dt  
 c            with F0 = A + B (Ts(t))  
 c                 Capcal = B*dt  
 c            
 c   Interface:  
 c   ----------  
 c  
 c   Arguments:  
 c   ----------  
 c   ptimestep            physical timestep (s)  
 c   indice               sub-surface index  
 c   snow(klon,nbsrf)     snow  
 c   ptsrf(klon)          surface temperature at time-step t (K)  
 c   ptsoil(klon,nsoilmx) temperature inside the ground (K)  
 c   pcapcal(klon)        surfacic specific heat (W*m-2*s*K-1)  
 c   pfluxgrd(klon)       surface diffusive flux from ground (Wm-2)  
 c    
 c=======================================================================  
 c   declarations:  
 c   -------------  
   
   
 c-----------------------------------------------------------------------  
 c  arguments  
 c  ---------  
   
       REAL ptimestep  
       INTEGER indice, knon  
       REAL ptsrf(klon),ptsoil(klon,nsoilmx),snow(klon)  
       REAL pcapcal(klon),pfluxgrd(klon)  
   
 c-----------------------------------------------------------------------  
 c  local arrays  
 c  ------------  
   
       INTEGER ig,jk  
 c$$$      REAL zdz2(nsoilmx),z1(klon)  
       REAL zdz2(nsoilmx),z1(klon,nbsrf)  
       REAL min_period,dalph_soil  
       REAL ztherm_i(klon)  
   
 c   local saved variables:  
 c   ----------------------  
       REAL dz1(nsoilmx),dz2(nsoilmx)  
 c$$$          REAL zc(klon,nsoilmx),zd(klon,nsoilmx)  
       REAL zc(klon,nsoilmx,nbsrf),zd(klon,nsoilmx,nbsrf)  
       REAL lambda  
       SAVE dz1,dz2,zc,zd,lambda  
       LOGICAL firstcall, firstsurf(nbsrf)  
       SAVE firstcall, firstsurf  
       REAL isol,isno,iice  
       SAVE isol,isno,iice  
   
       DATA firstcall/.true./  
       DATA firstsurf/.TRUE.,.TRUE.,.TRUE.,.TRUE./  
   
       DATA isol,isno,iice/2000.,2000.,2000./  
   
 c-----------------------------------------------------------------------  
 c   Depthts:  
 c   --------  
   
       REAL fz,rk,fz1,rk1,rk2  
       fz(rk)=fz1*(dalph_soil**rk-1.)/(dalph_soil-1.)  
       pfluxgrd(:) = 0.  
 c   calcul de l'inertie thermique a partir de la variable rnat.  
 c   on initialise a iice meme au-dessus d'un point de mer au cas  
 c   ou le point de mer devienne point de glace au pas suivant  
 c   on corrige si on a un point de terre avec ou sans glace  
 c  
       IF (indice.EQ.is_sic) THEN  
          DO ig = 1, knon  
             ztherm_i(ig)   = iice  
             IF (snow(ig).GT.0.0) ztherm_i(ig)   = isno  
          ENDDO  
       ELSE IF (indice.EQ.is_lic) THEN  
          DO ig = 1, knon  
             ztherm_i(ig)   = iice  
             IF (snow(ig).GT.0.0) ztherm_i(ig)   = isno  
          ENDDO  
       ELSE IF (indice.EQ.is_ter) THEN  
          DO ig = 1, knon  
             ztherm_i(ig)   = isol  
             IF (snow(ig).GT.0.0) ztherm_i(ig)   = isno  
          ENDDO  
       ELSE IF (indice.EQ.is_oce) THEN  
          DO ig = 1, knon  
             ztherm_i(ig)   = iice  
          ENDDO  
       ELSE  
          PRINT*, "valeur d indice non prevue", indice  
          stop 1  
       ENDIF  
   
   
 c$$$      IF (firstcall) THEN  
       IF (firstsurf(indice)) THEN  
   
 c-----------------------------------------------------------------------  
 c   ground levels  
 c   grnd=z/l where l is the skin depth of the diurnal cycle:  
 c   --------------------------------------------------------  
   
          min_period=1800. ! en secondes  
          dalph_soil=2.    ! rapport entre les epaisseurs de 2 couches succ.  
   
          OPEN(99,file='soil.def',status='old',form='formatted',err=9999)  
          READ(99,*) min_period  
          READ(99,*) dalph_soil  
          PRINT*,'Discretization for the soil model'  
          PRINT*,'First level e-folding depth',min_period,  
      s   '   dalph',dalph_soil  
          CLOSE(99)  
 9999     CONTINUE  
   
 c   la premiere couche represente un dixieme de cycle diurne  
          fz1=sqrt(min_period/3.14)  
   
          DO jk=1,nsoilmx  
             rk1=jk  
             rk2=jk-1  
             dz2(jk)=fz(rk1)-fz(rk2)  
          ENDDO  
          DO jk=1,nsoilmx-1  
             rk1=jk+.5  
             rk2=jk-.5  
             dz1(jk)=1./(fz(rk1)-fz(rk2))  
          ENDDO  
          lambda=fz(.5)*dz1(1)  
          PRINT*,'full layers, intermediate layers (seconds)'  
          DO jk=1,nsoilmx  
             rk=jk  
             rk1=jk+.5  
             rk2=jk-.5  
             PRINT *,'fz=',  
      .               fz(rk1)*fz(rk2)*3.14,fz(rk)*fz(rk)*3.14  
          ENDDO  
 C PB  
          firstsurf(indice) = .FALSE.  
 c$$$         firstcall =.false.  
   
 c   Initialisations:  
 c   ----------------  
   
       ELSE   !--not firstcall  
 c-----------------------------------------------------------------------  
 c   Computation of the soil temperatures using the Cgrd and Dgrd  
 c  coefficient computed at the previous time-step:  
 c  -----------------------------------------------  
   
 c    surface temperature  
          DO ig=1,knon  
             ptsoil(ig,1)=(lambda*zc(ig,1,indice)+ptsrf(ig))/  
      s      (lambda*(1.-zd(ig,1,indice))+1.)  
          ENDDO  
   
 c   other temperatures  
          DO jk=1,nsoilmx-1  
             DO ig=1,knon  
                ptsoil(ig,jk+1)=zc(ig,jk,indice)+zd(ig,jk,indice)  
      $            *ptsoil(ig,jk)  
             ENDDO  
          ENDDO  
   
       ENDIF !--not firstcall  
 c-----------------------------------------------------------------------  
 c   Computation of the Cgrd and Dgrd coefficient for the next step:  
 c   ---------------------------------------------------------------  
   
 c$$$  PB ajout pour cas glace de mer  
       IF (indice .EQ. is_sic) THEN  
           DO ig = 1 , knon  
             ptsoil(ig,nsoilmx) = RTT - 1.8  
           END DO  
       ENDIF  
   
       DO jk=1,nsoilmx  
          zdz2(jk)=dz2(jk)/ptimestep  
       ENDDO  
   
       DO ig=1,knon  
          z1(ig,indice)=zdz2(nsoilmx)+dz1(nsoilmx-1)  
          zc(ig,nsoilmx-1,indice)=  
      $       zdz2(nsoilmx)*ptsoil(ig,nsoilmx)/z1(ig,indice)  
          zd(ig,nsoilmx-1,indice)=dz1(nsoilmx-1)/z1(ig,indice)  
       ENDDO  
   
       DO jk=nsoilmx-1,2,-1  
          DO ig=1,knon  
             z1(ig,indice)=1./(zdz2(jk)+dz1(jk-1)+dz1(jk)  
      $         *(1.-zd(ig,jk,indice)))  
             zc(ig,jk-1,indice)=  
      s      (ptsoil(ig,jk)*zdz2(jk)+dz1(jk)*zc(ig,jk,indice))  
      $          *z1(ig,indice)  
             zd(ig,jk-1,indice)=dz1(jk-1)*z1(ig,indice)  
          ENDDO  
       ENDDO  
   
 c-----------------------------------------------------------------------  
 c   computation of the surface diffusive flux from ground and  
 c   calorific capacity of the ground:  
 c   ---------------------------------  
   
       DO ig=1,knon  
          pfluxgrd(ig)=ztherm_i(ig)*dz1(1)*  
      s   (zc(ig,1,indice)+(zd(ig,1,indice)-1.)*ptsoil(ig,1))  
          pcapcal(ig)=ztherm_i(ig)*  
      s   (dz2(1)+ptimestep*(1.-zd(ig,1,indice))*dz1(1))  
          z1(ig,indice)=lambda*(1.-zd(ig,1,indice))+1.  
          pcapcal(ig)=pcapcal(ig)/z1(ig,indice)  
          pfluxgrd(ig) = pfluxgrd(ig)  
      s   + pcapcal(ig) * (ptsoil(ig,1) * z1(ig,indice)  
      $       - lambda * zc(ig,1,indice)  
      $       - ptsrf(ig))  
      s   /ptimestep  
       ENDDO  
2    
3        RETURN    IMPLICIT NONE
4        END  
5    contains
6    
7      SUBROUTINE soil(dtime, nisurf, snow, tsurf, tsoil, soilcap, soilflux)
8    
9        ! From LMDZ4/libf/phylmd/soil.F, version 1.1.1.1, 2004/05/19
10    
11        ! Author: Frederic Hourdin, January 30th, 1992
12    
13        ! Object: computation of the soil temperature evolution, the heat
14        ! capacity per unit surface and the surface conduction flux
15    
16        ! Method: implicit time integration
17    
18        ! Consecutive ground temperatures are related by:
19        ! T(k + 1) = C(k) + D(k) * T(k) (1)
20        ! The coefficients C and D are computed at the t - dt time-step.
21        ! Structure of the procedure:
22        ! 1) new temperatures are computed using (1)
23        ! 2) C and D coefficients are computed from the new temperature
24        ! profile for the t + dt time-step
25        ! 3) the coefficients A and B are computed where the diffusive
26        ! fluxes at the t + dt time-step is given by
27        ! Fdiff = A + B Ts(t + dt)
28        ! or
29        ! Fdiff = F0 + Soilcap (Ts(t + dt) - Ts(t)) / dt
30        ! with
31        ! F0 = A + B (Ts(t))
32        ! Soilcap = B * dt
33    
34        USE indicesol, only: nbsrf, is_lic, is_oce, is_sic, is_ter
35        USE dimphy, only: klon
36        USE dimsoil, only: nsoilmx
37        USE suphec_m, only: rtt
38    
39        REAL, intent(in):: dtime ! physical timestep (s)
40        INTEGER, intent(in):: nisurf ! sub-surface index
41        REAL, intent(in):: snow(:) ! (knon)
42        REAL, intent(in):: tsurf(:) ! (knon) surface temperature at time-step t (K)
43    
44        real, intent(inout):: tsoil(:, :) ! (knon, nsoilmx)
45        ! temperature inside the ground (K)
46    
47        REAL, intent(out):: soilcap(:) ! (knon)
48        ! specific heat per unit surface (W m-2 s K-1)
49    
50        REAL, intent(out):: soilflux(:) ! (knon)
51        ! surface diffusive flux from ground (W m-2)
52    
53        ! Local:
54    
55        INTEGER knon, ig, jk
56        REAL zdz2(nsoilmx)
57        real z1(size(tsurf), nbsrf) ! (knon, nbsrf)
58        REAL min_period, dalph_soil
59        REAL ztherm_i(size(tsurf)) ! (knon)
60        REAL, save:: dz1(nsoilmx), dz2(nsoilmx)
61        REAL, save:: zc(klon, nsoilmx, nbsrf), zd(klon, nsoilmx, nbsrf)
62        REAL, save:: lambda
63        LOGICAL:: firstsurf(nbsrf) = .TRUE.
64        REAL:: isol = 2000., isno = 2000., iice = 2000.
65    
66        ! Depths:
67        REAL rk, fz1, rk1, rk2
68    
69        !-----------------------------------------------------------------------
70    
71        knon = size(tsurf)
72    
73        ! Calcul de l'inertie thermique. On initialise \`a iice m\^eme
74        ! au-dessus d'un point de mer au cas o\`u le point de mer devienne
75        ! point de glace au pas suivant. On corrige si on a un point de
76        ! terre avec ou sans glace.
77    
78        IF (nisurf==is_sic) THEN
79           DO ig = 1, knon
80              ztherm_i(ig) = iice
81              IF (snow(ig) > 0.0) ztherm_i(ig) = isno
82           END DO
83        ELSE IF (nisurf==is_lic) THEN
84           DO ig = 1, knon
85              ztherm_i(ig) = iice
86              IF (snow(ig) > 0.0) ztherm_i(ig) = isno
87           END DO
88        ELSE IF (nisurf==is_ter) THEN
89           DO ig = 1, knon
90              ztherm_i(ig) = isol
91              IF (snow(ig) > 0.0) ztherm_i(ig) = isno
92           END DO
93        ELSE IF (nisurf==is_oce) THEN
94           DO ig = 1, knon
95              ztherm_i(ig) = iice
96           END DO
97        ELSE
98           PRINT *, 'valeur d indice non prevue', nisurf
99           STOP 1
100        END IF
101    
102        IF (firstsurf(nisurf)) THEN
103           ! ground levels
104           ! grnd=z / l where l is the skin depth of the diurnal cycle:
105    
106           min_period = 1800. ! en secondes
107           dalph_soil = 2. ! rapport entre les epaisseurs de 2 couches succ.
108    
109           OPEN(99, FILE='soil.def', STATUS='old', FORM='formatted', ERR=9999)
110           READ(99, *) min_period
111           READ(99, *) dalph_soil
112           PRINT *, 'Discretization for the soil model'
113           PRINT *, 'First level e-folding depth', min_period, ' dalph', &
114                dalph_soil
115           CLOSE(99)
116    9999   CONTINUE
117    
118           ! la premiere couche represente un dixieme de cycle diurne
119           fz1 = sqrt(min_period / 3.14)
120    
121           DO jk = 1, nsoilmx
122              rk1 = jk
123              rk2 = jk - 1
124              dz2(jk) = fz(rk1) - fz(rk2)
125           END DO
126           DO jk = 1, nsoilmx - 1
127              rk1 = jk + .5
128              rk2 = jk - .5
129              dz1(jk) = 1. / (fz(rk1) - fz(rk2))
130           END DO
131           lambda = fz(.5) * dz1(1)
132           PRINT *, 'full layers, intermediate layers (seconds)'
133           DO jk = 1, nsoilmx
134              rk = jk
135              rk1 = jk + .5
136              rk2 = jk - .5
137              PRINT *, 'fz=', fz(rk1) * fz(rk2) * 3.14, fz(rk) * fz(rk) * 3.14
138           END DO
139           ! PB
140           firstsurf(nisurf) = .FALSE.
141        ELSE
142           ! Computation of the soil temperatures using the Zc and Zd
143           ! coefficient computed at the previous time-step:
144    
145           ! surface temperature
146           DO ig = 1, knon
147              tsoil(ig, 1) = (lambda * zc(ig, 1, nisurf) + tsurf(ig)) &
148                   / (lambda * (1. - zd(ig, 1, nisurf)) + 1.)
149           END DO
150    
151           ! other temperatures
152           DO jk = 1, nsoilmx - 1
153              DO ig = 1, knon
154                 tsoil(ig, jk + 1) = zc(ig, jk, nisurf) &
155                      + zd(ig, jk, nisurf) * tsoil(ig, jk)
156              END DO
157           END DO
158        END IF
159    
160        ! Computation of the Zc and Zd coefficient for the next step:
161    
162        IF (nisurf==is_sic) THEN
163           DO ig = 1, knon
164              tsoil(ig, nsoilmx) = rtt - 1.8
165           END DO
166        END IF
167    
168        DO jk = 1, nsoilmx
169           zdz2(jk) = dz2(jk) / dtime
170        END DO
171    
172        DO ig = 1, knon
173           z1(ig, nisurf) = zdz2(nsoilmx) + dz1(nsoilmx - 1)
174           zc(ig, nsoilmx - 1, nisurf) = zdz2(nsoilmx) * tsoil(ig, nsoilmx) / &
175                z1(ig, nisurf)
176           zd(ig, nsoilmx - 1, nisurf) = dz1(nsoilmx - 1) / z1(ig, nisurf)
177        END DO
178    
179        DO jk = nsoilmx - 1, 2, - 1
180           DO ig = 1, knon
181              z1(ig, nisurf) = 1. / (zdz2(jk) + dz1(jk - 1) &
182                   + dz1(jk) * (1. - zd(ig, jk, nisurf)))
183              zc(ig, jk - 1, nisurf) = (tsoil(ig, jk) * zdz2(jk) &
184                   + dz1(jk) * zc(ig, jk, nisurf)) * z1(ig, nisurf)
185              zd(ig, jk - 1, nisurf) = dz1(jk - 1) * z1(ig, nisurf)
186           END DO
187        END DO
188    
189        ! computation of the surface diffusive flux from ground and
190        ! calorific capacity of the ground:
191    
192        DO ig = 1, knon
193           soilflux(ig) = ztherm_i(ig) * dz1(1) * (zc(ig, 1, nisurf) + (zd(ig, 1, &
194                nisurf) - 1.) * tsoil(ig, 1))
195           soilcap(ig) = ztherm_i(ig) * (dz2(1) &
196                + dtime * (1. - zd(ig, 1, nisurf)) * dz1(1))
197           z1(ig, nisurf) = lambda * (1. - zd(ig, 1, nisurf)) + 1.
198           soilcap(ig) = soilcap(ig) / z1(ig, nisurf)
199           soilflux(ig) = soilflux(ig) + soilcap(ig) * (tsoil(ig, 1) &
200                * z1(ig, nisurf) - lambda * zc(ig, 1, nisurf) - tsurf(ig)) / dtime
201        END DO
202    
203      contains
204    
205        pure real function fz(rk)
206    
207          real, intent(in):: rk
208    
209          !-----------------------------------------
210    
211          fz = fz1 * (dalph_soil**rk - 1.) / (dalph_soil - 1.)
212    
213        end function fz
214    
215      END SUBROUTINE soil
216    
217    end module soil_m

Legend:
Removed from v.3  
changed lines
  Added in v.221

  ViewVC Help
Powered by ViewVC 1.1.21