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

Last change on this file since 3791 was 3789, checked in by jbclement, 9 months ago

PEM:
Few corrections for the layering algorithm, in particular when a dust lag layer is created.
JBC

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