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

Last change on this file since 3820 was 3809, checked in by jbclement, 3 weeks ago

PEM:

  • Correction to detect whether the stratum below the dust lag is made of ice or not.
  • Correction for the initialization of surface ice and 'h2o_ice_depth' according to the layerings map.
  • Correction to handle flow of glaciers with the layering algorithm.
  • Simplification of "recomp_tend_h2o", making it more robust.
  • Making the removing of a stratum more robust.
  • Plotting the orbital variations over the simulated time in "visu_evol_layering.py".
  • Lowering the value of dust tendency.
  • Addition of "_co2" in the variables name for the CO2 flux correction.

JBC

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