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

Last change on this file since 3784 was 3782, checked in by jbclement, 10 months ago

PEM:

  • Correction to identify sublimating ice (surface vs subsurface) at initialization
  • Gathering the processes of "ice condensation" and "dust sedimentation" in the same framework of the layering algorithm
  • Reordering the workflow to manage the different situations of the layering algorithm

JBC

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