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

Last change on this file since 3777 was 3770, checked in by jbclement, 10 months ago

PEM:
Revision of the layering structure and algorithm:

  • 'stratum' components are now expressed in height
  • deletion of the (redundant) thickness feature of 'stratum'
  • 'stratif' in the PEM main program is renamed 'deposits'
  • addition of several procedures to get useful information about a stratum (major component or thickness)
  • all subsurface layers are now represented in the layering structure by strata with negative top elevation
  • simplification of the different situations arising from the input tendencies
  • porosity is determined for the entire stratum (and not anymore for each component) based on dominant component
  • sublimation of CO2 and H2O ice is now handled simultaneously (more realistic) in a stratum
  • linking the layering algorithm with the PEM initilization/finalization regarding PCM data and with the PEM stopping criteria
  • making separate cases for glaciers vs layering management
  • H2O sublimation flux correction is now handled with the layering when a dust lag layer layer is growing
  • update of 'h2o_ice_depth' and 'zdqsdif' accordingly at the PEM end for the PCM

JBC

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