source: trunk/LMDZ.COMMON/libf/evolution/ini_soil_mod.F90 @ 2840

Last change on this file since 2840 was 2835, checked in by romain.vande, 3 years ago

Mars PEM:
Introduction of the possibility to follow an orbital forcing.
Introduction of new control parameters.
Cleaning of the PEM (removing unused files, add comments and new files)

A file named run_PEM.def can be added to the run.def. It contains the following variables:

_ evol_orbit_pem: Boolean. Do you want to follow an orbital forcing predefined (read in ob_ex_lsp.asc for example)? (default=false)
_ year_bp_ini: Integer. Number of year before present to start the pem run if evol_orbit_pem=.true. , default=0
_ Max_iter_pem: Integer. Maximal number of iteration if none of the stopping criterion is reached and if evol_orbit_pem=.false., default=99999999
_ dt_pem: Integer. Time step of the PEM in year, default=1
_ alpha_criterion: Real. Acceptance rate of sublimating ice surface change, default=0.2
_ soil_pem: Boolean. Do you want to run with subsurface physical processes in the PEM? default=.true.

RV

File size: 11.8 KB
Line 
1      MODULE ini_soil_mod
2
3      IMPLICIT NONE
4     
5      CONTAINS   
6
7     subroutine ini_icetable(timelen,ngrid,nsoil_PEM, &
8               therm_i, timestep,tsurf_ave,tsoil_ave,tsurf_inst, tsoil_inst,q_co2,q_h2o,ps,ice_table)
9
10      use vertical_layers_mod, only: ap,bp
11      use comsoil_h_PEM, only:  fluxgeo,layer_PEM,inertiedat_PEM
12      use comsoil_h,only: volcapa, nsoilmx
13
14   implicit none
15
16!-----------------------------------------------------------------------
17!  Author: LL
18!  Purpose: Compute soil temperature using an implict 1st order scheme
19
20!  Note: depths of layers and mid-layers, soil thermal inertia and
21!        heat capacity are commons in comsoil_PEM.h
22!        A convergence loop is added until equilibrium
23!-----------------------------------------------------------------------
24
25#include "dimensions.h"
26
27!-----------------------------------------------------------------------
28!  arguments
29!  ---------
30!  inputs:
31      integer,intent(in) :: timelen     ! Time length in for time-series data
32      integer,intent(in) :: ngrid       ! number of (horizontal) grid-points
33      integer,intent(in) :: nsoil_PEM   ! number of soil layers  in the PEM
34
35      real,intent(in) :: timestep           ! time step
36      real,intent(in) :: tsurf_ave(ngrid)   ! surface temperature
37
38      real,intent(in) :: q_co2(ngrid,timelen)                     ! MMR tracer co2 [kg/kg]
39      real,intent(in) :: q_h2o(ngrid,timelen)                     ! MMR tracer h2o [kg/kg]
40      real,intent(in) :: ps(ngrid,timelen)                        ! surface pressure [Pa]
41      real,intent(in) :: tsurf_inst(ngrid,timelen) ! soil (mid-layer) temperature
42
43! outputs:
44      real,intent(inout) :: tsoil_ave(ngrid,nsoil_PEM) ! soil (mid-layer) temperature.
45      real,intent(inout) :: tsoil_inst(ngrid,nsoil_PEM,timelen) ! soil (mid-layer) temperature
46      real,intent(out) :: ice_table(ngrid)                 ! ice table [m]
47      real,intent(inout) :: therm_i(ngrid,nsoil_PEM) ! thermal inertia
48
49! local variables:
50      integer ig,isoil,it,k,iref
51      REAL :: error_depth = 2.
52      REAL :: tsoil_saved(nsoil_PEM)
53      integer :: countmax = 20
54      integer :: countloop
55      REAL :: tol_error = 0.1
56      REAL :: ice_inertia = 2120.
57      REAL :: alph_PEM(nsoil_PEM-1)
58      REAL :: beta_PEM(nsoil_PEM-1)
59      real :: rhoc(nsoil_PEM)
60      real :: volcapa_ice = 1.43e7
61
62      real :: k_soil(nsoil_PEM)
63      real :: d1(nsoil_PEM),d2(nsoil_PEM),d3(nsoil_PEM),re(nsoil_PEM)
64      real :: Tcol_saved(nsoil_PEM)
65      real :: tsoil_prev(nsoil_PEM)
66      real :: tsurf_prev
67      real :: icedepth_prev
68
69    real :: m_h2o = 18.01528E-3
70    real :: m_co2 = 44.01E-3 
71    real :: m_noco2 = 33.37E-3 
72    real :: A,B,z1,z2
73    real :: alpha = -6143.7
74    real :: beta = 29.9074
75   
76    real,allocatable :: mass_mean(:)                            ! mean mass above the surface
77    real,allocatable :: zplev(:)                           ! pressure above the surface
78    real,allocatable :: pvapor(:)                               ! partial pressure above the surface
79   
80    real,allocatable :: rhovapor(:)
81    real :: rhovapor_avg                          ! mean vapor_density at the surface yearly averaged
82
83    real :: psv_surf
84    real,allocatable :: rho_soil(:)            ! water vapor in the soil
85    real,allocatable :: rho_soil_avg(:)                ! water vapor in the soil yearly averaged
86
87    real,allocatable :: diff_rho(:)                    ! difference of vapor content
88
89    A =(1/m_co2 - 1/m_noco2)
90    B=1/m_noco2
91
92    ice_table(:) = 1.
93    do ig = 1,ngrid
94      error_depth = 1.
95      countloop = 0
96   
97      do while(( error_depth.gt.tol_error).and.(countloop.lt.countmax).and.(ice_table(ig).gt.-1e-20))
98   
99        countloop = countloop +1
100        Tcol_saved(:) = tsoil_ave(ig,:)
101
102!2.  Compute ice table
103
104! 2.1 Compute  water density at the surface, yearly averaged
105        allocate(mass_mean(timelen))
106!   1.1 Compute the partial pressure of vapor
107! a. the molecular mass into the column
108       mass_mean(:) = 1/(A*q_co2(ig,:) +B)
109! b. pressure level
110        allocate(zplev(timelen))
111        do it = 1,timelen
112         zplev(it) = ap(1) + bp(1)*ps(ig,it)
113        enddo
114
115! c. Vapor pressure
116        allocate(pvapor(timelen))
117        pvapor(:) = mass_mean(:)/m_h2o*q_h2o(ig,:)*zplev(:)
118        deallocate(zplev)
119        deallocate(mass_mean)
120 
121!  d!  Check if there is frost at the surface and then compute the density
122!    at the surface
123        allocate(rhovapor(timelen))
124
125         do it = 1,timelen
126           psv_surf = exp(alpha/tsurf_inst(ig,it) +beta)
127           rhovapor(it) = min(psv_surf,pvapor(it))/tsurf_inst(ig,it)
128         enddo
129        deallocate(pvapor)
130        rhovapor_avg =SUM(rhovapor(:),1)/timelen                     
131        deallocate(rhovapor)
132
133! 2.2 Compute  water density at the soil layer, yearly averaged
134
135        allocate(rho_soil(timelen))
136        allocate(rho_soil_avg(nsoil_PEM))
137
138        do isoil = 1,nsoil_PEM
139          do it = 1,timelen
140            rho_soil(it) = exp(alpha/tsoil_inst(ig,isoil,it) +beta)/tsoil_inst(ig,isoil,it)       
141          enddo
142         rho_soil_avg(isoil) = SUM(rho_soil(:),1)/timelen     
143        enddo
144        deallocate(rho_soil)
145         
146!2.3 Final: compute ice table
147        icedepth_prev = ice_table(ig)
148        ice_table(ig) = -1
149        allocate(diff_rho(nsoil_PEM))
150        do isoil = 1,nsoil_PEM
151          diff_rho(isoil) = rhovapor_avg -  rho_soil_avg(isoil)
152        enddo
153        deallocate(rho_soil_avg)
154
155        if(diff_rho(1) > 0) then
156          ice_table(ig) = 0.
157        else
158          do isoil = 1,nsoil_PEM -1
159            if((diff_rho(isoil).lt.0).and.(diff_rho(isoil+1).gt.0.)) then
160              z1 = (diff_rho(isoil) - diff_rho(isoil+1))/(layer_PEM(isoil) - layer_PEM(isoil+1))
161              z2 = -layer_PEM(isoil+1)*z1 +  diff_rho(isoil+1)
162              ice_table(ig) = -z2/z1
163              exit
164            endif
165          enddo
166        endif
167   
168        deallocate(diff_rho)
169
170!3. Update Soil Thermal Inertia
171
172        if (ice_table(ig).gt. 0.) then
173          if (ice_table(ig).lt. 1e-10) then
174            do isoil = 1,nsoil_PEM
175              therm_i(ig,isoil)=ice_inertia
176            enddo
177          else
178      ! 4.1 find the index of the mixed layer
179          iref=0 ! initialize iref
180          do k=1,nsoil_PEM ! loop on layers
181            if (ice_table(ig).ge.layer_PEM(k)) then
182              iref=k ! pure regolith layer up to here
183            else
184              ! correct iref was obtained in previous cycle
185            exit
186            endif
187          enddo
188
189      ! 4.2 Build the new ti
190         do isoil=1,iref
191           therm_i(ig,isoil) =inertiedat_PEM(ig,isoil)
192         enddo
193
194         if (iref.lt.nsoil_PEM) then
195           if (iref.ne.0) then
196             ! mixed layer
197             therm_i(ig,iref+1)=sqrt((layer_PEM(iref+1)-layer_PEM(iref))/ &
198              (((ice_table(ig)-layer_PEM(iref))/(inertiedat_PEM(ig,iref)**2))+ &
199                      ((layer_PEM(iref+1)-ice_table(ig))/(ice_inertia**2))))
200           
201           else ! first layer is already a mixed layer
202            ! (ie: take layer(iref=0)=0)
203            therm_i(ig,1)=sqrt((layer_PEM(1))/ &
204                          (((ice_table(ig))/(inertiedat_PEM(ig,1)**2))+ &
205                           ((layer_PEM(1)-ice_table(ig))/(ice_inertia**2))))
206           endif ! of if (iref.ne.0)       
207           ! lower layers of pure ice
208           do isoil=iref+2,nsoil_PEM
209             therm_i(ig,isoil)=ice_inertia
210           enddo
211         endif ! of if (iref.lt.(nsoilmx))
212       endif ! permanent glaciers
213
214       call soil_pem_1D(nsoil_PEM,.true.,therm_i(ig,:),timestep,tsurf_ave(ig),tsoil_ave(ig,:),alph_PEM,beta_PEM)
215       call soil_pem_1D(nsoil_PEM,.false.,therm_i(ig,:),timestep,tsurf_ave(ig),tsoil_ave(ig,:),alph_PEM,beta_PEM)
216
217       do it = 1,timelen
218         tsoil_inst(ig,:,it) = tsoil_inst(ig,:,it) - (Tcol_saved(:) - tsoil_ave(ig,:))
219       enddo
220
221       error_depth = abs(icedepth_prev - ice_table(ig))     
222       endif
223
224     enddo
225
226     error_depth = 1.
227     countloop = 0
228   enddo
229 
230      END SUBROUTINE ini_icetable
231      subroutine soil_pem_1D(nsoil,firstcall, &
232               therm_i,                          &
233               timestep,tsurf,tsoil,alph,beta)
234
235      use comsoil_h_PEM, only: layer_PEM, mlayer_PEM,  &
236                           mu_PEM,fluxgeo
237      use comsoil_h,only: volcapa
238      implicit none
239
240!-----------------------------------------------------------------------
241!  Author: LL
242!  Purpose: Compute soil temperature using an implict 1st order scheme
243
244!  Note: depths of layers and mid-layers, soil thermal inertia and
245!        heat capacity are commons in comsoil_PEM.h
246!        A convergence loop is added until equilibrium
247!-----------------------------------------------------------------------
248
249#include "dimensions.h"
250!#include "dimphys.h"
251
252!#include"comsoil.h"
253
254
255!-----------------------------------------------------------------------
256!  arguments
257!  ---------
258!  inputs:
259      integer,intent(in) :: nsoil       ! number of soil layers 
260      logical,intent(in) :: firstcall ! identifier for initialization call
261      real,intent(in) :: therm_i(nsoil) ! thermal inertia
262      real,intent(in) :: timestep           ! time step
263      real,intent(in) :: tsurf   ! surface temperature
264 
265! outputs:
266      real,intent(inout) :: tsoil(nsoil) ! soil (mid-layer) temperature
267      real,intent(inout) :: alph(nsoil-1)
268      real,intent(inout) :: beta(nsoil-1)
269     
270! local variables:
271      integer ik
272      real :: thermdiff_PEM(nsoil-1)
273      real :: mthermdiff_PEM(0:nsoil-1)
274      real :: coefd_PEM(nsoil-1)
275      real :: coefq_PEM(0:nsoil-1)
276
277! 0. Initialisations and preprocessing step
278 if (firstcall) then
279   
280! 0.1 Build mthermdiff_PEM(:), the mid-layer thermal diffusivities
281        do ik=0,nsoil-1
282          mthermdiff_PEM(ik)=therm_i(ik+1)*therm_i(ik+1)/volcapa
283   
284        enddo
285
286! 0.2 Build thermdiff(:), the "interlayer" thermal diffusivities
287        do ik=1,nsoil-1
288      thermdiff_PEM(ik)=((layer_PEM(ik)-mlayer_PEM(ik-1))*mthermdiff_PEM(ik) &
289                     +(mlayer_PEM(ik)-layer_PEM(ik))*mthermdiff_PEM(ik-1))  &
290                         /(mlayer_PEM(ik)-mlayer_PEM(ik-1))
291        enddo
292
293! 0.3 Build coefficients mu_PEM, q_{k+1/2}, d_k, alpha_k and capcal
294      ! mu_PEM
295      mu_PEM=mlayer_PEM(0)/(mlayer_PEM(1)-mlayer_PEM(0))
296
297      ! q_{1/2}
298      coefq_PEM(0)=volcapa*layer_PEM(1)/timestep
299        ! q_{k+1/2}
300        do ik=1,nsoil-1
301          coefq_PEM(ik)=volcapa*(layer_PEM(ik+1)-layer_PEM(ik))                  &
302                      /timestep
303        enddo
304
305        ! d_k
306        do ik=1,nsoil-1
307          coefd_PEM(ik)=thermdiff_PEM(ik)/(mlayer_PEM(ik)-mlayer_PEM(ik-1))
308        enddo
309       
310        ! alph_PEM_{N-1}
311        alph(nsoil-1)=coefd_PEM(nsoil-1)/                        &
312                       (coefq_PEM(nsoil-1)+coefd_PEM(nsoil-1))
313        ! alph_PEM_k
314        do ik=nsoil-2,1,-1
315          alph(ik)=coefd_PEM(ik)/(coefq_PEM(ik)+coefd_PEM(ik+1)*    &
316                                   (1.-alph(ik+1))+coefd_PEM(ik))
317        enddo
318
319endif ! of if (firstcall)
320
321      IF (.not.firstcall) THEN
322!  2. Compute soil temperatures
323! First layer:
324        tsoil(1)=(tsurf+mu_PEM*beta(1)* & 
325                                  thermdiff_PEM(1)/mthermdiff_PEM(0))/ &
326                   (1.+mu_PEM*(1.0-alph(1))*&
327                    thermdiff_PEM(1)/mthermdiff_PEM(0))
328
329! Other layers:
330      do ik=1,nsoil-1
331          tsoil(ik+1)=alph(ik)*tsoil(ik)+beta(ik)
332       enddo
333     
334          ENDIF
335
336!  2. Compute beta_PEM coefficients (preprocessing for next time step)
337! Bottom layer, beta_PEM_{N-1}
338
339        beta(nsoil-1)=coefq_PEM(nsoil-1)*tsoil(nsoil)            &
340                        /(coefq_PEM(nsoil-1)+coefd_PEM(nsoil-1)) &
341                 +  fluxgeo/(coefq_PEM(nsoil-1)+coefd_PEM(nsoil-1))
342! Other layers
343      do ik=nsoil-2,1,-1
344          beta(ik)=(coefq_PEM(ik)*tsoil(ik+1)+           &
345                      coefd_PEM(ik+1)*beta(ik+1))/               &
346                      (coefq_PEM(ik)+coefd_PEM(ik+1)*(1.0-alph(ik+1)) &
347                       +coefd_PEM(ik))
348      enddo
349
350      end
351
352      END MODULE ini_soil_mod     
Note: See TracBrowser for help on using the repository browser.