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

Last change on this file was 3821, checked in by jbclement, 6 days ago

PEM:
Addition of the flag 'impose_dust_ratio' (default: .false.) to impose a dust-to-ice ratio instead of a dust tendency for the layering algorithm. The ratio value can be set in the "run_PEM.def" by 'dust_to_ice_ratio' (default: 0.01).
JBC

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