source: trunk/LMDZ.COMMON/libf/evolution/layering_mod.F90 @ 3563

Last change on this file since 3563 was 3553, checked in by jbclement, 3 weeks ago

PEM:
Addition of the shifting of the soil temperature profile to follow the surface evolution due to ice condensation/sublimation + small cleanings/improvements.
JBC

File size: 31.2 KB
Line 
1MODULE layering_mod
2
3!=======================================================================
4! Purpose: Manage layered deposits in the PEM with a linked list data structure
5!
6! Author: JBC
7! Date: 08/03/2024
8!=======================================================================
9
10use glaciers_mod, only: rho_co2ice, rho_h2oice
11
12implicit none
13
14!---- Declarations
15! Numerical parameter
16real, parameter :: eps = epsilon(1.), tol = 1.e2*eps
17integer         :: nb_str_max
18logical         :: layering_algo
19
20! Physical parameters
21real, parameter :: d_dust = 5.78e-2             ! Tendency of dust [kg.m-2.y-1]
22real, parameter :: dry_lag_porosity = 0.5       ! Porosity of dust lag
23real, parameter :: dry_regolith_porosity = 0.45 ! Porosity of regolith
24real, parameter :: co2ice_porosity = 0.3        ! Porosity of CO2 ice
25real, parameter :: h2oice_porosity = 0.3        ! Porosity of H2O ice
26real, parameter :: rho_dust = 2500.             ! Density of dust [kg.m-3]
27real, parameter :: rho_rock = 3200.             ! Density of rock [kg.m-3]
28
29! Lag layer parameters -> see Levrard et al. 2007
30real, parameter :: hmin_lag = 0.5  ! Minimal height of the lag deposit to reduce the sblimation rate
31real, parameter :: fred_subl = 0.1 ! Reduction factor of sublimation rate
32
33! Stratum = node of the linked list
34type :: stratum
35    real                   :: thickness      ! Layer thickness [m]
36    real                   :: top_elevation  ! Layer top_elevation (top height from the surface) [m]
37    real                   :: co2ice_volfrac ! CO2 ice volumetric fraction
38    real                   :: h2oice_volfrac ! H2O ice volumetric fraction
39    real                   :: dust_volfrac   ! Dust volumetric fraction
40    real                   :: air_volfrac    ! Air volumetric fraction inside pores
41    type(stratum), pointer :: up => null()   ! Upper stratum (next node)
42    type(stratum), pointer :: down => null() ! Lower stratum (previous node)
43end type stratum
44
45! Layering = linked list
46type layering
47    integer                :: nb_str = 0       ! Number of strata
48    type(stratum), pointer :: bottom => null() ! First stratum (head of the list)
49    type(stratum), pointer :: top => null()    ! Last stratum (tail of the list)
50end type layering
51
52! Array of pointers to "stratum"
53type ptrarray
54    type(stratum), pointer :: p
55end type ptrarray
56
57!=======================================================================
58contains
59! Procedures to manipulate the data structure:
60!     > print_stratum
61!     > add_stratum
62!     > insert_stratum
63!     > rm_stratum
64!     > get_stratum
65!     > ini_layering
66!     > del_layering
67!     > print_layering
68!     > get_nb_str_max
69!     > stratif2array
70!     > array2stratif
71!     > print_stratif
72! Procedures for the algorithm to evolve the layering:
73!     > make_layering
74!     > subl_co2ice_layering
75!     > subl_h2oice_layering
76!     > lift_dust_lags
77!=======================================================================
78! To display a stratum
79SUBROUTINE print_stratum(this)
80
81implicit none
82
83!---- Arguments
84type(stratum), intent(in) :: this
85
86!---- Code
87write(*,'(a20,es13.6)') 'Thickness      : ', this%thickness
88write(*,'(a20,es13.6)') 'Top elevation  : ', this%top_elevation
89write(*,'(a20,es13.6)') 'CO2 ice (m3/m3): ', this%co2ice_volfrac
90write(*,'(a20,es13.6)') 'H2O ice (m3/m3): ', this%h2oice_volfrac
91write(*,'(a20,es13.6)') 'Dust (m3/m3)   : ', this%dust_volfrac
92write(*,'(a20,es13.6)') 'Air (m3/m3)    : ', this%air_volfrac
93
94END SUBROUTINE print_stratum
95
96!=======================================================================
97! To add a stratum to the top of a layering
98SUBROUTINE add_stratum(this,thickness,top_elevation,co2ice,h2oice,dust,air)
99
100implicit none
101
102!---- Arguments
103type(layering), intent(inout)  :: this
104real, intent(in), optional :: thickness, top_elevation, co2ice, h2oice, dust, air
105
106!---- Local variables
107type(stratum), pointer :: str
108
109!---- Code
110! Creation of the stratum
111allocate(str)
112nullify(str%up,str%down)
113str%thickness = 1.
114str%top_elevation = 1.
115str%co2ice_volfrac = 0.
116str%h2oice_volfrac = 0.
117str%dust_volfrac = 0.
118str%air_volfrac = 1.
119if (present(thickness)) str%thickness = thickness
120if (present(top_elevation)) str%top_elevation = top_elevation
121if (present(co2ice)) str%co2ice_volfrac = co2ice
122if (present(h2oice)) str%h2oice_volfrac = h2oice
123if (present(dust)) str%dust_volfrac = dust
124if (present(air)) str%air_volfrac = air
125
126! Verification of volume fraction
127if (abs(1. - (str%co2ice_volfrac + str%h2oice_volfrac + str%dust_volfrac + str%air_volfrac)) > tol) &
128     error stop 'add_stratum: properties for the new stratum are not possible (sum of volumetric fraction /= 1)!'
129
130! Increment the number of strata
131this%nb_str = this%nb_str + 1
132
133! Add the stratum to the layering
134if (.not. associated(this%bottom)) then ! If it is the very first one
135    this%bottom => str
136    this%top => str
137else
138    str%down => this%top
139    this%top%up => str
140    this%top => str
141endif
142
143END SUBROUTINE add_stratum
144
145!=======================================================================
146! To insert a stratum after another one in a layering
147SUBROUTINE insert_stratum(this,str_prev,thickness,top_elevation,co2ice,h2oice,dust,air)
148
149implicit none
150
151!---- Arguments
152type(layering),         intent(inout) :: this
153type(stratum), pointer, intent(inout) :: str_prev
154real, intent(in), optional :: thickness, top_elevation, co2ice, h2oice, dust, air
155
156!---- Local variables
157type(stratum), pointer :: str, current
158
159!---- Code
160if (.not. associated(str_prev%up)) then ! If str_prev is the top stratum of the layering
161    call add_stratum(this,thickness,top_elevation,co2ice,h2oice,dust,air)
162else
163    ! Creation of the stratum
164    allocate(str)
165    nullify(str%up,str%down)
166    str%thickness = 1.
167    str%top_elevation = 1.
168    str%co2ice_volfrac = 0.
169    str%h2oice_volfrac = 0.
170    str%dust_volfrac = 0.
171    str%air_volfrac = 1.
172    if (present(thickness)) str%thickness = thickness
173    if (present(top_elevation)) str%top_elevation = top_elevation
174    if (present(co2ice)) str%co2ice_volfrac = co2ice
175    if (present(h2oice)) str%h2oice_volfrac = h2oice
176    if (present(dust)) str%dust_volfrac = dust
177    if (present(air)) str%air_volfrac = air
178
179    ! Verification of volume fraction
180    if (abs(1. - (str%co2ice_volfrac + str%h2oice_volfrac + str%dust_volfrac + str%air_volfrac)) > tol) &
181         error stop 'insert_stratum: properties for the new stratum are not possible (sum of volumetric fraction /= 1)!'
182
183    ! Increment the number of strata
184    this%nb_str = this%nb_str + 1
185
186    ! Insert the stratum into the layering at the right place
187    str%down => str_prev
188    str%up => str_prev%up
189    str_prev%up => str
190    str%up%down => str
191
192    ! Correct the value of top_elevation for the upper strata
193    current => str%up
194    do while (associated(current))
195        current%top_elevation = current%down%top_elevation + current%thickness
196        current => current%up
197    enddo
198endif
199
200END SUBROUTINE insert_stratum
201
202!=======================================================================
203! To remove a stratum in a layering
204SUBROUTINE rm_stratum(this,str)
205
206implicit none
207
208!---- Arguments
209type(layering),         intent(inout) :: this
210type(stratum), pointer, intent(inout) :: str
211
212!---- Local variables
213type(stratum), pointer :: new_str
214
215!---- Code
216! Protect the 3 sub-surface strata from removing
217if (str%top_elevation <= 0.) return
218
219! Decrement the number of strata
220this%nb_str = this%nb_str - 1
221
222! Remove the stratum from the layering
223str%down%up => str%up
224if (associated(str%up)) then ! If it is not the last one at the top of the layering
225    str%up%down => str%down
226else
227    this%top => str%down
228endif
229new_str => str%down
230nullify(str%up,str%down)
231deallocate(str)
232nullify(str)
233str => new_str
234
235END SUBROUTINE rm_stratum
236
237!=======================================================================
238! To get a specific stratum in a layering
239FUNCTION get_stratum(lay,i) RESULT(str)
240
241implicit none
242
243!---- Arguments
244type(layering), intent(in) :: lay
245integer,        intent(in) :: i
246type(stratum), pointer     :: str
247
248!---- Local variables
249integer :: k
250
251!---- Code
252if (i < 1 .or. i > lay%nb_str) error stop 'get_stratum: requested number is beyond the number of strata of the layering!'
253k = 1
254str => lay%bottom
255do while (k /= i)
256    str => str%up
257    k = k + 1
258enddo
259
260END FUNCTION get_stratum
261
262!=======================================================================
263! To initialize the layering
264SUBROUTINE ini_layering(this)
265
266implicit none
267
268!---- Arguments
269type(layering), intent(inout) :: this
270
271!---- Code
272! Creation of three strata at the bottom of the layering
273! 1) Dry porous deep regolith
274!call add_stratum(this,18.,-12.,0.,0.,dry_regolith_porosity,1. - dry_regolith_porosity)
275! 2) Ice-cemented regolith (ice table)
276!call add_stratum(this,10.,-2.,0.,1. - dry_regolith_porosity,dry_regolith_porosity,0.)
277! 3) Dry porous regolith
278call add_stratum(this,2.,0.,0.,0.,dry_regolith_porosity,1. - dry_regolith_porosity)
279
280END SUBROUTINE ini_layering
281
282!=======================================================================
283! To delete the entire layering
284SUBROUTINE del_layering(this)
285
286implicit none
287
288!---- Arguments
289type(layering), intent(inout) :: this
290
291!---- Local variables
292type(stratum), pointer :: current, next
293
294!---- Code
295current => this%bottom
296do while (associated(current))
297    next => current%up
298    deallocate(current)
299    nullify(current)
300    current => next
301enddo
302this%nb_str = 0
303
304END SUBROUTINE del_layering
305
306!=======================================================================
307! To display a layering
308SUBROUTINE print_layering(this)
309
310implicit none
311
312!---- Arguments
313type(layering), intent(in) :: this
314
315!---- Local variables
316type(stratum), pointer :: current
317integer                :: i
318
319!---- Code
320current => this%top
321
322i = this%nb_str
323do while (associated(current))
324    write(*,'(a8,i4)') 'Stratum ', i
325    call print_stratum(current)
326    write(*,*)
327    current => current%down
328    i = i - 1
329enddo
330
331END SUBROUTINE print_layering
332
333!=======================================================================
334! To get the maximum number of "stratum" in the stratification (layerings)
335FUNCTION get_nb_str_max(stratif,ngrid,nslope) RESULT(nb_str_max)
336
337implicit none
338
339!---- Arguments
340type(layering), dimension(ngrid,nslope), intent(in) :: stratif
341integer,                                 intent(in) :: ngrid, nslope
342integer :: nb_str_max
343
344!---- Local variables
345integer :: ig, islope
346
347!---- Code
348nb_str_max = 0
349do islope = 1,nslope
350    do ig = 1,ngrid
351        nb_str_max = max(stratif(ig,islope)%nb_str,nb_str_max)
352    enddo
353enddo
354
355END FUNCTION get_nb_str_max
356
357!=======================================================================
358! To convert the stratification data structure (layerings) into an array able to be outputted
359SUBROUTINE stratif2array(stratif,ngrid,nslope,stratif_array)
360
361implicit none
362
363!---- Arguments
364integer,                                 intent(in) :: ngrid, nslope
365type(layering), dimension(ngrid,nslope), intent(in) :: stratif
366real, dimension(:,:,:,:), allocatable, intent(inout) :: stratif_array
367
368!---- Local variables
369type(stratum), pointer :: current
370integer                :: ig, islope, k
371
372!---- Code
373stratif_array = 0.
374do islope = 1,nslope
375    do ig = 1,ngrid
376        current => stratif(ig,islope)%bottom
377        k = 1
378        do while (associated(current))
379            stratif_array(ig,islope,k,1) = current%thickness
380            stratif_array(ig,islope,k,2) = current%top_elevation
381            stratif_array(ig,islope,k,3) = current%co2ice_volfrac
382            stratif_array(ig,islope,k,4) = current%h2oice_volfrac
383            stratif_array(ig,islope,k,5) = current%dust_volfrac
384            stratif_array(ig,islope,k,6) = current%air_volfrac
385            current => current%up
386            k = k + 1
387        enddo
388    enddo
389enddo
390
391END SUBROUTINE stratif2array
392
393!=======================================================================
394! To convert the stratification array into the stratification data structure (layerings)
395SUBROUTINE array2stratif(stratif_array,ngrid,nslope,stratif)
396
397implicit none
398
399!---- Arguments
400integer,                               intent(in) :: ngrid, nslope
401real, dimension(:,:,:,:), allocatable, intent(in) :: stratif_array
402type(layering), dimension(ngrid,nslope), intent(inout) :: stratif
403
404!---- Local variables
405integer :: ig, islope, k
406
407!---- Code
408do islope = 1,nslope
409    do ig = 1,ngrid
410        stratif(ig,islope)%bottom%thickness      = stratif_array(ig,islope,1,1)
411        stratif(ig,islope)%bottom%top_elevation  = stratif_array(ig,islope,1,2)
412        stratif(ig,islope)%bottom%co2ice_volfrac = stratif_array(ig,islope,1,3)
413        stratif(ig,islope)%bottom%h2oice_volfrac = stratif_array(ig,islope,1,4)
414        stratif(ig,islope)%bottom%dust_volfrac   = stratif_array(ig,islope,1,5)
415        stratif(ig,islope)%bottom%air_volfrac    = stratif_array(ig,islope,1,6)
416        do k = 2,size(stratif_array,3)
417            if (all(abs(stratif_array(ig,islope,k,:)) < eps)) exit
418            call add_stratum(stratif(ig,islope),stratif_array(ig,islope,k,1),stratif_array(ig,islope,k,2),stratif_array(ig,islope,k,3),stratif_array(ig,islope,k,4),stratif_array(ig,islope,k,5),stratif_array(ig,islope,k,6))
419        enddo
420    enddo
421enddo
422
423END SUBROUTINE array2stratif
424
425!=======================================================================
426! To display a stratification (layerings)
427SUBROUTINE print_stratif(this,ngrid,nslope)
428
429implicit none
430
431!---- Arguments
432integer,                                 intent(in) :: ngrid, nslope
433type(layering), dimension(ngrid,nslope), intent(in) :: this
434
435!---- Local variables
436integer :: ig, islope
437
438!---- Code
439do ig = 1,ngrid
440    write(*,'(a10,i4)') 'Grid cell ', ig
441    do islope = 1,nslope
442        write(*,'(a13,i1)') 'Slope number ', islope
443        call print_layering(this(ig,islope))
444        write(*,*) '~~~~~~~~~~'
445    enddo
446    write(*,*) '--------------------'
447enddo
448
449END SUBROUTINE print_stratif
450
451!=======================================================================
452! Layering algorithm
453SUBROUTINE make_layering(this,d_co2ice,d_h2oice,d_dust,new_str,zshift_surf,new_lag1,new_lag2,zlag,stopPEM,current1,current2)
454
455implicit none
456
457!---- Arguments
458! Inputs
459real, intent(in) :: d_co2ice, d_h2oice, d_dust
460
461! Outputs
462type(layering),         intent(inout) :: this
463type(stratum), pointer, intent(inout) :: current1, current2
464logical,                intent(inout) :: new_str, new_lag1, new_lag2
465integer,                intent(inout) :: stopPEM
466real, intent(out) :: zshift_surf, zlag
467
468!---- Local variables
469real                   :: dh_co2ice, dh_h2oice, dh_dust
470real                   :: h_co2ice_old, h_h2oice_old, h_dust_old
471real                   :: thickness, h2subl, h2subl_tot, h2lift, h2lift_tot
472real                   :: h_toplag
473type(stratum), pointer :: currentloc
474
475!---- Code
476dh_co2ice = d_co2ice/rho_co2ice
477dh_h2oice = d_h2oice/rho_h2oice
478dh_dust = d_dust/rho_dust
479zshift_surf = 0.
480zlag = 0.
481
482if (dh_dust < 0.) then ! Dust lifting only
483    if (abs(dh_co2ice) > eps .or. abs(dh_h2oice) > eps) error stop 'Situation not managed: dust lifting + CO2/H2O ice condensation/sublimation!'
484    write(*,'(a)') ' Stratification -> Dust lifting'
485    h2lift_tot = abs(dh_dust)
486    do while (h2lift_tot > 0. .and. associated(current1))
487        ! Is the considered stratum a dust lag?
488        if (abs(1. - (current1%dust_volfrac + current1%air_volfrac)) < tol) then ! Yes, we can lift dust
489            h_dust_old = current1%dust_volfrac*current1%thickness
490            ! How much dust can be lifted in the considered dust lag?
491            if (h2lift_tot - h_dust_old <= eps) then ! There is enough to lift
492                h2lift = h2lift_tot
493                h2lift_tot = 0.
494                call lift_dust_lags(this,current1,h2lift)
495            else ! Only a fraction can be lifted and so we move to the underlying stratum
496                h2lift = h_dust_old
497                h2lift_tot = h2lift_tot - h2lift
498                call lift_dust_lags(this,current1,h2lift)
499                current1 => current1%down
500            endif
501        else ! No, we stop
502            write(*,'(a)') ' Stratification -> Dust lifting: no dust lag!'
503            stopPEM = 8
504            exit
505        endif
506    enddo
507    if (h2lift_tot > 0.) then
508        write(*,'(a)') ' Stratification -> Not enough dust in the lag layers to complete the lifting!'
509        stopPEM = 8
510    endif
511    zshift_surf = dh_dust + h2lift_tot
512
513else
514
515!------ Dust sedimentation only
516    if (abs(dh_co2ice) < eps .and. abs(dh_h2oice) < eps) then
517        write(*,'(a)') ' Stratification -> Dust sedimentation'
518        ! New stratum at the layering top by sedimentation of dust
519        thickness = dh_dust/(1. - dry_regolith_porosity)
520        if (thickness > 0.) then ! Only if the stratum is building up
521             if (new_str) then
522                 call add_stratum(this,thickness,this%top%top_elevation + thickness,0.,0.,dh_dust/thickness,dry_regolith_porosity)
523                 new_str = .false.
524             else
525                 this%top%thickness = this%top%thickness + thickness
526                 this%top%top_elevation = this%top%top_elevation + thickness
527             endif
528        endif
529        zshift_surf = thickness
530
531!------ Condensation of CO2 ice + H2O ice
532    else if ((dh_co2ice >= 0. .and. dh_h2oice > 0.) .or. (dh_co2ice > 0. .and. dh_h2oice >= 0.)) then
533        write(*,'(a)') ' Stratification -> CO2 and H2O ice condensation'
534        ! New stratum at the layering top by condensation of CO2 and H2O ice
535        thickness = dh_co2ice/(1. - co2ice_porosity) + dh_h2oice/(1. - h2oice_porosity) + dh_dust
536        if (thickness > 0.) then ! Only if the stratum is building up
537             if (new_str) then
538                 call add_stratum(this,thickness,this%top%top_elevation + thickness,dh_co2ice/thickness,dh_h2oice/thickness,dh_dust/thickness,1. - (dh_co2ice/thickness + dh_h2oice/thickness + dh_dust/thickness))
539                 new_str = .false.
540             else
541                 this%top%thickness = this%top%thickness + thickness
542                 this%top%top_elevation = this%top%top_elevation + thickness
543             endif
544        endif
545        zshift_surf = thickness
546
547!------ Sublimation of CO2 ice + Condensation of H2O ice
548    else if (dh_co2ice < 0. .and. dh_h2oice > 0.) then
549        write(*,'(a)') ' Stratification -> Sublimation of CO2 ice + Condensation of H2O ice'
550        ! CO2 ice sublimation in the considered stratum + New stratum for dust lag
551        h2subl_tot = abs(dh_co2ice)
552        do while (h2subl_tot > 0. .and. associated(current1))
553            h_co2ice_old = current1%co2ice_volfrac*current1%thickness
554            h_h2oice_old = current1%h2oice_volfrac*current1%thickness
555            h_dust_old = current1%dust_volfrac*current1%thickness
556
557            ! How much is CO2 ice sublimation inhibited by the top dust lag?
558            h_toplag = 0.
559            if (associated(current1%up)) then ! If there is an upper stratum
560                currentloc => current1%up
561                do while (abs(1. - (currentloc%dust_volfrac + currentloc%air_volfrac)) < tol)
562                    h_toplag = h_toplag + currentloc%thickness
563                    if (.not. associated(currentloc%up)) exit
564                    currentloc => currentloc%up
565                enddo
566            endif
567            h2subl_tot = h2subl_tot*fred_subl**(h_toplag/hmin_lag)
568
569            ! How much CO2 ice can sublimate in the considered stratum?
570            if (h2subl_tot - h_co2ice_old <= eps) then ! There is enough to sublimate
571                h2subl = h2subl_tot
572                h2subl_tot = 0.
573                call subl_co2ice_layering(this,current1,h2subl,h_co2ice_old,h_h2oice_old,h_dust_old,zshift_surf,new_lag1,zlag)
574            else if (h_co2ice_old < eps) then ! There is nothing to sublimate
575                ! Is the considered stratum a dust lag?
576                if (abs(1. - (current1%dust_volfrac + current1%air_volfrac)) < tol) then ! Yes, we move to the underlying stratum
577                    current1 => current1%down
578                    new_lag1 = .true.
579                else ! No, so we stop here
580                    exit
581                endif
582            else ! Only a fraction can sublimate and so we move to the underlying stratum
583                h2subl = h_co2ice_old
584                h2subl_tot = h2subl_tot - h2subl
585                call subl_co2ice_layering(this,current1,h2subl,h_co2ice_old,h_h2oice_old,h_dust_old,zshift_surf,new_lag1,zlag)
586                current1 => current1%down
587                new_lag1 = .true.
588            endif
589        enddo
590        if (h2subl_tot > 0.) then
591            write(*,'(a)') ' Stratification -> Not enough CO2 ice in the layering to complete the sublimation!'
592            stopPEM = 8
593        endif
594        ! New stratum at the layering top by condensation of H2O ice
595        thickness = dh_h2oice/(1. - h2oice_porosity) + dh_dust
596        if (thickness > 0.) then ! Only if the stratum is building up
597             if (new_str) then
598                 call add_stratum(this,thickness,this%top%top_elevation + thickness,0.,dh_h2oice/thickness,dh_dust/thickness,1. - (dh_h2oice/thickness + dh_dust/thickness))
599                 new_str = .false.
600             else
601                 this%top%thickness = this%top%thickness + thickness
602                 this%top%top_elevation = this%top%top_elevation + thickness
603             endif
604        endif
605        zshift_surf = zshift_surf + thickness
606
607!------ Sublimation of CO2 ice + H2O ice
608    else if ((dh_co2ice <= 0. .and. dh_h2oice < 0.) .or. (dh_co2ice < 0. .and. dh_h2oice <= 0.)) then
609        write(*,'(a)') ' Stratification -> Sublimation of CO2 and H2O ice'
610        ! CO2 ice sublimation in the considered stratum + New stratum for dust lag
611        h2subl_tot = abs(dh_co2ice)
612        do while (h2subl_tot > 0. .and. associated(current1))
613            h_co2ice_old = current1%co2ice_volfrac*current1%thickness
614            h_h2oice_old = current1%h2oice_volfrac*current1%thickness
615            h_dust_old = current1%dust_volfrac*current1%thickness
616
617            ! How much is CO2 ice sublimation inhibited by the top dust lag?
618            h_toplag = 0.
619            if (associated(current1%up)) then ! If there is an upper stratum
620                currentloc => current1%up
621                do while (abs(1. - (currentloc%dust_volfrac + currentloc%air_volfrac)) < tol)
622                    h_toplag = h_toplag + currentloc%thickness
623                    if (.not. associated(currentloc%up)) exit
624                    currentloc => currentloc%up
625                enddo
626            endif
627            h2subl_tot = h2subl_tot*fred_subl**(h_toplag/hmin_lag)
628
629            ! How much CO2 ice can sublimate in the considered stratum?
630            if (h2subl_tot - h_co2ice_old <= eps) then ! There is enough to sublimate
631                h2subl = h2subl_tot
632                h2subl_tot = 0.
633                call subl_co2ice_layering(this,current1,h2subl,h_co2ice_old,h_h2oice_old,h_dust_old,zshift_surf,new_lag1,zlag)
634            else if (h_co2ice_old < eps) then ! There is nothing to sublimate
635                ! Is the considered stratum a dust lag?
636                if (abs(1. - (current1%dust_volfrac + current1%air_volfrac)) < tol) then ! Yes, we move to the underlying stratum
637                    current1 => current1%down
638                    new_lag1 = .true.
639                else ! No, so we stop here
640                    exit
641                endif
642            else ! Only a fraction can sublimate and so we move to the underlying stratum
643                h2subl = h_co2ice_old
644                h2subl_tot = h2subl_tot - h2subl
645                call subl_co2ice_layering(this,current1,h2subl,h_co2ice_old,h_h2oice_old,h_dust_old,zshift_surf,new_lag1,zlag)
646                current1 => current1%down
647                new_lag1 = .true.
648            endif
649        enddo
650        if (h2subl_tot > 0.) then
651            write(*,'(a)') ' Stratification -> Not enough CO2 ice in the layering to complete the sublimation!'
652            stopPEM = 8
653        endif
654        ! H2O ice sublimation in the considered stratum + New stratum for dust lag
655        h2subl_tot = abs(dh_h2oice)
656        do while (h2subl_tot > 0. .and. associated(current2))
657            h_co2ice_old = current2%co2ice_volfrac*current2%thickness
658            h_h2oice_old = current2%h2oice_volfrac*current2%thickness
659            h_dust_old = current2%dust_volfrac*current2%thickness
660
661            ! How much is H2O ice sublimation inhibited by the top dust lag?
662            h_toplag = 0.
663            if (associated(current2%up)) then ! If there is an upper stratum
664                currentloc => current2%up
665                do while (abs(1. - (currentloc%dust_volfrac + currentloc%air_volfrac)) < tol)
666                    h_toplag = h_toplag + currentloc%thickness
667                    if (.not. associated(currentloc%up)) exit
668                    currentloc => currentloc%up
669                enddo
670            endif
671            h2subl_tot = h2subl_tot*fred_subl**(h_toplag/hmin_lag)
672
673            ! How much H2O ice can sublimate in the considered stratum?
674            if (h2subl_tot - h_h2oice_old <= eps) then ! There is enough to sublimate
675                h2subl = h2subl_tot
676                h2subl_tot = 0.
677                call subl_h2oice_layering(this,current2,h2subl,h_co2ice_old,h_h2oice_old,h_dust_old,zshift_surf,new_lag2,zlag)
678            else if (h_h2oice_old < eps) then ! There is nothing to sublimate
679                ! Is the considered stratum a dust lag?
680                if (abs(1. - (current1%dust_volfrac + current1%air_volfrac)) < tol) then ! Yes, we move to the underlying stratum
681                    current1 => current1%down
682                    new_lag1 = .true.
683                else ! No, so we stop here
684                    exit
685                endif
686            else ! Only a fraction can sublimate and so we move to the underlying stratum
687                h2subl = h_h2oice_old
688                h2subl_tot = h2subl_tot - h2subl
689                call subl_h2oice_layering(this,current2,h2subl,h_co2ice_old,h_h2oice_old,h_dust_old,zshift_surf,new_lag2,zlag)
690                current2 => current2%down
691                new_lag2 = .true.
692            endif
693        enddo
694        if (h2subl_tot > 0.) then
695            write(*,'(a)') ' Stratification -> Not enough H2O ice in the layering to complete the sublimation!'
696            stopPEM = 8
697        endif
698
699!------ Condensation of CO2 ice + Sublimation of H2O ice
700    else if (dh_co2ice > 0. .and. dh_h2oice < 0.) then
701        error stop 'Impossible situation: CO2 ice condensation + H2O ice sublimation!'
702    endif
703endif
704
705END SUBROUTINE make_layering
706
707!=======================================================================
708! To sublimate CO2 ice in the layering
709SUBROUTINE subl_co2ice_layering(this,str,h2subl,h_co2ice_old,h_h2oice_old,h_dust_old,zshift_surf,new_lag,zlag)
710
711implicit none
712
713!---- Arguments
714type(layering),         intent(inout) :: this
715type(stratum), pointer, intent(inout) :: str
716logical,                intent(inout) :: new_lag
717real,                   intent(inout) :: zshift_surf, zlag
718real, intent(in) :: h2subl, h_co2ice_old, h_h2oice_old, h_dust_old
719
720!---- Local variables
721real                   :: r_subl, hsubl_dust, h_lag
722type(stratum), pointer :: current
723
724!---- Code
725! How much dust does CO2 ice sublimation involve to create the lag?
726r_subl = h2subl/(1. - co2ice_porosity) &
727        /(str%thickness*(str%co2ice_volfrac/(1. - co2ice_porosity) + str%h2oice_volfrac/(1. - h2oice_porosity)))
728hsubl_dust = r_subl*str%dust_volfrac*str%thickness
729
730str%thickness = str%thickness - h2subl/(1. - co2ice_porosity) - hsubl_dust
731zshift_surf = zshift_surf - h2subl/(1. - co2ice_porosity) - hsubl_dust
732if (str%thickness < tol) then
733    ! Remove the sublimating stratum if there is no ice anymore
734    call rm_stratum(this,str)
735else
736    ! Update of properties in the sublimating stratum
737    str%top_elevation = str%top_elevation - h2subl/(1. - co2ice_porosity) - hsubl_dust
738    str%co2ice_volfrac = (h_co2ice_old - h2subl)/str%thickness
739    str%h2oice_volfrac = h_h2oice_old/str%thickness
740    str%dust_volfrac = (h_dust_old - hsubl_dust)/str%thickness
741    str%air_volfrac = 1. - (str%co2ice_volfrac + str%h2oice_volfrac + str%dust_volfrac)
742    ! Correct the value of top_elevation for the upper strata
743    current => str%up
744    do while (associated(current))
745        current%top_elevation = current%down%top_elevation + current%thickness
746        current => current%up
747    enddo
748endif
749
750! New stratum = dust lag
751h_lag = hsubl_dust/(1. - dry_lag_porosity)
752if (h_lag > 0.) then ! Only if the dust lag is building up
753    if (new_lag) then
754        call insert_stratum(this,str,h_lag,str%top_elevation + h_lag,0.,0.,1. - dry_lag_porosity,dry_lag_porosity)
755        new_lag = .false.
756    else
757        str%up%thickness = str%up%thickness + h_lag
758        str%up%top_elevation = str%up%top_elevation + h_lag
759    endif
760endif
761zlag = zlag + h_lag
762
763END SUBROUTINE subl_co2ice_layering
764
765!=======================================================================
766! To sublimate H2O ice in the layering
767SUBROUTINE subl_h2oice_layering(this,str,h2subl,h_co2ice_old,h_h2oice_old,h_dust_old,zshift_surf,new_lag,zlag)
768
769implicit none
770
771!---- Arguments
772type(layering),         intent(inout) :: this
773type(stratum), pointer, intent(inout) :: str
774logical,                intent(inout) :: new_lag
775real,                   intent(inout) :: zshift_surf, zlag
776real, intent(in) :: h2subl, h_co2ice_old, h_h2oice_old, h_dust_old
777
778!---- Local variables
779real                   :: r_subl, hsubl_dust, h_lag
780type(stratum), pointer :: current
781
782!---- Code
783! How much dust does CO2 ice sublimation involve to create the lag?
784r_subl = h2subl/(1. - h2oice_porosity) &
785        /(str%thickness*(str%co2ice_volfrac/(1. - co2ice_porosity) + str%h2oice_volfrac/(1. - h2oice_porosity)))
786hsubl_dust = r_subl*str%dust_volfrac*str%thickness
787
788str%thickness = str%thickness - h2subl/(1. - h2oice_porosity) - hsubl_dust
789zshift_surf = zshift_surf - h2subl/(1. - h2oice_porosity) - hsubl_dust
790if (str%thickness < tol) then
791    ! Remove the sublimating stratum if there is no ice anymore
792    call rm_stratum(this,str)
793else
794    ! Update of properties in the sublimating stratum
795    str%top_elevation = str%top_elevation - h2subl/(1. - h2oice_porosity) - hsubl_dust
796    str%co2ice_volfrac = h_co2ice_old/str%thickness
797    str%h2oice_volfrac = (h_h2oice_old - h2subl)/str%thickness
798    str%dust_volfrac = (h_dust_old - hsubl_dust)/str%thickness
799    str%air_volfrac = 1. - (str%co2ice_volfrac + str%h2oice_volfrac + str%dust_volfrac)
800    ! Correct the value of top_elevation for the upper strata
801    current => str%up
802    do while (associated(current))
803        current%top_elevation = current%down%top_elevation + current%thickness
804        current => current%up
805    enddo
806endif
807
808! New stratum = dust lag
809h_lag = hsubl_dust/(1. - dry_lag_porosity)
810if (h_lag > 0.) then ! Only if the dust lag is building up
811    if (new_lag) then
812        call insert_stratum(this,str,h_lag,str%top_elevation + h_lag,0.,0.,1. - dry_lag_porosity,dry_lag_porosity)
813        new_lag = .false.
814    else
815        str%up%thickness = str%up%thickness + h_lag
816        str%up%top_elevation = str%up%top_elevation + h_lag
817    endif
818endif
819zlag = zlag + h_lag
820
821END SUBROUTINE subl_h2oice_layering
822
823!=======================================================================
824! To lift dust in the layering
825SUBROUTINE lift_dust_lags(this,str,h2lift)
826
827implicit none
828
829!---- Arguments
830type(layering),         intent(inout) :: this
831type(stratum), pointer, intent(inout) :: str
832real, intent(in) :: h2lift
833
834!---- Code
835! Update of properties in the eroding dust lag
836str%thickness = str%thickness - h2lift/(1. - str%air_volfrac)
837str%top_elevation = str%top_elevation - h2lift/(1. - str%air_volfrac)
838! Remove the eroding dust lag if there is no dust anymore
839if (str%thickness < tol) call rm_stratum(this,str)
840
841END SUBROUTINE lift_dust_lags
842
843END MODULE layering_mod
Note: See TracBrowser for help on using the repository browser.