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

Last change on this file since 4134 was 4110, checked in by jbclement, 9 days ago

PEM:

  • Introduction of a configurable display/logging system with options 'out2term', 'out2log', 'verbosity_lvl'. All messages now use verbosity levels ('LVL_NFO', 'LVL_WRN', 'LVL_ERR' and 'LVL_DBG').
  • Code encapsulation improvements with systematic privacy/protection of module variables.
  • Addition of workflow safety checks for required executables, dependencies (e.g. 'ncdump'), input files and callphys keys.
  • Renaming of PEM starting and diagnostic files ("startevol.nc" into "startevo.nc", "diagevol.nc" into "diagevo.nc").

JBC

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