source: trunk/LMDZ.COMMON/libf/evolution/layered_deposits.F90 @ 4138

Last change on this file since 4138 was 4135, checked in by jbclement, 9 days ago

PEM:
Relocate Mars-specific parameters out of "planet" module and into the modules that own their physics domain.
JBC

File size: 48.5 KB
Line 
1MODULE layered_deposits
2!-----------------------------------------------------------------------
3! NAME
4!     layered_deposits
5!
6! DESCRIPTION
7!     Manage layered deposits in the PEM with a linked list data structure.
8!     Provides data types and subroutines to manipulate layers of ice and dust.
9!
10! AUTHORS & DATE
11!     JB Clement, 2024
12!
13! NOTES
14!
15!-----------------------------------------------------------------------
16
17! DEPENDENCIES
18! ------------
19use numerics, only: dp, di, k4, tol
20use geometry, only: ngrid, nslope
21use surf_ice, only: rho_co2ice, rho_h2oice
22
23! DECLARATION
24! -----------
25implicit none
26
27! VARIABLES
28! ---------
29! Numerical parameter
30logical(k4), protected :: do_layering
31
32! Physical parameters
33logical(k4), protected, private :: impose_dust_ratio            ! Impose dust-to-ice ratio instead of dust tendency (see 'dust2ice_ratio')
34real(dp),    protected, private :: dust2ice_ratio               ! Dust-to-ice ratio when ice condenses (10% by default)
35real(dp),    protected, private :: d_dust                       ! Tendency of dust [kg.m-2.y-1]
36real(dp),    parameter, private :: dry_lag_porosity  = 0.2_dp   ! Porosity of dust lag
37real(dp),    parameter, private :: wet_lag_porosity  = 0.15_dp  ! Porosity of water ice lag
38real(dp),    parameter, private :: co2ice_porosity   = 0.05_dp  ! Porosity of CO2 ice
39real(dp),    parameter, private :: h2oice_porosity   = 0.1_dp   ! Porosity of H2O ice
40real(dp),    parameter, private :: rho_dust          = 2500._dp ! Density of dust [kg.m-3]
41real(dp),    parameter, private :: h_patchy_dust     = 5.e-4_dp ! Height under which a dust lag is considered patchy [m]
42real(dp),    parameter, private :: h_patchy_ice      = 5.e-4_dp ! Height under which a H2O ice lag is considered patchy [m]
43
44! Parameters for CO2 flux correction (inspired by Levrard et al. 2007)
45real(dp), parameter, private :: hmin_lag_co2 = 0.5_dp ! Minimal height of the lag deposit to reduce the sublimation rate [m]
46real(dp), parameter, private :: fred_sublco2 = 0.1_dp ! Reduction factor of sublimation rate
47
48! DATA STRUCTURES
49! ---------------
50! Stratum = node of the linked list
51type :: stratum
52    real(dp)               :: top_elevation   ! Layer top_elevation (top height from the surface) [m]
53    real(dp)               :: h_co2ice        ! Height of CO2 ice [m]
54    real(dp)               :: h_h2oice        ! Height of H2O ice [m]
55    real(dp)               :: h_dust          ! Height of dust [m]
56    real(dp)               :: h_pore          ! Height of pores [m]
57    real(dp)               :: poreice_volfrac ! Pore-filled ice volumetric fraction
58    type(stratum), pointer :: up => null()    ! Upper stratum (next node)
59    type(stratum), pointer :: down => null()  ! Lower stratum (previous node)
60end type stratum
61
62! Layering = linked list
63type layering
64    integer(di)            :: nb_str = 0       ! Number of strata
65    type(stratum), pointer :: bottom => null() ! First stratum (head of the list)
66    type(stratum), pointer :: top => null()    ! Last stratum (tail of the list)
67    !real(dp)               :: h_toplag         ! Height of dust layer at the top [m]
68    !type(stratum), pointer :: subice => null() ! Shallower stratum containing ice
69    !type(stratum), pointer :: surf => null()   ! Surface stratum
70end type layering
71
72! Array of pointers to "stratum"
73type ptrarray
74    type(stratum), pointer :: p
75end type ptrarray
76
77contains
78!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
79
80!=======================================================================
81SUBROUTINE set_layered_deposits_config(do_layering_in,impose_dust_ratio_in,d_dust_in,dust2ice_ratio_in)
82!-----------------------------------------------------------------------
83! NAME
84!     set_layered_deposits_config
85!
86! DESCRIPTION
87!     Setter for 'layered_deposits' configuration parameters.
88!
89! AUTHORS & DATE
90!     JB Clement, 02/2026
91!
92! NOTES
93!
94!-----------------------------------------------------------------------
95
96! DEPENDENCIES
97! ------------
98use utility,  only: real2str, bool2str
99use display,  only: print_msg, LVL_NFO
100use stoppage, only: stop_clean
101
102! DECLARATION
103! -----------
104implicit none
105
106! ARGUMENTS
107! ---------
108logical(k4), intent(in) :: do_layering_in, impose_dust_ratio_in
109real(dp),    intent(in) :: d_dust_in, dust2ice_ratio_in
110
111! CODE
112! ----
113do_layering = do_layering_in
114impose_dust_ratio = impose_dust_ratio_in
115d_dust = d_dust_in
116dust2ice_ratio = dust2ice_ratio_in
117call print_msg('do_layering       = '//bool2str(do_layering),LVL_NFO)
118call print_msg('impose_dust_ratio = '//bool2str(impose_dust_ratio),LVL_NFO)
119call print_msg('d_dust            = '//real2str(d_dust),LVL_NFO)
120call print_msg('dust2ice_ratio    = '//real2str(dust2ice_ratio),LVL_NFO)
121if (dust2ice_ratio < 0._dp .or. dust2ice_ratio > 1._dp) call stop_clean(__FILE__,__LINE__,'''dust2ice_ratio'' outside admissible range [0.,1.]!',1)
122
123END SUBROUTINE set_layered_deposits_config
124!=======================================================================
125
126!=======================================================================
127SUBROUTINE print_stratum(this)
128!-----------------------------------------------------------------------
129! NAME
130!     print_stratum
131!
132! DESCRIPTION
133!     Print a stratum.
134!
135! AUTHORS & DATE
136!     JB Clement, 2024
137!
138! NOTES
139!
140!-----------------------------------------------------------------------
141
142! DEPENDENCIES
143! ------------
144use utility, only: real2str
145use display, only: print_msg, LVL_DBG
146
147! DECLARATION
148! -----------
149implicit none
150
151! ARGUMENTS
152! ---------
153type(stratum), intent(in) :: this
154
155! CODE
156! ----
157call print_msg('Top elevation       [m]: '//real2str(this%top_elevation),LVL_DBG)
158call print_msg('Height of CO2 ice   [m]: '//real2str(this%h_co2ice),LVL_DBG)
159call print_msg('Height of H2O ice   [m]: '//real2str(this%h_h2oice),LVL_DBG)
160call print_msg('Height of dust      [m]: '//real2str(this%h_dust),LVL_DBG)
161call print_msg('Height of pores     [m]: '//real2str(this%h_pore),LVL_DBG)
162call print_msg('Pore-filled ice [m3/m3]: '//real2str(this%poreice_volfrac),LVL_DBG)
163
164END SUBROUTINE print_stratum
165!=======================================================================
166
167!=======================================================================
168SUBROUTINE add_stratum(this,top_elevation,co2ice,h2oice,dust,pore,poreice)
169!-----------------------------------------------------------------------
170! NAME
171!     add_stratum
172!
173! DESCRIPTION
174!     Add a stratum to the top of a layering.
175!
176! AUTHORS & DATE
177!     JB Clement, 2024
178!
179! NOTES
180!
181!-----------------------------------------------------------------------
182
183! DECLARATION
184! -----------
185implicit none
186
187! ARGUMENTS
188! ---------
189type(layering), intent(inout)        :: this
190real(dp),       intent(in), optional :: top_elevation, co2ice, h2oice, dust, pore, poreice
191
192! LOCAL VARIABLES
193! ---------------
194type(stratum), pointer :: str
195
196! CODE
197! ----
198! Creation of the stratum
199allocate(str)
200nullify(str%up,str%down)
201str%top_elevation   = 1._dp
202str%h_co2ice        = 0._dp
203str%h_h2oice        = 0._dp
204str%h_dust          = 1._dp
205str%h_pore          = 0._dp
206str%poreice_volfrac = 0._dp
207if (present(top_elevation)) str%top_elevation   = top_elevation
208if (present(co2ice))        str%h_co2ice        = co2ice
209if (present(h2oice))        str%h_h2oice        = h2oice
210if (present(dust))          str%h_dust          = dust
211if (present(pore))          str%h_pore          = pore
212if (present(poreice))       str%poreice_volfrac = poreice
213
214! Increment the number of strata
215this%nb_str = this%nb_str + 1
216
217! Add the stratum to the layering
218if (.not. associated(this%bottom)) then ! If it is the very first one
219    this%bottom => str
220    this%top => str
221else
222    str%down => this%top
223    this%top%up => str
224    this%top => str
225end if
226
227END SUBROUTINE add_stratum
228!=======================================================================
229
230!=======================================================================
231SUBROUTINE insert_stratum(this,str_prev,top_elevation,co2ice,h2oice,dust,pore,poreice)
232!-----------------------------------------------------------------------
233! NAME
234!     insert_stratum
235!
236! DESCRIPTION
237!     Insert a stratum after a given previous stratum in the layering.
238!
239! AUTHORS & DATE
240!     JB Clement, 2024
241!
242! NOTES
243!
244!-----------------------------------------------------------------------
245
246! DECLARATION
247! -----------
248implicit none
249
250! ARGUMENTS
251! ---------
252type(layering),         intent(inout)        ::  this
253type(stratum), pointer, intent(inout)        ::  str_prev
254real(dp),               intent(in), optional :: top_elevation, co2ice, h2oice, dust, pore, poreice
255
256! LOCAL VARIABLES
257! ---------------
258type(stratum), pointer :: str, current
259
260! CODE
261! ----
262if (.not. associated(str_prev%up)) then ! If str_prev is the top stratum of the layering
263    call add_stratum(this,top_elevation,co2ice,h2oice,dust,pore,poreice)
264else
265    ! Creation of the stratum
266    allocate(str)
267    nullify(str%up,str%down)
268    str%top_elevation   = 1._dp
269    str%h_co2ice        = 0._dp
270    str%h_h2oice        = 0._dp
271    str%h_dust          = 1._dp
272    str%h_pore          = 0._dp
273    str%poreice_volfrac = 0._dp
274    if (present(top_elevation)) str%top_elevation   = top_elevation
275    if (present(co2ice))        str%h_co2ice        = co2ice
276    if (present(h2oice))        str%h_h2oice        = h2oice
277    if (present(dust))          str%h_dust          = dust
278    if (present(pore))          str%h_pore          = pore
279    if (present(poreice))       str%poreice_volfrac = poreice
280
281    ! Increment the number of strata
282    this%nb_str = this%nb_str + 1
283
284    ! Insert the stratum into the layering at the right place
285    str%down => str_prev
286    str%up => str_prev%up
287    str_prev%up => str
288    str%up%down => str
289
290    ! Correct the value of top_elevation for the upper strata
291    current => str%up
292    do while (associated(current))
293        current%top_elevation = current%down%top_elevation + thickness(current)
294        current => current%up
295    end do
296end if
297
298END SUBROUTINE insert_stratum
299!=======================================================================
300
301!=======================================================================
302SUBROUTINE del_stratum(this,str)
303!-----------------------------------------------------------------------
304! NAME
305!     del_stratum
306!
307! DESCRIPTION
308!     Delete a stratum from the layering and fix links.
309!
310! AUTHORS & DATE
311!     JB Clement, 2024
312!
313! NOTES
314!
315!-----------------------------------------------------------------------
316
317! DECLARATION
318! -----------
319implicit none
320
321! ARGUMENTS
322! ---------
323type(layering),         intent(inout) :: this
324type(stratum), pointer, intent(inout) :: str
325
326! LOCAL VARIABLES
327! ---------------
328type(stratum), pointer :: new_str
329
330! CODE
331! ----
332! Protect the sub-surface strata from deletion
333if (str%top_elevation <= 0.) return
334
335! Decrement the number of strata
336this%nb_str = this%nb_str - 1
337
338! Making the new links
339if (associated(str%down)) then ! If there is a lower stratum
340    str%down%up => str%up
341else ! If it was the first stratum (bottom of layering)
342    this%bottom => str%up
343end if
344if (associated(str%up)) then ! If there is an upper stratum
345    str%up%down => str%down
346else ! If it was the last stratum (top of layering)
347    this%top => str%down
348end if
349
350! Remove the stratum from the layering
351new_str => str%down
352nullify(str%up,str%down)
353deallocate(str)
354nullify(str)
355str => new_str
356
357END SUBROUTINE del_stratum
358!=======================================================================
359
360!=======================================================================
361FUNCTION get_stratum(lay,i) RESULT(str)
362!-----------------------------------------------------------------------
363! NAME
364!     get_stratum
365!
366! DESCRIPTION
367!     Return the i-th stratum in the layering.
368!
369! AUTHORS & DATE
370!     JB Clement, 2024
371!
372! NOTES
373!
374!-----------------------------------------------------------------------
375
376! DEPENDENCIES
377! ------------
378use stoppage, only: stop_clean
379
380! DECLARATION
381! -----------
382implicit none
383
384! ARGUMENTS
385! ---------
386type(layering), intent(in) :: lay
387integer(di),    intent(in) :: i
388type(stratum), pointer     :: str
389
390! LOCAL VARIABLES
391! ---------------
392integer(di) :: k
393
394! CODE
395! ----
396if (i < 1 .or. i > lay%nb_str) call stop_clean(__FILE__,__LINE__,'requested number is beyond the number of strata of the layering!',1)
397k = 1
398str => lay%bottom
399do while (k /= i)
400    str => str%up
401    k = k + 1
402end do
403
404END FUNCTION get_stratum
405!=======================================================================
406
407!=======================================================================
408SUBROUTINE ini_layering(this)
409!-----------------------------------------------------------------------
410! NAME
411!     del_layering
412!
413! DESCRIPTION
414!     Initialize the layering base structure.
415!
416! AUTHORS & DATE
417!     JB Clement, 2024
418!
419! NOTES
420!
421!-----------------------------------------------------------------------
422
423! DEPENDENCIES
424! ------------
425use soil,     only: do_soil, layer, index_breccia, index_bedrock, regolith_porosity, breccia_porosity
426use geometry, only: nsoil
427
428! DECLARATION
429! -----------
430implicit none
431
432! ARGUMENTS
433! ---------
434type(layering), intent(inout) :: this
435
436! LOCAL VARIABLES
437! ---------------
438integer(di) :: i
439real(dp)    :: h_soil, h_pore, h_tot
440
441! CODE
442! ----
443! Creation of strata at the bottom of the layering to describe the sub-surface
444if (do_soil) then
445    do i = nsoil,index_bedrock,-1
446        h_soil = layer(i) - layer(i - 1) ! No porosity
447        call add_stratum(this,-layer(i - 1),0._dp,0._dp,h_soil,0._dp,0._dp)
448    end do
449    do i = index_bedrock - 1,index_breccia,-1
450        h_tot = layer(i) - layer(i - 1)
451        h_pore = h_tot*breccia_porosity
452        h_soil = h_tot - h_pore
453        call add_stratum(this,-layer(i - 1),0._dp,0._dp,h_soil,h_pore,0._dp)
454    end do
455    do i = index_breccia - 1,2,-1
456        h_tot = layer(i) - layer(i - 1)
457        h_pore = h_tot*regolith_porosity
458        h_soil = h_tot - h_pore
459        call add_stratum(this,-layer(i - 1),0._dp,0._dp,h_soil,h_pore,0._dp)
460    end do
461    h_pore = layer(1)*regolith_porosity
462    h_soil = layer(1) - h_pore
463    call add_stratum(this,0._dp,0._dp,0._dp,h_soil,h_pore,0._dp)
464end if
465
466END SUBROUTINE ini_layering
467!=======================================================================
468
469!=======================================================================
470SUBROUTINE del_layering(this)
471!-----------------------------------------------------------------------
472! NAME
473!     del_layering
474!
475! DESCRIPTION
476!     Delete all strata in a layering and reset counters.
477!
478! AUTHORS & DATE
479!     JB Clement, 2024
480!
481! NOTES
482!
483!-----------------------------------------------------------------------
484
485! DECLARATION
486! -----------
487implicit none
488
489! ARGUMENTS
490! ---------
491type(layering), intent(inout) :: this
492
493! LOCAL VARIABLES
494! ---------------
495type(stratum), pointer :: current, next
496
497! CODE
498! ----
499current => this%bottom
500do while (associated(current))
501    next => current%up
502    deallocate(current)
503    nullify(current)
504    current => next
505end do
506this%nb_str = 0
507
508END SUBROUTINE del_layering
509!=======================================================================
510
511!=======================================================================
512SUBROUTINE print_layering(this)
513!-----------------------------------------------------------------------
514! NAME
515!     print_layering
516!
517! DESCRIPTION
518!     Display all strata from top to bottom for a layering.
519!
520! AUTHORS & DATE
521!     JB Clement, 2024
522!
523! NOTES
524!
525!-----------------------------------------------------------------------
526
527! DEPENDENCIES
528! ------------
529use utility, only: int2str
530use display, only: print_msg, LVL_DBG
531
532! DECLARATION
533! -----------
534implicit none
535
536! ARGUMENTS
537! ---------
538type(layering), intent(in) :: this
539
540! LOCAL VARIABLES
541! ---------------
542type(stratum), pointer :: current
543integer(di)            :: i
544
545! CODE
546! ----
547current => this%top
548
549i = this%nb_str
550do while (associated(current))
551    call print_msg('Stratum '//int2str(i),LVL_DBG)
552    call print_stratum(current)
553    call print_msg('',LVL_DBG)
554    current => current%down
555    i = i - 1
556end do
557
558END SUBROUTINE print_layering
559!=======================================================================
560
561!=======================================================================
562FUNCTION get_nb_str_max(layerings_map) RESULT(nb_str_max)
563!-----------------------------------------------------------------------
564! NAME
565!     get_nb_str_max
566!
567! DESCRIPTION
568!     Return the maximum number of strata across all grid/slope layerings.
569!
570! AUTHORS & DATE
571!     JB Clement, 2024
572!
573! NOTES
574!
575!-----------------------------------------------------------------------
576
577! DEPENDENCIES
578! ------------
579use geometry, only: ngrid, nslope
580
581! DECLARATION
582! -----------
583implicit none
584
585! ARGUMENTS
586! ---------
587type(layering), dimension(:,:), intent(in) :: layerings_map
588integer(di)                                :: nb_str_max
589
590! LOCAL VARIABLES
591! ---------------
592integer(di) :: ig, islope
593
594! CODE
595! ----
596nb_str_max = 0
597do islope = 1,nslope
598    do ig = 1,ngrid
599        nb_str_max = max(layerings_map(ig,islope)%nb_str,nb_str_max)
600    end do
601end do
602
603END FUNCTION get_nb_str_max
604!=======================================================================
605
606!=======================================================================
607SUBROUTINE map2array(layerings_map,layerings_array)
608!-----------------------------------------------------------------------
609! NAME
610!     map2array
611!
612! DESCRIPTION
613!     Convert the layerings map into an allocatable array for output.
614!
615! AUTHORS & DATE
616!     JB Clement, 2024
617!
618! NOTES
619!
620!-----------------------------------------------------------------------
621
622! DEPENDENCIES
623! ------------
624use geometry, only: ngrid, nslope
625
626! DECLARATION
627! -----------
628implicit none
629
630! ARGUMENTS
631! ---------
632type(layering), dimension(:,:),     intent(in)  :: layerings_map
633real(dp),       dimension(:,:,:,:), intent(out) :: layerings_array
634
635! LOCAL VARIABLES
636! ---------------
637type(stratum), pointer :: current
638integer(di)            :: ig, islope, k
639
640! CODE
641! ----
642layerings_array = 0.
643do islope = 1,nslope
644    do ig = 1,ngrid
645        current => layerings_map(ig,islope)%bottom
646        k = 1
647        do while (associated(current))
648            layerings_array(ig,islope,k,1) = current%top_elevation
649            layerings_array(ig,islope,k,2) = current%h_co2ice
650            layerings_array(ig,islope,k,3) = current%h_h2oice
651            layerings_array(ig,islope,k,4) = current%h_dust
652            layerings_array(ig,islope,k,5) = current%h_pore
653            layerings_array(ig,islope,k,6) = current%poreice_volfrac
654            current => current%up
655            k = k + 1
656        end do
657    end do
658end do
659
660END SUBROUTINE map2array
661!=======================================================================
662
663!=======================================================================
664SUBROUTINE array2map(layerings_array,layerings_map)
665!-----------------------------------------------------------------------
666! NAME
667!     array2map
668!
669! DESCRIPTION
670!     Convert the stratification array back into the layerings map.
671!
672! AUTHORS & DATE
673!     JB Clement, 2024
674!
675! NOTES
676!
677!-----------------------------------------------------------------------
678
679! DEPENDENCIES
680! ------------
681use geometry, only: ngrid, nslope
682
683! DECLARATION
684! -----------
685implicit none
686
687! ARGUMENTS
688! ---------
689real(dp),       dimension(:,:,:,:), intent(in)    :: layerings_array
690type(layering), dimension(:,:),     intent(inout) :: layerings_map
691
692! LOCAL VARIABLES
693! ---------------
694integer(di) :: ig, islope, k
695
696! CODE
697! ----
698do islope = 1,nslope
699    do ig = 1,ngrid
700        do k = 1,size(layerings_array,3)
701            call add_stratum(layerings_map(ig,islope),layerings_array(ig,islope,k,1),layerings_array(ig,islope,k,2),layerings_array(ig,islope,k,3),layerings_array(ig,islope,k,4),layerings_array(ig,islope,k,5),layerings_array(ig,islope,k,6))
702        end do
703    end do
704end do
705
706END SUBROUTINE array2map
707!=======================================================================
708
709!=======================================================================
710SUBROUTINE layering2surfice(layerings_map,h2o_ice,co2_ice,h2oice_depth)
711!-----------------------------------------------------------------------
712! NAME
713!     layering2surfice
714!
715! DESCRIPTION
716!     Convert the layerings map into surface ice arrays.
717!
718! AUTHORS & DATE
719!     JB Clement, 01/2026
720!
721! NOTES
722!
723!-----------------------------------------------------------------------
724
725! DEPENDENCIES
726! ------------
727use geometry, only: ngrid, nslope
728
729! DECLARATION
730! -----------
731implicit none
732
733! ARGUMENTS
734! ---------
735type(layering), dimension(:,:), intent(in)  :: layerings_map
736real(dp),       dimension(:,:), intent(out) :: h2o_ice, co2_ice, h2oice_depth
737
738! LOCAL VARIABLES
739! ---------------
740integer(di) :: ig, islope
741
742! CODE
743! ----
744do ig = 1,ngrid
745    do islope = 1,nslope
746        if (is_co2ice_str(layerings_map(ig,islope)%top)) then
747            co2_ice(ig,islope) = layerings_map(ig,islope)%top%h_co2ice*rho_co2ice
748        else if (is_h2oice_str(layerings_map(ig,islope)%top)) then
749            h2o_ice(ig,islope) = layerings_map(ig,islope)%top%h_h2oice*rho_h2oice
750        else
751            call subsurface_ice_layering(layerings_map(ig,islope),h2oice_depth(ig,islope),h2o_ice(ig,islope),co2_ice(ig,islope))
752        end if
753    end do
754end do
755
756END SUBROUTINE layering2surfice
757!=======================================================================
758
759!=======================================================================
760SUBROUTINE surfice2layering(h2o_ice,co2_ice,layerings_map)
761!-----------------------------------------------------------------------
762! NAME
763!     surfice2layering
764!
765! DESCRIPTION
766!     Convert surface ice arrays into the layerings map.
767!
768! AUTHORS & DATE
769!     JB Clement, 01/2026
770!
771! NOTES
772!
773!-----------------------------------------------------------------------
774
775! DEPENDENCIES
776! ------------
777use geometry, only: ngrid, nslope
778
779! DECLARATION
780! -----------
781implicit none
782
783! ARGUMENTS
784! ---------
785real(dp),       dimension(:,:), intent(in)    :: h2o_ice, co2_ice
786type(layering), dimension(:,:), intent(inout) :: layerings_map
787
788! LOCAL VARIABLES
789! ---------------
790integer(di) :: i, islope
791
792! CODE
793! ----
794do islope = 1,nslope
795    do i = 1,ngrid
796        layerings_map(i,islope)%top%h_h2oice = h2o_ice(i,islope)/rho_h2oice
797        layerings_map(i,islope)%top%h_co2ice = co2_ice(i,islope)/rho_co2ice
798    end do
799end do
800
801END SUBROUTINE surfice2layering
802!=======================================================================
803
804!=======================================================================
805SUBROUTINE print_layerings_map(this)
806!-----------------------------------------------------------------------
807! NAME
808!     print_layerings_map
809!
810! DESCRIPTION
811!     Display the entire layerings map for all grids and slopes.
812!
813! AUTHORS & DATE
814!     JB Clement, 2024
815!
816! NOTES
817!
818!-----------------------------------------------------------------------
819
820! DEPENDENCIES
821! ------------
822use utility, only: int2str
823use display, only: print_msg, LVL_DBG
824
825! DEPENDENCIES
826! ------------
827use geometry, only: ngrid, nslope
828
829! DECLARATION
830! -----------
831implicit none
832
833! ARGUMENTS
834! ---------
835type(layering), dimension(:,:), intent(in) :: this
836
837! LOCAL VARIABLES
838! ---------------
839integer(di) :: ig, islope
840
841! CODE
842! ----
843do ig = 1,ngrid
844    call print_msg('Grid cell '//int2str(ig),LVL_DBG)
845    do islope = 1,nslope
846        call print_msg('Slope number '//int2str(islope),LVL_DBG)
847        call print_layering(this(ig,islope))
848        call print_msg('~~~~~~~~~~',LVL_DBG)
849    end do
850    call print_msg('--------------------',LVL_DBG)
851end do
852
853END SUBROUTINE print_layerings_map
854!=======================================================================
855
856!=======================================================================
857FUNCTION thickness(this) RESULT(h_str)
858!-----------------------------------------------------------------------
859! NAME
860!     thickness
861!
862! DESCRIPTION
863!     Compute the total thickness of a stratum.
864!
865! AUTHORS & DATE
866!     JB Clement, 2024
867!
868! NOTES
869!
870!-----------------------------------------------------------------------
871
872! DECLARATION
873! -----------
874implicit none
875
876! ARGUMENTS
877! ---------
878type(stratum), intent(in) :: this
879
880! LOCAL VARIABLES
881! ---------------
882real(dp) :: h_str
883
884! CODE
885! ----
886h_str = this%h_co2ice + this%h_h2oice + this%h_dust + this%h_pore
887
888END FUNCTION thickness
889!=======================================================================
890
891!=======================================================================
892FUNCTION is_co2ice_str(str) RESULT(co2ice_str)
893!-----------------------------------------------------------------------
894! NAME
895!     is_co2ice_str
896!
897! DESCRIPTION
898!     Check if a stratum can be considered as a CO2 ice layer.
899!
900! AUTHORS & DATE
901!     JB Clement, 2024
902!
903! NOTES
904!
905!-----------------------------------------------------------------------
906
907! DECLARATION
908! -----------
909implicit none
910
911! ARGUMENTS
912! ---------
913type(stratum), intent(in) :: str
914
915! LOCAL VARIABLES
916! ---------------
917logical(k4) :: co2ice_str
918
919! CODE
920! ----
921co2ice_str = .false.
922if (str%h_co2ice > str%h_h2oice .and. str%h_co2ice > str%h_dust) co2ice_str = .true.
923
924END FUNCTION is_co2ice_str
925!=======================================================================
926
927!=======================================================================
928FUNCTION is_h2oice_str(str) RESULT(h2oice_str)
929!-----------------------------------------------------------------------
930! NAME
931!     is_h2oice_str
932!
933! DESCRIPTION
934!     Check if a stratum can be considered as a H2O ice layer.
935!
936! AUTHORS & DATE
937!     JB Clement, 2024
938!
939! NOTES
940!
941!-----------------------------------------------------------------------
942
943! DECLARATION
944! -----------
945implicit none
946
947! ARGUMENTS
948! ---------
949type(stratum), intent(in) :: str
950
951! LOCAL VARIABLES
952! ---------------
953logical(k4) :: h2oice_str
954
955! CODE
956! ----
957h2oice_str = .false.
958if (str%h_h2oice > str%h_co2ice .and. str%h_h2oice > str%h_dust) h2oice_str = .true.
959
960END FUNCTION is_h2oice_str
961!=======================================================================
962
963!=======================================================================
964FUNCTION is_dust_str(str) RESULT(dust_str)
965!-----------------------------------------------------------------------
966! NAME
967!     is_dust_str
968!
969! DESCRIPTION
970!     Check if a stratum can be considered as a dust layer.
971!
972! AUTHORS & DATE
973!     JB Clement, 2024
974!
975! NOTES
976!
977!-----------------------------------------------------------------------
978
979! DECLARATION
980! -----------
981implicit none
982
983! ARGUMENTS
984! ---------
985type(stratum), intent(in) :: str
986
987! LOCAL VARIABLES
988! ---------------
989logical(k4) :: dust_str
990
991! CODE
992! ----
993dust_str = .false.
994if (str%h_dust > str%h_co2ice .and. str%h_dust > str%h_h2oice) dust_str = .true.
995
996END FUNCTION is_dust_str
997!=======================================================================
998
999!=======================================================================
1000FUNCTION is_dust_lag(str) RESULT(dust_lag)
1001!-----------------------------------------------------------------------
1002! NAME
1003!     is_dust_lag
1004!
1005! DESCRIPTION
1006!     Check if a stratum is a dust lag (no ice content).
1007!
1008! AUTHORS & DATE
1009!     JB Clement, 2024
1010!
1011! NOTES
1012!
1013!-----------------------------------------------------------------------
1014
1015! DECLARATION
1016! -----------
1017implicit none
1018
1019! ARGUMENTS
1020! ---------
1021type(stratum), intent(in) :: str
1022
1023! LOCAL VARIABLES
1024! ---------------
1025logical(k4) :: dust_lag
1026
1027! CODE
1028! ----
1029dust_lag = .false.
1030if (str%h_co2ice < tol .and. str%h_h2oice < tol .and. str%poreice_volfrac < tol) dust_lag = .true.
1031
1032END FUNCTION is_dust_lag
1033!=======================================================================
1034
1035!=======================================================================
1036SUBROUTINE subsurface_ice_layering(this,h_toplag,h2o_ice,co2_ice)
1037!-----------------------------------------------------------------------
1038! NAME
1039!     subsurface_ice_layering
1040!
1041! DESCRIPTION
1042!     Get data about possible subsurface ice in a layering.
1043!
1044! AUTHORS & DATE
1045!     JB Clement, 2024
1046!
1047! NOTES
1048!
1049!-----------------------------------------------------------------------
1050
1051! DECLARATION
1052! -----------
1053implicit none
1054
1055! ARGUMENTS
1056! ---------
1057type(layering), intent(in)  :: this
1058real(dp),       intent(out) :: h2o_ice, co2_ice, h_toplag
1059
1060! LOCAL VARIABLES
1061! ---------------
1062type(stratum), pointer :: current
1063
1064! CODE
1065! ----
1066h_toplag = 0._dp
1067h2o_ice = 0._dp
1068co2_ice = 0._dp
1069current => this%top
1070! Is the considered stratum a dust lag?
1071if (.not. is_dust_lag(current)) return
1072do while (is_dust_lag(current))
1073    h_toplag = h_toplag + thickness(current)
1074    if (associated(current%down)) then
1075        current => current%down
1076    else
1077        exit
1078    end if
1079end do
1080
1081if (.not. associated(current%down)) then ! Bottom of the layering -> no ice below
1082    h_toplag = 0._dp
1083    return
1084end if
1085
1086! Is the stratum below the dust lag made of ice?
1087if (current%h_h2oice > 0._dp .and. current%h_h2oice > current%h_co2ice) then ! Yes, there is more H2O ice than CO2 ice
1088    if (h_toplag < h_patchy_dust) then ! But the dust lag is too thin to considered ice as subsurface ice
1089        h_toplag = 0._dp
1090        h2o_ice = current%h_h2oice*rho_h2oice
1091    end if
1092else if (current%h_co2ice > 0._dp .and. current%h_co2ice > current%h_h2oice) then ! No, there is more CO2 ice than H2O ice
1093    h_toplag = 0._dp ! Because it matters only for H2O ice
1094    if (h_toplag < h_patchy_ice) co2_ice = current%h_co2ice*rho_co2ice ! But the dust lag is too thin to considered ice as subsurface ice
1095end if
1096
1097END SUBROUTINE subsurface_ice_layering
1098!=======================================================================
1099
1100!=======================================================================
1101SUBROUTINE lift_dust(this,str,h2lift)
1102!-----------------------------------------------------------------------
1103! NAME
1104!     lift_dust
1105!
1106! DESCRIPTION
1107!     Lift dust in a stratum by wind erosion or other processes.
1108!
1109! AUTHORS & DATE
1110!     JB Clement, 2024
1111!
1112! NOTES
1113!
1114!-----------------------------------------------------------------------
1115
1116! DECLARATION
1117! -----------
1118implicit none
1119
1120! ARGUMENTS
1121! ---------
1122type(layering),         intent(inout) :: this
1123type(stratum), pointer, intent(inout) :: str
1124real(dp),               intent(in)    :: h2lift
1125
1126! CODE
1127! ----
1128! Update of properties in the eroding dust lag
1129str%top_elevation = str%top_elevation - h2lift*(1._dp + str%h_pore/str%h_dust)
1130str%h_pore        = str%h_pore        - h2lift*str%h_pore/str%h_dust
1131str%h_dust        = str%h_dust        - h2lift
1132
1133! Remove the eroding dust lag if there is no dust anymore
1134if (str%h_dust < tol) call del_stratum(this,str)
1135
1136END SUBROUTINE lift_dust
1137!=======================================================================
1138
1139!=======================================================================
1140SUBROUTINE sublimate_ice(this,str,h2subl_co2ice,h2subl_h2oice,new_lag,zlag)
1141!-----------------------------------------------------------------------
1142! NAME
1143!     sublimate_ice
1144!
1145! DESCRIPTION
1146!     Handle ice sublimation in a stratum and create lag layer.
1147!
1148! AUTHORS & DATE
1149!     JB Clement, 2024
1150!
1151! NOTES
1152!
1153!-----------------------------------------------------------------------
1154
1155! DECLARATION
1156! -----------
1157implicit none
1158
1159! ARGUMENTS
1160! ---------
1161type(layering),         intent(inout) :: this
1162type(stratum), pointer, intent(inout) :: str
1163logical(k4),            intent(inout) :: new_lag
1164real(dp),               intent(inout) :: zlag
1165real(dp),               intent(in)    :: h2subl_co2ice, h2subl_h2oice
1166
1167! LOCAL VARIABLES
1168! ---------------
1169real(dp)               :: h2subl, h_ice, h_pore, h_pore_new, h_tot
1170real(dp)               :: hlag_dust, hlag_h2oice
1171type(stratum), pointer :: current
1172
1173! CODE
1174! ----
1175h_ice = str%h_co2ice + str%h_h2oice
1176h_pore = str%h_pore
1177h2subl = h2subl_co2ice + h2subl_h2oice
1178
1179! How much dust and H2O ice does ice sublimation involve to create the lag?
1180hlag_dust = str%h_dust*h2subl/h_ice
1181hlag_h2oice = 0._dp
1182if (h2subl_co2ice > 0._dp .and. h2subl_h2oice < tol) hlag_h2oice = str%h_h2oice*h2subl/h_ice
1183
1184! Update of properties in the sublimating stratum
1185str%top_elevation = str%top_elevation - h2subl*(1._dp + h_pore/h_ice) - hlag_dust - hlag_h2oice
1186str%h_co2ice      = str%h_co2ice      - h2subl_co2ice
1187str%h_h2oice      = str%h_h2oice      - h2subl_h2oice - hlag_h2oice
1188str%h_dust        = str%h_dust        - hlag_dust
1189str%h_pore        = str%h_pore        - h2subl*h_pore/h_ice
1190
1191! Correct the value of top_elevation for the upper strata
1192current => str%up
1193do while (associated(current))
1194    current%top_elevation = current%down%top_elevation + thickness(current)
1195    current => current%up
1196end do
1197
1198! Remove the sublimating stratum if there is no ice anymore
1199if (str%h_co2ice < tol .and. str%h_h2oice < tol) call del_stratum(this,str)
1200
1201! Which porosity is considered?
1202if (hlag_dust >= hlag_h2oice) then
1203    h_pore_new = hlag_dust*dry_lag_porosity/(1._dp - dry_lag_porosity)
1204else
1205    h_pore_new = hlag_h2oice*wet_lag_porosity/(1._dp - wet_lag_porosity)
1206end if
1207h_tot = hlag_dust + hlag_h2oice + h_pore_new
1208
1209! New stratum above the current stratum as a lag layer
1210if (new_lag) then
1211    call insert_stratum(this,str,str%top_elevation + h_tot,0._dp,hlag_h2oice,hlag_dust,h_pore_new,0._dp)
1212    new_lag = .false.
1213else
1214    str%up%top_elevation = str%up%top_elevation + h_tot
1215    str%up%h_h2oice      = str%up%h_h2oice      + hlag_h2oice
1216    str%up%h_dust        = str%up%h_dust        + hlag_dust
1217    str%up%h_pore        = str%up%h_pore        + h_pore_new
1218end if
1219
1220zlag = zlag + h_tot
1221
1222END SUBROUTINE sublimate_ice
1223!=======================================================================
1224
1225!=======================================================================
1226SUBROUTINE evolve_layering(this,d_co2ice,d_h2oice,new_str,zshift_surf,new_lag,zlag,current)
1227!-----------------------------------------------------------------------
1228! NAME
1229!     evolve_layering
1230!
1231! DESCRIPTION
1232!     Main algorithm for layering evolution. Manages ice condensation/sublimation
1233!     and dust sedimentation/lifting. Handles multiple scenarios: building new
1234!     strata from ice/dust, retreating strata from sublimation/lifting, and mixed
1235!     scenarios with CO2 ice sublimation combined with H2O ice condensation.
1236!
1237! AUTHORS & DATE
1238!     JB Clement, 09/2024
1239!
1240! NOTES
1241!     Creates dust lag layers when ice sublimation occurs.
1242!-----------------------------------------------------------------------
1243
1244! DEPENDENCIES
1245! ------------
1246use stoppage, only: stop_clean
1247use utility,  only: real2str
1248use display,  only: print_msg, LVL_ERR
1249use soil,     only: regolith_porosity
1250
1251! DECLARATION
1252! -----------
1253implicit none
1254
1255! ARGUMENTS
1256! ---------
1257type(layering),         intent(inout) ::  this
1258type(stratum), pointer, intent(inout) ::  current
1259real(dp),               intent(inout) ::  d_co2ice, d_h2oice
1260logical(k4),            intent(inout) ::  new_str, new_lag
1261real(dp),               intent(out)   ::  zshift_surf, zlag
1262
1263! LOCAL VARIABLES
1264! ---------------
1265real(dp)               :: dh_co2ice, dh_h2oice, dh_dust, dh_dust_co2, dh_dust_h2o
1266real(dp)               :: h_co2ice_old, h_h2oice_old
1267real(dp)               :: h2subl_co2ice, h2subl_h2oice, h2subl_co2ice_tot, h2subl_h2oice_tot
1268real(dp)               :: h2lift, h2lift_tot, h_pore, h_tot, h_toplag, R_subl
1269logical(k4)            :: unexpected
1270type(stratum), pointer :: currentloc
1271
1272! CODE
1273! ----
1274dh_co2ice = d_co2ice/rho_co2ice
1275dh_h2oice = d_h2oice/rho_h2oice
1276dh_dust = 0._dp
1277if (dh_h2oice > 0._dp) then ! To put a dust sedimentation tendency only when ice is condensing
1278    if (impose_dust_ratio) then
1279        if (dh_co2ice > 0._dp) then
1280            dh_dust = dust2ice_ratio*(dh_h2oice + dh_co2ice)
1281        else
1282            dh_dust = dust2ice_ratio*dh_h2oice
1283        end if
1284    else
1285        dh_dust = d_dust/rho_dust
1286    end if
1287end if
1288zshift_surf = this%top%top_elevation
1289zlag = 0._dp
1290unexpected = .false.
1291
1292!~~~~~~~~~~
1293! NOTHING HAPPENS
1294if (abs(dh_co2ice) < tol .and. abs(dh_h2oice) < tol .and. abs(dh_dust) < tol) then
1295    ! So we do nothing
1296!~~~~~~~~~~
1297! BUILDING A STRATUM (ice condensation and/or dust desimentation)
1298else if (dh_co2ice >= 0._dp .and. dh_h2oice >= 0._dp .and. dh_dust >= 0._dp) then
1299    ! Which porosity is considered?
1300    if (dh_co2ice > dh_h2oice .and. dh_co2ice > dh_dust) then ! CO2 ice is dominant
1301        h_pore = dh_co2ice*co2ice_porosity/(1._dp - co2ice_porosity)
1302    else if (dh_h2oice > dh_co2ice .and. dh_h2oice > dh_dust) then ! H2O ice is dominant
1303        h_pore = dh_h2oice*h2oice_porosity/(1._dp - h2oice_porosity)
1304    else if (dh_dust > dh_co2ice .and. dh_dust > dh_h2oice) then ! Dust is dominant
1305        h_pore = dh_dust*regolith_porosity/(1._dp - regolith_porosity)
1306    else
1307        unexpected = .true.
1308    end if
1309    h_tot = dh_co2ice + dh_h2oice + dh_dust + h_pore
1310    ! New stratum at the top of the layering
1311    if (new_str) then
1312        call add_stratum(this,this%top%top_elevation + h_tot,dh_co2ice,dh_h2oice,dh_dust,h_pore,0._dp)
1313        new_str = .false.
1314    else
1315        this%top%top_elevation = this%top%top_elevation + h_tot
1316        this%top%h_co2ice      = this%top%h_co2ice      + dh_co2ice
1317        this%top%h_h2oice      = this%top%h_h2oice      + dh_h2oice
1318        this%top%h_dust        = this%top%h_dust        + dh_dust
1319        this%top%h_pore        = this%top%h_pore        + h_pore
1320    end if
1321!~~~~~~~~~~
1322 ! RETREATING A STRATUM (ice sublimation and/or dust lifting)
1323else if (dh_co2ice <= 0._dp .and. dh_h2oice <= 0._dp .and. dh_dust <= 0._dp) then
1324        h2subl_co2ice_tot = abs(dh_co2ice)
1325        h2subl_h2oice_tot = abs(dh_h2oice)
1326        h2lift_tot = abs(dh_dust)
1327        do while ((h2subl_co2ice_tot > 0._dp .or. h2subl_h2oice_tot > 0._dp .or. h2lift_tot > 0._dp) .and. associated(current))
1328            h_co2ice_old = current%h_co2ice
1329            h_h2oice_old = current%h_h2oice
1330
1331            ! How much is CO2 ice sublimation inhibited by the top dust lag?
1332            R_subl = 1.
1333            if (associated(current%up)) then ! If there is an upper stratum
1334                h_toplag = 0._dp
1335                currentloc => current%up
1336                do while (is_dust_lag(currentloc) .and. associated(currentloc%up))
1337                    h_toplag = h_toplag + thickness(currentloc)
1338                    currentloc => currentloc%up
1339                end do
1340                if (currentloc%h_h2oice >= h_patchy_ice) then
1341                    R_subl = 0._dp
1342                else if (0._dp < currentloc%h_h2oice .and. currentloc%h_h2oice < h_patchy_ice) then
1343                    h_toplag = h_toplag + thickness(currentloc)
1344                    R_subl = fred_sublco2**(h_toplag/hmin_lag_co2)
1345                else
1346                    R_subl = fred_sublco2**(h_toplag/hmin_lag_co2)
1347                end if
1348            end if
1349           h2subl_co2ice_tot = h2subl_co2ice_tot*R_subl
1350
1351            ! Is there CO2 ice to sublimate?
1352            h2subl_co2ice = 0._dp
1353            if (h_co2ice_old > 0._dp .and. h2subl_co2ice_tot > 0._dp) then
1354                h2subl_co2ice = min(h2subl_co2ice_tot,h_co2ice_old)
1355                h2subl_co2ice_tot = h2subl_co2ice_tot - h2subl_co2ice
1356            end if
1357            ! Is there H2O ice to sublimate?
1358            h2subl_h2oice = 0._dp
1359            if (h_h2oice_old > 0._dp .and. h2subl_h2oice_tot > 0._dp) then
1360                h2subl_h2oice = min(h2subl_h2oice_tot,h_h2oice_old)
1361                h2subl_h2oice_tot = h2subl_h2oice_tot - h2subl_h2oice
1362            end if
1363            ! Ice sublimation
1364            if (h2subl_co2ice > 0._dp .or. h2subl_h2oice > 0._dp) call sublimate_ice(this,current,h2subl_co2ice,h2subl_h2oice,new_lag,zlag)
1365
1366            ! Is there dust to lift?
1367            h2lift = 0._dp
1368            if (is_dust_lag(current) .and. h2lift_tot > 0._dp) then
1369                h2lift = min(h2lift_tot,current%h_dust)
1370                h2lift_tot = h2lift_tot - h2lift
1371                ! Dust lifting
1372                if (h2lift > 0._dp) call lift_dust(this,current,h2lift)
1373            else if (associated(current%up)) then
1374                if (is_dust_lag(current%up) .and. h2lift_tot > 0._dp) then
1375                    h2lift = min(h2lift_tot,current%up%h_dust)
1376                    h2lift_tot = h2lift_tot - h2lift
1377                    ! Dust lifting
1378                    if (h2lift > 0._dp) call lift_dust(this,current%up,h2lift)
1379                end if
1380            end if
1381
1382            ! 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
1383            if ((h2subl_co2ice_tot > 0. .or. h2subl_h2oice_tot > 0._dp .or. h2lift_tot > 0._dp) .and. current%h_co2ice < tol .and. current%h_h2oice < tol .and. current%poreice_volfrac < tol) then
1384                current => current%down
1385                new_lag = .true.
1386            else
1387                exit
1388            end if
1389        end do
1390        if (h2subl_co2ice_tot > 0._dp) dh_co2ice = 0._dp ! No CO2 ice available anymore so the tendency is set to 0
1391        if (h2subl_h2oice_tot > 0._dp) dh_h2oice = 0._dp ! No H2O ice available anymore so the tendency is set to 0
1392        if (h2lift_tot > 0._dp) dh_dust = 0._dp ! No dust available anymore so the tendency is set to 0
1393!~~~~~~~~~~
1394! CO2 ICE SUBLIMATION + H2O ICE CONDENSATION
1395else if (dh_co2ice <= 0._dp .and. dh_h2oice >= 0._dp) then
1396    if (dh_dust >= 0._dp) then
1397        dh_dust_co2 = 0._dp
1398        dh_dust_h2o = dh_dust
1399    else
1400        dh_dust_co2 = dh_dust
1401        dh_dust_h2o = 0._dp
1402    end if
1403    if (abs(dh_co2ice) > dh_h2oice) then ! CO2 ice sublimation is dominant
1404        ! CO2 ICE SUBLIMATION: retreating a stratum
1405        h2subl_co2ice_tot = abs(dh_co2ice)
1406        h2lift_tot = abs(dh_dust_co2)
1407        do while ((h2subl_co2ice_tot > 0._dp .or. h2lift_tot > 0._dp) .and. associated(current))
1408            h_co2ice_old = current%h_co2ice
1409
1410            ! How much is CO2 ice sublimation inhibited by the top dust lag?
1411            R_subl = 1.
1412            if (associated(current%up)) then ! If there is an upper stratum
1413                h_toplag = 0._dp
1414                currentloc => current%up
1415                do while (is_dust_lag(currentloc) .and. associated(currentloc%up))
1416                    h_toplag = h_toplag + thickness(currentloc)
1417                    currentloc => currentloc%up
1418                end do
1419                if (currentloc%h_h2oice >= h_patchy_ice) then
1420                    R_subl = 0._dp
1421                else if (0._dp < currentloc%h_h2oice .and. currentloc%h_h2oice < h_patchy_ice) then
1422                    h_toplag = h_toplag + thickness(currentloc)
1423                    R_subl = fred_sublco2**(h_toplag/hmin_lag_co2)
1424                else
1425                    R_subl = fred_sublco2**(h_toplag/hmin_lag_co2)
1426                end if
1427            end if
1428           h2subl_co2ice_tot = h2subl_co2ice_tot*R_subl
1429
1430            ! Is there CO2 ice to sublimate?
1431            h2subl_co2ice = 0._dp
1432            if (h_co2ice_old > 0._dp .and. h2subl_co2ice_tot > 0._dp) then
1433                h2subl_co2ice = min(h2subl_co2ice_tot,h_co2ice_old)
1434                h2subl_co2ice_tot = h2subl_co2ice_tot - h2subl_co2ice
1435            end if
1436            ! Ice sublimation
1437            if (h2subl_co2ice > 0._dp) call sublimate_ice(this,current,h2subl_co2ice,0._dp,new_lag,zlag)
1438
1439            ! Is there dust to lift?
1440            h2lift = 0._dp
1441            if (is_dust_lag(current) .and. h2lift_tot > 0._dp) then
1442                h2lift = min(h2lift_tot,current%h_dust)
1443                h2lift_tot = h2lift_tot - h2lift
1444                ! Dust lifting
1445                if (h2lift > 0._dp) call lift_dust(this,current,h2lift)
1446            else if (associated(current%up)) then
1447                if (is_dust_lag(current%up) .and. h2lift_tot > 0._dp) then
1448                    h2lift = min(h2lift_tot,current%up%h_dust)
1449                    h2lift_tot = h2lift_tot - h2lift
1450                    ! Dust lifting
1451                    if (h2lift > 0._dp) call lift_dust(this,current%up,h2lift)
1452                end if
1453            end if
1454
1455            ! 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
1456            if ((h2subl_co2ice_tot > 0._dp .or. h2lift_tot > 0._dp) .and. current%h_co2ice < tol) then
1457                current => current%down
1458                new_lag = .true.
1459            else
1460                exit
1461            end if
1462        end do
1463        if (h2subl_co2ice_tot > 0._dp) dh_co2ice = 0._dp ! No CO2 ice available anymore so the tendency is set to 0
1464        if (h2lift_tot > 0._dp) dh_dust = 0._dp ! No dust available anymore so the tendency is set to 0
1465
1466        ! H2O ICE CONDENSATION: building a stratum
1467        h_pore = dh_h2oice*h2oice_porosity/(1._dp - h2oice_porosity)
1468        h_tot = dh_h2oice + dh_dust_h2o + h_pore
1469        ! New stratum at the top of the layering
1470        if (new_str) then
1471            call add_stratum(this,this%top%top_elevation + h_tot,0._dp,dh_h2oice,dh_dust_h2o,h_pore,0._dp)
1472            new_str = .false.
1473        else
1474            this%top%top_elevation = this%top%top_elevation + h_tot
1475            this%top%h_h2oice      = this%top%h_h2oice      + dh_h2oice
1476            this%top%h_dust        = this%top%h_dust        + dh_dust_h2o
1477            this%top%h_pore        = this%top%h_pore        + h_pore
1478        end if
1479    else ! H2O ice condensation is dominant
1480        ! H2O ICE CONDENSATION: building a stratum
1481        h_pore = dh_h2oice*h2oice_porosity/(1._dp - h2oice_porosity)
1482        h_tot = dh_h2oice + dh_dust_h2o + h_pore
1483        ! New stratum at the top of the layering
1484        if (new_str) then
1485            call add_stratum(this,this%top%top_elevation + h_tot,0._dp,dh_h2oice,dh_dust_h2o,h_pore,0._dp)
1486            new_str = .false.
1487        else
1488            this%top%top_elevation = this%top%top_elevation + h_tot
1489            this%top%h_h2oice      = this%top%h_h2oice      + dh_h2oice
1490            this%top%h_dust        = this%top%h_dust        + dh_dust_h2o
1491            this%top%h_pore        = this%top%h_pore        + h_pore
1492        end if
1493
1494        ! CO2 ICE SUBLIMATION: retreating a stratum
1495        h2subl_co2ice_tot = abs(dh_co2ice)
1496        h2lift_tot = abs(dh_dust_co2)
1497        do while ((h2subl_co2ice_tot > 0._dp .or. h2lift_tot > 0._dp) .and. associated(current))
1498            h_co2ice_old = current%h_co2ice
1499
1500            ! How much is CO2 ice sublimation inhibited by the top dust lag?
1501            R_subl = 1._dp
1502            if (associated(current%up)) then ! If there is an upper stratum
1503                h_toplag = 0._dp
1504                currentloc => current%up
1505                do while (is_dust_lag(currentloc) .and. associated(currentloc%up))
1506                    h_toplag = h_toplag + thickness(currentloc)
1507                    currentloc => currentloc%up
1508                end do
1509                if (currentloc%h_h2oice >= h_patchy_ice) then
1510                    R_subl = 0._dp
1511                else if (0._dp < currentloc%h_h2oice .and. currentloc%h_h2oice < h_patchy_ice) then
1512                    h_toplag = h_toplag + thickness(currentloc)
1513                    R_subl = fred_sublco2**(h_toplag/hmin_lag_co2)
1514                else
1515                    R_subl = fred_sublco2**(h_toplag/hmin_lag_co2)
1516                end if
1517            end if
1518           h2subl_co2ice_tot = h2subl_co2ice_tot*R_subl
1519
1520            ! Is there CO2 ice to sublimate?
1521            h2subl_co2ice = 0._dp
1522            if (h_co2ice_old > 0._dp .and. h2subl_co2ice_tot > 0._dp) then
1523                h2subl_co2ice = min(h2subl_co2ice_tot,h_co2ice_old)
1524                h2subl_co2ice_tot = h2subl_co2ice_tot - h2subl_co2ice
1525            end if
1526            ! Ice sublimation
1527            if (h2subl_co2ice > 0._dp) call sublimate_ice(this,current,h2subl_co2ice,0._dp,new_lag,zlag)
1528
1529            ! Is there dust to lift?
1530            h2lift = 0._dp
1531            if (is_dust_lag(current) .and. h2lift_tot > 0._dp) then
1532                h2lift = min(h2lift_tot,current%h_dust)
1533                h2lift_tot = h2lift_tot - h2lift
1534                ! Dust lifting
1535                if (h2lift > 0._dp) call lift_dust(this,current,h2lift)
1536            else if (associated(current%up)) then
1537                if (is_dust_lag(current%up) .and. h2lift_tot > 0.) then
1538                    h2lift = min(h2lift_tot,current%up%h_dust)
1539                    h2lift_tot = h2lift_tot - h2lift
1540                    ! Dust lifting
1541                    if (h2lift > 0.) call lift_dust(this,current%up,h2lift)
1542                end if
1543            end if
1544
1545            ! 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
1546            if ((h2subl_co2ice_tot > 0._dp .or. h2lift_tot > 0._dp) .and. current%h_co2ice < tol) then
1547                current => current%down
1548                new_lag = .true.
1549            else
1550                exit
1551            end if
1552        end do
1553        if (h2subl_co2ice_tot > 0._dp) dh_co2ice = 0._dp ! No CO2 ice available anymore so the tendency is set to 0
1554        if (h2lift_tot > 0._dp) dh_dust = 0._dp ! No dust available anymore so the tendency is set to 0
1555    end if
1556!~~~~~~~~~~
1557! NOT EXPECTED SITUATION
1558else
1559    unexpected = .true.
1560end if
1561
1562if (unexpected) then
1563    call print_msg('    dh_co2ice [m/y] = '//real2str(dh_co2ice),LVL_ERR)
1564    call print_msg('    dh_h2oice [m/y] = '//real2str(dh_h2oice),LVL_ERR)
1565    call print_msg('    dh_dust   [m/y] = '//real2str(dh_dust),LVL_ERR)
1566    call stop_clean(__FILE__,__LINE__,'situation for the layering construction not managed!',1)
1567end if
1568
1569zshift_surf = this%top%top_elevation - zshift_surf
1570
1571END SUBROUTINE evolve_layering
1572!=======================================================================
1573
1574END MODULE layered_deposits
Note: See TracBrowser for help on using the repository browser.