source: trunk/LMDZ.MARS/libf/phymars/soilwater.F90 @ 4029

Last change on this file since 4029 was 4018, checked in by aslmd, 4 months ago

MESOSCALE: no planetwide, no write_output, no future for meeeee

File size: 67.4 KB
Line 
1subroutine soilwater(ngrid, nlayer, nq, nsoil, nqsoil, ptsrf, ptsoil, ptimestep, &
2    exchange, qsat_surf, pq, pa, pb, pc, pd, pdqsdifpot, pqsurf, &
3    pqsoil, pplev, rhoatmo, writeoutput, zdqsdifrego, zq1temp2, saturation_water_ice)
4
5    use comsoil_h, only: igcm_h2o_vap_soil, igcm_h2o_ice_soil, igcm_h2o_vap_ads, layer, mlayer, choice_ads, &
6                         porosity_reg, ads_const_D, ads_massive_ice
7    use comcstfi_h, only: pi, r
8    use tracer_mod, only: igcm_h2o_vap
9    use surfdat_h, only: watercaptag
10    use geometry_mod, only: cell_area, latitude_deg
11#ifndef MESOSCALE
12    use write_output_mod, only: write_output
13#endif
14
15    implicit none
16
17    ! =================================================================================================
18    ! Description:
19    !
20    ! This subroutine calculates the profile of water vapor, adsorbed water and ice in the regolith,
21    ! down to depth(nsoil) ~ 18m. It calculates the flux of water vapor (zdqsdifrego) between the
22    ! subsurface and the atmosphere.
23    !
24    ! Water vapor and adsorbed water are treated as two separate subsurface tracers that are connected
25    ! by adsorption / desorption coefficients, including an adsorption / desorption kinetic factor.
26    !
27    ! The water adsorption isotherm is linear, with a saturation plateau corresponding to one monolayer
28    ! of adsorbed water molecules (i.e. an approximation of a Langmuir-type isotherm). The slope of the
29    ! isotherm is defined by the enthalpy of adsorption (in kJ/mol).
30    ! New since 2020: the adsorption isotherm is now linear by part, to better simulate Type II or Type III
31    ! isotherms (and not only Type I)
32    !
33    ! The linearized adsorption-diffusion equation is solved first, then the water vapor pressure is
34    ! compared to the saturation vapor pressure, and if the latter is reached, ice is formed, the water vapor
35    ! pressure is fixed to its saturation value and the adsorption-diffusion equation is solved again.
36    ! If ice was already present, its sublimation or growth is calculated.
37    !
38    ! This subroutine is called by vdifc.F if the parameters "adsorption_soil" and "water" are set to true in
39    ! callphys.def. It returns the flux of water vapor that is injected into or out of the regolith,
40    ! and which serves as a boundary condition to calculate the vertical atmospheric profile of water vapor
41    ! in vdifc. It also calculates the exchange between the subsurface and surface ice.
42    !
43    ! It requires three subsurface tracers to be defined in traceur.def:
44    !    - h2o_vap_soil (subsurface water vapor)
45    !    - h2o_ice_soil (subsurface ice)
46    !    - h2o_ads_vap  (adsorbed water)
47    !
48    ! Authors: Pierre-Yves Meslin (pmeslin@irap.omp.eu), cleaned by Lucas Lange
49    ! For previous version (with numerous commented lines), see -r 3904
50    ! =================================================================================================
51
52    ! Arguments
53    ! ======================================================================
54
55    ! Inputs
56    integer, intent(in) :: ngrid                    ! number of points in the model (all lat and long point in one 1D array)
57    integer, intent(in) :: nlayer                   ! number of layers
58    integer, intent(in) :: nq                       ! number of tracers
59    integer, intent(in) :: nsoil
60    integer, intent(in) :: nqsoil
61    logical, save :: firstcall_soil = .true.        ! triggers the initialization
62    real, intent(in) :: ptsoil(ngrid, nsoil)        ! subsurface temperatures
63    real, intent(in) :: ptsrf(ngrid)                ! surface temperature
64    real, intent(in) :: ptimestep                   ! length of the timestep (unit depends on run.def file)
65    logical, intent(in) :: exchange(ngrid)          ! logical array describing whether there is exchange with the atmosphere at the current timestep
66
67    real, intent(in) :: qsat_surf(ngrid)            ! saturation mixing ratio at the surface at the current surface temperature (formerly qsat)
68    real, intent(in) :: pq(ngrid, nlayer, nq)       ! tracer atmospheric mixing ratio
69    real, intent(in) :: pa(ngrid, nlayer)           ! coefficients za
70    real, intent(in) :: pb(ngrid, nlayer)           ! coefficients zb
71    real, intent(in) :: pc(ngrid, nlayer)           ! coefficients zc
72    real, intent(in) :: pd(ngrid, nlayer)           ! coefficients zd
73    real, intent(in) :: pdqsdifpot(ngrid)           ! potential pdqsdif (without subsurface-atmosphere exchange)
74
75    real, intent(in) :: pplev(ngrid, nlayer+1)      ! atmospheric pressure levels
76    real, intent(in) :: rhoatmo(ngrid)              ! atmospheric air density (1st layer) (not used right now)
77    logical, intent(in) :: writeoutput              ! check we are at the last subtimestep for output
78
79    ! Variables modified
80    real, intent(inout) :: pqsoil(ngrid, nsoil, nqsoil) ! subsurface tracers (water vapor and ice)
81    real, intent(in) :: pqsurf(ngrid)               ! water ice on the surface
82                                                     ! (in kg.m-3: m-3 of pore air for water vapor and m-3 of regolith for water ice and adsorbed water)
83
84    ! Outputs
85    real, intent(out) :: zdqsdifrego(ngrid)         ! flux from subsurface (positive pointing outwards)
86    real, intent(out) :: zq1temp2(ngrid)            ! temporary atmospheric mixing ratio after exchange with subsurface (kg/kg)
87    real*8, intent(out) :: saturation_water_ice(ngrid, nsoil) ! water pore ice saturation level (formerly Sw)
88
89    ! Outputs for the output files
90    real*8 :: preduite(ngrid, nsoil)                ! how close the water vapor density is to adsorption saturation
91    integer :: exch(ngrid)                          ! translates the logical variable exchange into a -1 or 1
92    real*8 :: mass_h2o(ngrid)                       ! mass of subsurface water column at each point (kg.m-2) (formerly mh2otot)
93    real*8 :: mass_ice(ngrid)                       ! mass of subsurface ice at each point (kg.m-2) (formerly micetot)
94    real*8 :: mass_h2o_tot                          ! mass of subsurface water over the whole planet
95    real*8 :: mass_ice_tot                          ! mass of subsurface ice over the whole planet
96    real*8 :: nsurf(ngrid)                          ! surface tracer density in kg/m^3
97    real*8 :: close_out(ngrid, nsoil)               ! output for close_top and close_bottom
98
99    ! Local (saved) variables
100    ! ======================================================================
101
102    real*8 :: P_sat_soil(ngrid, nsoil)              ! water saturation pressure of subsurface cells (at mid-layers) (formerly Psatsoil)
103    real*8 :: nsatsoil(ngrid, nsoil)                ! gas number density at saturation pressure
104    real*8, allocatable, save :: znsoil(:, :)       ! water vapor soil concentration (kg.m-3 of pore air)
105    real*8 :: znsoilprev(ngrid, nsoil)              ! value of znsoil in the previous timestep
106    real*8 :: znsoilprev2(ngrid, nsoil)             ! second variable for the value of znsoil in the previous timestep
107    real*8 :: zdqsoil(ngrid, nsoil)                 ! increase of pqsoil if sublimation of ice
108    real*8, allocatable, save :: ice(:, :)          ! ice content of subsurface cells (at mid-layers) (kg/m3)
109    real*8 :: iceprev(ngrid, nsoil)
110    logical :: ice_index_flag(nsoil)                ! flag for ice presence
111    real*8, allocatable, save :: adswater(:, :)     ! adsorbed water in subsurface cells (at mid-layers)
112    real*8 :: adswater_temp(ngrid, nsoil)           ! temporary variable for adsorbed water
113    logical, allocatable, save :: over_mono_sat_flag(:, :) ! flag for cells above monolayer saturation
114    real*8 :: adswprev(ngrid, nsoil)
115    logical :: recompute_cell_ads_flag(nsoil)       ! flag to check whether coefficients have changed and need recomputing
116
117    real*8, save :: adswater_sat_mono                ! adsorption monolayer saturation value (kg.m-3 of regolith)
118    real*8 :: delta0(ngrid)                         ! coefficient delta(0) modified
119    real*8 :: alpha0(ngrid)
120    real*8 :: beta0(ngrid)
121
122    ! Adsorption/Desorption variables and parameters
123    real*8 :: Ka(ngrid, nsoil)                      ! adsorption time constant (s-1) before monolayer saturation (first segment of the bilinear function)
124    real*8 :: Kd(ngrid, nsoil)                      ! desorption time constant (s-1) before monolayer saturation (first segment of the bilinear function)
125    real*8 :: k_ads_eq(ngrid, nsoil)                ! equilibrium adsorption coefficient (formerly kads) before monolayer saturation
126    real*8 :: Ka2(ngrid, nsoil)                     ! adsorption time constant (s-1) after monolayer saturation (second segment of the bilinear function)
127    real*8 :: Kd2(ngrid, nsoil)                     ! desorption time constant (s-1) after monolayer saturation (second segment of the bilinear function)
128    real*8 :: k_ads_eq2(ngrid, nsoil)               ! equilibrium adsorption coefficient after monolayer saturation (second segment of the bilinear function)
129    real*8 :: c0(ngrid, nsoil)                      ! intercept of the second line in the bilinear function
130    real*8, parameter :: kinetic_factor = 0.01      ! (inverse of) characteristic time to reach adsorption equilibrium (s-1):
131                                                     ! fixed arbitrarily when kinetics factors are unknown
132
133    real*8, allocatable, save :: ztot1(:, :)        ! total (water vapor + ice) content (kg.m-3 of soil)
134    real*8 :: dztot1(nsoil)
135    real*8 :: h2otot(ngrid, nsoil)                  ! total water content (ice + water vapor + adsorbed water)
136    real*8 :: flux(ngrid, 0:nsoil-1)                ! fluxes at interfaces (kg.m-2.s-1) (positive = upward)
137    real*8 :: rho(ngrid)                            ! air density (first subsurface layer)
138    real*8 :: rhosurf(ngrid)                        ! surface air density
139
140    ! Porosity and tortuosity variables
141    real*8, allocatable, save :: porosity_ice_free(:, :)  ! porosity with no ice present (formerly eps0)
142    real*8, allocatable, save :: porosity(:, :)           ! porosity (formerly eps)
143    real*8 :: porosity_prev(ngrid, nsoil)                 ! porosity from previous timestep
144    real*8, allocatable, save :: tortuosity(:, :)         ! tortuosity factor (formerly tortuo)
145
146    real*8 :: saturation_water_ice_inter(ngrid, nsoil)    ! water pore ice saturation level at the interlayer
147
148    ! Diffusion coefficients
149    real*8 :: D_mid(ngrid, nsoil)                   ! midlayer diffusion coefficients
150    real*8 :: D_inter(ngrid, nsoil)                 ! interlayer diffusion coefficients (formerly D)
151    real*8, allocatable, save :: D0(:, :)           ! diffusion coefficient prefactor
152    real*8 :: omega(ngrid, nsoil)                   ! H2O-CO2 collision integral
153    real*8 :: vth(ngrid, nsoil)                     ! H2O thermal speed
154    real*8, parameter :: Dk0 = 0.459D0              ! Knudsen diffusion coefficient (for saturation_water_ice = 0)
155    real*8 :: Dk(ngrid, nsoil)                      ! Knudsen diffusion coefficient (divided by porosity/tortuosity factor)
156    real*8 :: Dk_inter(ngrid, nsoil)                ! Knudsen diffusion coefficient at the interlayer
157    real*8 :: Dm(ngrid, nsoil)                      ! molecular diffusion coefficient
158    real*8 :: Dm_inter(ngrid, nsoil)                ! molecular diffusion coefficient at the interlayer
159
160    real*8, parameter :: choke_fraction = 0.8D0     ! fraction of ice that prevents further diffusion
161    logical, allocatable, save :: close_top(:, :)   ! closing diffusion at the top of a layer if ice rises over saturation
162    logical, allocatable, save :: close_bottom(:, :) ! closing diffusion at the bottom of a layer if ice rises over saturation
163    logical, parameter :: print_closure_warnings = .true.
164
165    ! Coefficients for the diffusion calculations
166    real*8 :: A(ngrid, nsoil)                       ! coefficient in the diffusion formula
167    real*8 :: B(ngrid, nsoil)                       ! coefficient in the diffusion formula
168    real*8 :: C(ngrid, nsoil)                       ! coefficient in the diffusion formula
169    real*8 :: E(ngrid, nsoil)                       ! coefficient in the diffusion formula (before monolayer saturation)
170    real*8 :: F(ngrid, nsoil)                       ! coefficient in the diffusion formula (before monolayer saturation)
171    real*8 :: E2(ngrid, nsoil)                      ! coefficient in the diffusion formula (after monolayer saturation)
172    real*8 :: F2(ngrid, nsoil)                      ! coefficient in the diffusion formula (after monolayer saturation)
173    real*8, allocatable, save :: zalpha(:, :)       ! alpha coefficients
174    real*8, allocatable, save :: zbeta(:, :)        ! beta coefficients
175    real*8 :: zdelta(ngrid, nsoil-1)                ! delta coefficients
176
177    ! Distances between layers
178    real*8, allocatable, save :: interlayer_dz(:, :)      ! distance between the interlayer points in m (formerly interdz)
179    real*8, allocatable, save :: midlayer_dz(:, :)        ! distance between the midcell points in m (formerly middz)
180
181    real*8 :: nsat(ngrid, nsoil)                    ! amount of water vapor at (adsorption) monolayer saturation
182
183    real*8, allocatable, save :: meshsize(:, :)     ! scaling/dimension factor for the pore size
184    real*8, allocatable, save :: rho_soil(:, :)     ! soil density (bulk - kg/m3) (formerly rhosoil)
185    real*8, allocatable, save :: cste_ads(:, :)     ! prefactor of adsorption coeff. k
186
187    ! General constants
188    real*8, parameter :: kb = 1.38065D-23           ! Boltzmann constant
189    real*8, parameter :: mw = 2.988D-26             ! water molecular weight
190
191    ! Adsorption coefficients
192    real*8, parameter :: enthalpy_ads = 35.D3       ! enthalpy of adsorption (J.mol-1) options 21.D3, 35.D3, and 60.D3
193    real*8, parameter :: enthalpy_ads2 = 21.D3      ! enthalpy of adsorption (J.mol-1) for the second segment
194    real*8, parameter :: DeltaQ_ads = 21.D3         ! heat of adsorption - enthalpy of liquefaction/sublimation for the first segment (J.mol-1)
195    real*8, parameter :: DeltaQ_ads2 = 21.D3        ! heat of adsorption - enthalpy of liquefaction/sublimation for the second segment (J.mol-1)
196    real*8, parameter :: tau0 = 1D-14
197    real*8, parameter :: S = 17.D3                  ! soil specific surface area (m2.kg-1 of solid) options: 17.D3 and 106.D3
198    real*8, parameter:: Sm = 10.6D-20               ! surface of the water molecule (m2)
199
200    ! Reference values for choice_ads = 2
201    real*8, parameter :: Tref = 243.15D0
202    real*8, parameter :: nref = 2.31505631D-6       ! not used anymore (for the time being)
203    real*8, parameter :: Kd_ref = 0.0206D0          ! not used for the time being
204    real*8, parameter :: Ka_ref = 2.4D-4            ! not used for the time being
205    real*8, parameter :: Kref = 0.205D-6            ! value obtained from the fit of all adsorption data from Pommerol (2009)
206    real*8, parameter :: Kref2 = 0.108D-7           ! value obtained from the fit of all adsorption data from Pommerol (2009)
207
208    logical :: recompute_all_cells_ads_flag          ! flag to check whether there is a cell of a column that requires recomputing
209    logical :: sublimation_flag
210    logical :: condensation_flag(nsoil)
211
212    ! Variables and parameters for the H2O map
213    integer, parameter :: n_long_H2O = 66           ! number of longitudes of the new H2O map
214    integer, parameter :: n_lat_H2O = 50            ! number of latitudes of the new H2O map
215    real*8, parameter :: rho_H2O_ice = 920.0D0      ! ice density (formerly rhoice)
216    real :: latH2O(n_lat_H2O*n_long_H2O)            ! latitude at H2O map points
217    real :: longH2O(n_lat_H2O*n_long_H2O)           ! longitude at H2O map points
218    real :: H2O_depth_data(n_lat_H2O*n_long_H2O)    ! depth of the ice layer in g/cm^2 at H2O map points
219    real :: H2O_cover_data(n_lat_H2O*n_long_H2O)    ! H2O content of the cover layer at H2O map points (not used yet)
220    real :: dataH2O(n_lat_H2O*n_long_H2O)           ! H2O content of the ice layer at H2O map points
221    real :: latH2O_temp(n_lat_H2O*n_long_H2O)       ! intermediate variable
222    real :: longH2O_temp(n_lat_H2O*n_long_H2O)      ! intermediate variable
223    real :: dataH2O_temp(n_lat_H2O*n_long_H2O)      ! intermediate variable
224    real :: H2O_depth_data_temp(n_lat_H2O*n_long_H2O) ! intermediate variable
225    real, allocatable, save :: H2O(:)               ! H2O map interpolated at GCM grid points (in wt%)
226    real, allocatable, save :: H2O_depth(:)         ! H2O map ice depth interpolated at GCM in g/cm^2
227
228    ! Variables for the 1D case
229    real*8, parameter :: mmr_h2o = 0.6D-4           ! water vapor mass mixing ratio (for initialization only)
230    real*8 :: diff(ngrid, nsoil)                    ! difference between total water content and ice + vapor content
231    real :: var_flux_soil(ngrid, nsoil)             ! output of the flux between soil layers (kg/m^3/s)
232    real :: default_diffcoeff = 4e-4                ! diffusion coefficient by default (no variations with Temperature and pressure (m/s^2)
233    real :: tol_massiveice = 50.                    ! tolerance to account for massive ice (kg/m^3)
234
235    ! Loop variables and counters
236    integer :: ig, ik, i, j                         ! loop variables
237    logical :: output_trigger                       ! used to limit amount of written output
238    integer, save :: n                              ! number of runs of this subroutine
239    integer :: sublim_n                             ! number of sublimation loop runs
240    integer :: satur_mono_n                         ! number of monolayer saturation loop runs
241
242    ! Allocate arrays if not already done
243    if (.not. allocated(znsoil)) then
244        allocate(znsoil(ngrid, nsoil))
245        allocate(ice(ngrid, nsoil))
246        allocate(adswater(ngrid, nsoil))
247        allocate(ztot1(ngrid, nsoil))
248        allocate(porosity_ice_free(ngrid, nsoil))
249        allocate(porosity(ngrid, nsoil))
250        allocate(tortuosity(ngrid, nsoil))
251        allocate(D0(ngrid, nsoil))
252        allocate(interlayer_dz(ngrid, nsoil))
253        allocate(midlayer_dz(ngrid, 0:nsoil))
254        allocate(zalpha(ngrid, nsoil))       ! extra entry to match output format
255        allocate(zbeta(ngrid, nsoil))        ! extra entry to match output format
256        allocate(meshsize(ngrid, nsoil))
257        allocate(rho_soil(ngrid, nsoil))
258        allocate(cste_ads(ngrid, nsoil))
259        allocate(H2O(ngrid))
260        allocate(H2O_depth(ngrid))
261        allocate(close_top(ngrid, nsoil))
262        allocate(close_bottom(ngrid, nsoil))
263        allocate(over_mono_sat_flag(ngrid, nsoil))
264    endif
265
266    ! Initialization
267    ! ================
268
269    if (firstcall_soil) then
270        n = 0
271        close_top = .false.
272        close_bottom = .false.
273        print *, "adsorption enthalpy first segment: ", enthalpy_ads
274        print *, "adsorption enthalpy second segment: ", enthalpy_ads2
275        print *, "adsorption BET constant C first segment: ", DeltaQ_ads
276        print *, "adsorption BET constant C second segment: ", DeltaQ_ads2
277        print *, "specific surface area: ", S
278
279        do ig = 1, ngrid
280            ! Initialize soil parameters
281            ! ===========================
282
283            ! Initialize the midlayer distances
284            midlayer_dz(ig, 0) = mlayer(0)
285
286            do ik = 1, nsoil - 1
287                midlayer_dz(ig, ik) = mlayer(ik) - mlayer(ik - 1)
288            enddo
289
290            ! Initialize the interlayer distances
291            interlayer_dz(ig, 1) = layer(1)
292            do ik = 2, nsoil
293                interlayer_dz(ig, ik) = layer(ik) - layer(ik - 1)
294            enddo
295
296            ! Choice of porous medium and D0
297            ! ===============================
298            do ik = 1, nsoil
299                ! These properties are defined here in order to enable custom profiles
300                if (ads_massive_ice) then
301                    if (pqsoil(ig, ik, igcm_h2o_ice_soil) .gt. tol_massiveice) then
302                        porosity_ice_free(ig, ik) = 0.999999
303                    else
304                        porosity_ice_free(ig, ik) = porosity_reg
305                    endif
306                else
307                    porosity_ice_free(ig, ik) = porosity_reg
308                endif
309                tortuosity(ig, ik) = 1.5D0
310                rho_soil(ig, ik) = 1.3D3 ! in kg/m3 of regolith (incl. porosity)
311
312                meshsize(ig, ik) = 5.D-6  ! characteristic size 1e-6 = 1 micron
313                D0(ig, ik) = porosity_ice_free(ig, ik) / tortuosity(ig, ik)
314            enddo
315
316            ! Choice of adsorption coefficients
317            ! ==================================
318            ! Unit = kg/m3; From best fit of all adsorption data from Pommerol et al. (2009)
319            adswater_sat_mono = 2.6998D-7 * S * rho_soil(ig, 1)
320
321            ! Initialization of ice, water vapor and adsorbed water profiles
322            ! ===============================================================
323            do ik = 1, nsoil
324                znsoil(ig, ik) = pqsoil(ig, ik, igcm_h2o_vap_soil)
325                ice(ig, ik) = pqsoil(ig, ik, igcm_h2o_ice_soil)
326                adswater(ig, ik) = pqsoil(ig, ik, igcm_h2o_vap_ads)
327
328                saturation_water_ice(ig, ik) = min(ice(ig, ik) / (rho_H2O_ice * porosity_ice_free(ig, ik)), 0.999D-0)
329
330                if (saturation_water_ice(ig, ik) .lt. 0.D0) then
331                    print *, "WARNING!! soil water ice negative at ", ig, ik
332                    print *, "saturation value: ", saturation_water_ice(ig, ik)
333                    print *, "setting saturation to 0"
334                    saturation_water_ice(ig, ik) = max(saturation_water_ice(ig, ik), 0.D0)
335                endif
336
337                porosity(ig, ik) = porosity_ice_free(ig, ik) * (1.D0 - saturation_water_ice(ig, ik))
338
339                ! Initialize soil as if all points are below the monolayer saturation level
340                if (adswater(ig, ik) .gt. adswater_sat_mono) then
341                    over_mono_sat_flag(ig, ik) = .true.
342                else
343                    over_mono_sat_flag(ig, ik) = .false.
344                endif
345            enddo
346        enddo
347
348        print *, "initializing H2O data"
349
350        do ig = 1, ngrid
351            output_trigger = .true.
352            do ik = 1, nsoil
353                saturation_water_ice(ig, ik) = min(ice(ig, ik) / (rho_H2O_ice * porosity_ice_free(ig, ik)), 0.999D-0)
354                saturation_water_ice(ig, ik) = max(saturation_water_ice(ig, ik), 0.D0)
355                porosity(ig, ik) = porosity_ice_free(ig, ik) * (1.D0 - saturation_water_ice(ig, ik))
356            enddo
357        enddo
358
359        print *, "Kinetic factor: ", kinetic_factor
360        if (kinetic_factor .eq. 0) then
361            print *, "WARNING: adsorption is switched off"
362        endif
363        firstcall_soil = .false.
364    endif  ! of "if firstcall_soil"
365
366    ! Update properties in case of the sublimation of massive ice
367    if (ads_massive_ice) then
368        do ig = 1, ngrid
369            do ik = 1, nsoil
370                if (pqsoil(ig, ik, igcm_h2o_ice_soil) .gt. tol_massiveice) then
371                    porosity_ice_free(ig, ik) = 0.999999
372                else
373                    porosity_ice_free(ig, ik) = porosity_reg
374                endif
375            enddo
376        enddo
377    endif
378
379! Computation of new (new step) transport coefficients
380! ===================================================
381
382do ig = 1, ngrid  ! loop over all gridpoints
383    if (.not. watercaptag(ig)) then  ! if there is no polar cap
384       
385        do ik = 1, nsoil
386            ! Calculate water saturation level (pore volume filled by ice / total pore volume)
387            saturation_water_ice(ig, ik) = min(ice(ig, ik) / (rho_H2O_ice * porosity_ice_free(ig, ik)), 0.999D0)
388           
389            if (saturation_water_ice(ig, ik) < 0.D0) then
390                print *, "WARNING!! soil water ice negative at ", ig, ik
391                print *, "saturation value: ", saturation_water_ice(ig, ik)
392                print *, "setting saturation to 0"
393                saturation_water_ice(ig, ik) = max(saturation_water_ice(ig, ik), 0.D0)
394            endif
395           
396            ! Save the old porosity
397            porosity_prev(ig, ik) = porosity(ig, ik)
398           
399            ! Calculate the new porosity
400            porosity(ig, ik) = porosity_ice_free(ig, ik) * (1.D0 - saturation_water_ice(ig, ik))
401            ! Note: saturation_water_ice and porosity are computed from the ice content of the previous timestep
402        enddo
403       
404        ! Calculate the air density in the first subsurface layer
405        rho(ig) = pplev(ig, 1) / (r * ptsoil(ig, 1))
406       
407        ! Calculate diffusion coefficients at mid- and interlayers (with ice content from the previous timestep)
408        ! Dependence on saturation_water_ice taken from Hudson et al. (2009) and Meslin et al. (SSSAJ, 2010)
409        do ik = 1, nsoil  ! loop over all soil levels
410           
411            ! Calculate H2O mean thermal velocity
412            vth(ig, ik) = dsqrt(8.D0 * 8.314D0 * ptsoil(ig, ik) / (pi * 18.D-3))
413           
414            ! Calculate the H2O - CO2 collision integral (after Mellon and Jakosky, JGR, 1993)
415            omega(ig, ik) = 1.442D0 - 0.673D0 * dlog(2.516D-3 * ptsoil(ig, ik)) &
416                          + 0.252D0 * (dlog(2.516D-3 * ptsoil(ig, ik))) ** 2.D0 &
417                          - 0.047D0 * (dlog(2.516D-3 * ptsoil(ig, ik))) ** 3.D0 &
418                          + 0.003D0 * (dlog(2.516D-3 * ptsoil(ig, ik))) ** 4.D0
419           
420            ! Calculate the molecular diffusion coefficient
421            Dm(ig, ik) = 4.867D0 * ptsoil(ig, ik) ** (3.D0 / 2.D0) &
422                       / (pplev(ig, 1) * omega(ig, ik)) * 1.D-4
423           
424            ! Calculate the Knudsen diffusion coefficient (divided by D0 = porosity / tortuosity)
425            Dk(ig, ik) = Dk0 / D0(ig, ik) * meshsize(ig, ik) * vth(ig, ik)
426           
427            ! Calculate midlayer diffusion coefficient (with dependence on saturation from Meslin et al., 2010)
428            D_mid(ig, ik) = D0(ig, ik) * (1.D0 - saturation_water_ice(ig, ik)) ** 2.D0 &
429                          * 1.D0 / (1.D0 / Dm(ig, ik) + 1.D0 / Dk(ig, ik))
430           
431            if (ads_const_D) D_mid(ig, ik) = default_diffcoeff
432           
433        enddo
434       
435        ! Calculate interlayer diffusion coefficient as interpolation of the midlayer coefficients
436        do ik = 1, nsoil - 1
437            Dm_inter(ig, ik) = ((layer(ik) - mlayer(ik - 1)) * Dm(ig, ik + 1) &
438                              + (mlayer(ik) - layer(ik)) * Dm(ig, ik)) / (mlayer(ik) - mlayer(ik - 1))
439           
440            Dk_inter(ig, ik) = ((layer(ik) - mlayer(ik - 1)) * Dk(ig, ik + 1) &
441                              + (mlayer(ik) - layer(ik)) * Dk(ig, ik)) / (mlayer(ik) - mlayer(ik - 1))
442           
443            if (close_bottom(ig, ik) .or. close_top(ig, ik + 1)) then
444                saturation_water_ice_inter(ig, ik) = 0.999D0
445            else
446                saturation_water_ice_inter(ig, ik) = min(saturation_water_ice(ig, ik + 1), saturation_water_ice(ig, ik))
447            endif
448           
449            saturation_water_ice_inter(ig, ik) = min(saturation_water_ice(ig, ik + 1), saturation_water_ice(ig, ik))
450           
451            D_inter(ig, ik) = D0(ig, ik) * (1.D0 - saturation_water_ice_inter(ig, ik)) ** 2.D0 &
452                            * 1.D0 / (1.D0 / Dm_inter(ig, ik) + 1.D0 / Dk_inter(ig, ik))
453           
454            if (ads_const_D) D_inter(ig, ik) = default_diffcoeff
455           
456        enddo
457    endif
458enddo
459
460! Computation of new adsorption/desorption constants (Ka, Kd coefficients), and C, E, F coefficients
461! ==================================================================================================
462
463do ig = 1, ngrid  ! loop over all gridpoints
464    if (.not. watercaptag(ig)) then  ! if there is no polar cap
465        do ik = 1, nsoil  ! loop over all soil levels
466           
467            if (choice_ads == 1) then  ! Constant, uniform diffusion coefficient D0 (prescribed)
468               
469                ! First segment of the bilinear function (before monolayer saturation)
470                ! Calculate the equilibrium adsorption coefficient
471                k_ads_eq(ig, ik) = rho_soil(ig, ik) * S * vth(ig, ik) / 4.D0 &
472                                 / (dexp(-enthalpy_ads / (8.314D0 * ptsoil(ig, ik))) / tau0)
473               
474                ! Calculate the desorption coefficient
475                Kd(ig, ik) = kinetic_factor / (1.D0 + k_ads_eq(ig, ik) / porosity(ig, ik))
476               
477                ! Calculate the absorption coefficient
478                Ka(ig, ik) = kinetic_factor * k_ads_eq(ig, ik) / (1.D0 + k_ads_eq(ig, ik) / porosity(ig, ik))
479               
480                ! Second segment of the bilinear function (after monolayer saturation) - added 2020
481                ! Calculate the equilibrium adsorption coefficient
482                k_ads_eq2(ig, ik) = rho_soil(ig, ik) * S * vth(ig, ik) / 4.D0 &
483                                  / (dexp(-enthalpy_ads2 / (8.314D0 * ptsoil(ig, ik))) / tau0)
484               
485                ! Calculate the desorption coefficient
486                Kd2(ig, ik) = kinetic_factor / (1.D0 + k_ads_eq2(ig, ik) / porosity(ig, ik))
487               
488                ! Calculate the absorption coefficient
489                Ka2(ig, ik) = kinetic_factor * k_ads_eq2(ig, ik) / (1.D0 + k_ads_eq2(ig, ik) / porosity(ig, ik))
490               
491            elseif (choice_ads == 2) then  ! Modified 2020 (with DeltaQ instead of Q)
492               
493                ! First segment of the bilinear function (before monolayer saturation)
494                ! Calculate the equilibrium adsorption coefficient
495                k_ads_eq(ig, ik) = 8.314D0 * rho_soil(ig, ik) * S * ptsoil(ig, ik) / 18.D-3 * Kref &
496                                 * dexp(DeltaQ_ads / 8.314D0 * (1.D0 / ptsoil(ig, ik) - 1.D0 / Tref))
497               
498                ! Calculate the desorption coefficient
499                Kd(ig, ik) = kinetic_factor / (1.D0 + k_ads_eq(ig, ik) / porosity(ig, ik))
500               
501                ! Calculate the absorption coefficient
502                Ka(ig, ik) = kinetic_factor * k_ads_eq(ig, ik) / (1.D0 + k_ads_eq(ig, ik) / porosity(ig, ik))
503               
504                ! Second segment of the bilinear function (after monolayer saturation) - added 2020
505                ! Calculate the equilibrium adsorption coefficient
506                k_ads_eq2(ig, ik) = 8.314D0 * rho_soil(ig, ik) * S * ptsoil(ig, ik) / 18.D-3 * Kref2 &
507                                  * dexp(DeltaQ_ads2 / 8.314D0 * (1.D0 / ptsoil(ig, ik) - 1.D0 / Tref))
508               
509                ! Calculate the desorption coefficient
510                Kd2(ig, ik) = kinetic_factor / (1.D0 + k_ads_eq2(ig, ik) / porosity(ig, ik))
511               
512                ! Calculate the absorption coefficient
513                Ka2(ig, ik) = kinetic_factor * k_ads_eq2(ig, ik) / (1.D0 + k_ads_eq2(ig, ik) / porosity(ig, ik))
514               
515            elseif (choice_ads == 0) then  ! No adsorption/desorption
516                Ka(ig, ik) = 0.D0
517                Kd(ig, ik) = 0.D0
518                Ka2(ig, ik) = 0.D0
519                Kd2(ig, ik) = 0.D0
520            endif
521           
522            ! Calculate the amount of water vapor at monolayer saturation - modified 2020
523            if (choice_ads /= 0) nsat(ig, ik) = adswater_sat_mono * Kd(ig, ik) / Ka(ig, ik)
524           
525            ! Calculate the intercept of the second line in the bilinear function - added 2020; corrected 2024
526            c0(ig, ik) = (1.D0 - (k_ads_eq2(ig, ik) / k_ads_eq(ig, ik))) * adswater_sat_mono
527           
528            ! Calculate C, E, and F coefficients for later calculations
529            C(ig, ik) = interlayer_dz(ig, ik) / ptimestep
530           
531            ! First segment of the bilinear function (before monolayer saturation)
532            E(ig, ik) = Ka(ig, ik) / (1.D0 + ptimestep * Kd(ig, ik))
533            F(ig, ik) = Kd(ig, ik) / (1.D0 + ptimestep * Kd(ig, ik))
534           
535            ! Second segment of the bilinear function (after monolayer saturation) - added 2020
536            E2(ig, ik) = Ka2(ig, ik) / (1.D0 + ptimestep * Kd2(ig, ik))
537            F2(ig, ik) = Kd2(ig, ik) / (1.D0 + ptimestep * Kd2(ig, ik))
538           
539            ! Save the old water concentration
540            znsoilprev(ig, ik) = znsoil(ig, ik)
541            znsoilprev2(ig, ik) = znsoil(ig, ik)  ! needed in "special case" loop
542            adswprev(ig, ik) = adswater(ig, ik)
543            iceprev(ig, ik) = ice(ig, ik)
544           
545            ! Calculate the total ice + water vapor content
546            ztot1(ig, ik) = porosity_prev(ig, ik) * znsoil(ig, ik) + ice(ig, ik)
547        enddo
548    endif
549enddo
550
551! Computation of delta, alpha and beta coefficients
552! =================================================
553
554do ig = 1, ngrid  ! loop over all gridpoints
555    ! Initialize the flux to zero to avoid undefined values
556    zdqsdifrego(ig) = 0.D0
557    do ik = 0, nsoil - 1
558        flux(ig, ik) = 0.D0
559    enddo
560   
561    if (.not. watercaptag(ig)) then  ! if there is no polar cap
562        do ik = 1, nsoil  ! loop over all soil levels
563            if (ice(ig, ik) == 0.D0) then
564                ice_index_flag(ik) = .false.
565            else
566                ice_index_flag(ik) = .true.
567            endif
568        enddo
569       
570        do ik = 1, nsoil  ! loop over all soil levels
571           
572            ! Calculate A and B coefficients - modified 2020
573            if (.not. over_mono_sat_flag(ig, ik)) then  ! Assume cell below the monolayer saturation
574                ! Calculate A and B coefficients (first segment of the bilinear function)
575                A(ig, ik) = E(ig, ik) * interlayer_dz(ig, ik)
576                B(ig, ik) = interlayer_dz(ig, ik) * F(ig, ik) * adswprev(ig, ik)
577            else  ! Assume cell over the monolayer saturation - added 2020
578                ! Calculate A and B coefficients (second segment of the bilinear function)
579                A(ig, ik) = E2(ig, ik) * interlayer_dz(ig, ik)
580                B(ig, ik) = interlayer_dz(ig, ik) * F2(ig, ik) * adswprev(ig, ik) &
581                          + interlayer_dz(ig, ik) * (F2(ig, ik) * Kd2(ig, ik) * c0(ig, ik) * ptimestep - Kd2(ig, ik) * c0(ig, ik))
582            endif
583           
584            ! Calculate the saturation pressure
585            P_sat_soil(ig, ik) = 611.D0 * dexp(22.5D0 * (1.D0 - 273.16D0 / ptsoil(ig, ik)))
586           
587            ! Calculate the gas number density at saturation pressure
588            nsatsoil(ig, ik) = (P_sat_soil(ig, ik) * mw) / (kb * ptsoil(ig, ik))
589        enddo
590       
591        ! Calculate the alpha, beta, and delta coefficients for the surface layer
592        delta0(ig) = pa(ig, 1) + pb(ig, 2) * (1.D0 - pd(ig, 2)) + porosity_ice_free(ig, 1) * pb(ig, 1)
593        alpha0(ig) = porosity_ice_free(ig, 1) * pb(ig, 1) / delta0(ig)
594       
595        beta0(ig) = (pb(ig, 2) * pc(ig, 2) + pq(ig, 1, igcm_h2o_vap) * pa(ig, 1) + pqsurf(ig)) / delta0(ig)
596       
597        ! Set loop flags
598        do ik = 1, nsoil
599            condensation_flag(ik) = .false.
600        enddo
601       
602        sublimation_flag = .true.
603        sublim_n = 0
604        do while (sublimation_flag)  ! while there is sublimation
605            sublim_n = sublim_n + 1
606           
607            if (sublim_n > 100) then
608                print *, "sublimation not converging in call ", n
609                print *, "might as well stop now"
610                stop
611            endif
612           
613            ! Reset flag
614            sublimation_flag = .false.
615           
616            recompute_all_cells_ads_flag = .true.
617            satur_mono_n = 0
618            do while (recompute_all_cells_ads_flag)
619                satur_mono_n = satur_mono_n + 1
620               
621                ! Reset loop flag
622                recompute_all_cells_ads_flag = .false.
623               
624                ! Calculate the surface air density
625                rhosurf(ig) = pplev(ig, 1) / (r * ptsrf(ig))
626               
627                ! Calculate the coefficients in the uppermost layer
628                if (exchange(ig)) then  ! if there is surface exchange
629                   
630                    ! Calculate the delta, alpha, and beta coefficients
631                    zdelta(ig, 1) = A(ig, 1) + porosity(ig, 1) * C(ig, 1) &
632                                  + D_inter(ig, 1) / midlayer_dz(ig, 1) &
633                                  + porosity_ice_free(ig, 1) * pb(ig, 1) / (rho(ig) * ptimestep) * (1.D0 - alpha0(ig))
634                   
635                    zalpha(ig, 1) = D_inter(ig, 1) / midlayer_dz(ig, 1) * 1.D0 / zdelta(ig, 1)
636                   
637                    zbeta(ig, 1) = (porosity_ice_free(ig, 1) * pb(ig, 1) / ptimestep * beta0(ig) &
638                                 + porosity_prev(ig, 1) * C(ig, 1) * znsoilprev(ig, 1) + B(ig, 1)) / zdelta(ig, 1)
639                else
640                    ! Calculate the delta, alpha, and beta coefficients without exchange
641                    zdelta(ig, 1) = A(ig, 1) + D_inter(ig, 1) / midlayer_dz(ig, 1) &
642                                  + D_mid(ig, 1) / midlayer_dz(ig, 0) + porosity(ig, 1) * C(ig, 1)
643                   
644                    zalpha(ig, 1) = D_inter(ig, 1) / midlayer_dz(ig, 1) * 1.D0 / zdelta(ig, 1)
645                   
646                    zbeta(ig, 1) = (D_mid(ig, 1) / midlayer_dz(ig, 0) * qsat_surf(ig) * rhosurf(ig) &
647                                 + porosity_prev(ig, 1) * C(ig, 1) * znsoilprev(ig, 1) + B(ig, 1)) / zdelta(ig, 1)
648                endif
649               
650                ! Check for ice
651                if (ice_index_flag(1)) then
652                    ! Set the alpha coefficient to zero
653                    zalpha(ig, 1) = 0.D0
654                    ! Set the beta coefficient to the number density at saturation pressure
655                    zbeta(ig, 1) = nsatsoil(ig, 1)
656                endif
657               
658                do ik = 2, nsoil - 1  ! go through all other layers
659                   
660                    ! Calculate delta, alpha, and beta coefficients
661                    zdelta(ig, ik) = A(ig, ik) + porosity(ig, ik) * C(ig, ik) &
662                                   + D_inter(ig, ik) / midlayer_dz(ig, ik) &
663                                   + D_inter(ig, ik - 1) / midlayer_dz(ig, ik - 1) * (1.D0 - zalpha(ig, ik - 1))
664                   
665                    zalpha(ig, ik) = D_inter(ig, ik) / midlayer_dz(ig, ik) * 1.D0 / zdelta(ig, ik)
666                   
667                    zbeta(ig, ik) = (D_inter(ig, ik - 1) / midlayer_dz(ig, ik - 1) * zbeta(ig, ik - 1) &
668                                   + B(ig, ik) + porosity_prev(ig, ik) * C(ig, ik) * znsoilprev(ig, ik)) / zdelta(ig, ik)
669                   
670                    ! Check for ice
671                    if (ice_index_flag(ik)) then
672                        ! Set the alpha coefficient to zero
673                        zalpha(ig, ik) = 0.D0
674                        ! Set the beta coefficient to the number density at saturation pressure
675                        zbeta(ig, ik) = nsatsoil(ig, ik)
676                    endif
677                enddo
678               
679                ! Computation of pqsoil, ztot1, zq1temp2 and zdqsdifrego
680                ! =======================================================
681               
682                ! Calculate the preliminary amount of water vapor in the bottom layer
683                if (ice_index_flag(nsoil)) then  ! if there is ice
684                    ! Set the vapor number density to saturation
685                    znsoil(ig, nsoil) = nsatsoil(ig, nsoil)
686                else
687                    ! Calculate the vapor number density in the lowest layer
688                    znsoil(ig, nsoil) = (D_inter(ig, nsoil - 1) / midlayer_dz(ig, nsoil - 1) * zbeta(ig, nsoil - 1) &
689                                       + porosity_prev(ig, nsoil) * C(ig, nsoil) * znsoilprev(ig, nsoil) + B(ig, nsoil)) &
690                                      / (porosity(ig, nsoil) * C(ig, nsoil) + A(ig, nsoil) &
691                                       + D_inter(ig, nsoil - 1) / midlayer_dz(ig, nsoil - 1) * (1.D0 - zalpha(ig, nsoil - 1)))
692                endif
693               
694                ! Calculate the preliminary amount of adsorbed water
695                if (.not. over_mono_sat_flag(ig, nsoil)) then  ! modified 2024
696                    adswater_temp(ig, nsoil) = (Ka(ig, nsoil) * ptimestep * znsoil(ig, nsoil) + adswprev(ig, nsoil)) &
697                                             / (1.D0 + ptimestep * Kd(ig, nsoil))
698                else
699                    adswater_temp(ig, nsoil) = (Ka2(ig, nsoil) * ptimestep * znsoil(ig, nsoil) + adswprev(ig, nsoil) &
700                                             + ptimestep * c0(ig, nsoil) * Kd2(ig, nsoil)) &
701                                             / (1.D0 + ptimestep * Kd2(ig, nsoil))
702                endif
703               
704                do ik = nsoil - 1, 1, -1  ! backward loop over all layers
705                   
706                    znsoil(ig, ik) = zalpha(ig, ik) * znsoil(ig, ik + 1) + zbeta(ig, ik)
707                   
708                    if (.not. over_mono_sat_flag(ig, ik)) then  ! modified 2024
709                        adswater_temp(ig, ik) = (Ka(ig, ik) * ptimestep * znsoil(ig, ik) + adswprev(ig, ik)) &
710                                              / (1.D0 + ptimestep * Kd(ig, ik))
711                    else
712                        adswater_temp(ig, ik) = (Ka2(ig, ik) * ptimestep * znsoil(ig, ik) + adswprev(ig, ik) &
713                                               + ptimestep * c0(ig, ik) * Kd2(ig, ik)) &
714                                               / (1.D0 + ptimestep * Kd2(ig, ik))
715                    endif
716                enddo
717               
718                ! Check if any cell is over monolayer saturation
719                do ik = 1, nsoil  ! loop over all soil levels
720                   
721                    ! Change of coefficients
722                    recompute_cell_ads_flag(ik) = .false.  ! Assume there is no change of coefficients
723                   
724                    if (adswater_temp(ig, ik) >= adswater_sat_mono) then
725                       
726                        print *, "NOTICE: over monolayer saturation"
727                       
728                        if (.not. over_mono_sat_flag(ig, ik)) then
729                            ! If the cell enters this scope, it means that the cell is over the monolayer
730                            ! saturation after calculation, but the coefficients assume it is below.
731                            ! Therefore, the cell needs to be recomputed
732                           
733                            over_mono_sat_flag(ig, ik) = .true.
734                            recompute_cell_ads_flag(ik) = .true.  ! There is a change of coefficients
735                           
736                            ! Change the A and B coefficients (change from first segment to second segment)
737                            A(ig, ik) = E2(ig, ik) * interlayer_dz(ig, ik)
738                            B(ig, ik) = interlayer_dz(ig, ik) * F2(ig, ik) * adswprev(ig, ik) &
739                                      + interlayer_dz(ig, ik) * (F2(ig, ik) * Kd2(ig, ik) * c0(ig, ik) * ptimestep - Kd2(ig, ik) * c0(ig, ik))
740                        endif
741                    else
742                        if (over_mono_sat_flag(ig, ik)) then
743                            ! If the cell enters this scope, it means that the cell is below the monolayer
744                            ! saturation after calculation, but the coefficients assume it is above.
745                            ! Therefore, the cell needs to be recomputed
746                           
747                            over_mono_sat_flag(ig, ik) = .false.
748                            recompute_cell_ads_flag(ik) = .true.  ! There is a change of coefficients
749                           
750                            ! Calculate A and B coefficients (reset to first segment of the bilinear function)
751                            A(ig, ik) = E(ig, ik) * interlayer_dz(ig, ik)
752                            B(ig, ik) = interlayer_dz(ig, ik) * F(ig, ik) * adswprev(ig, ik)
753                        endif
754                    endif
755                enddo
756               
757                ! If one cell needs to be recomputed, then all the column is to be recomputed too
758                do ik = 1, nsoil
759                    if (recompute_cell_ads_flag(ik)) then
760                        recompute_all_cells_ads_flag = .true.
761                    else
762                        adswater(ig, ik) = adswater_temp(ig, ik)  ! if no recomputing is needed, store the value
763                    endif
764                enddo
765            enddo  ! end loop while recompute_all_cells_ads_flag (monolayer saturation)
766           
767            ! Calculation of Fnet + Fads
768            ! ===========================
769           
770            ! Calculate the flux variable
771           
772            ! Calculate the flux in the top layer
773            if (exchange(ig)) then  ! if there is exchange
774                ! Calculate the flux taking diffusion to the atmosphere into account
775                flux(ig, 0) = porosity_ice_free(ig, 1) * pb(ig, 1) / ptimestep &
776                            * (znsoil(ig, 1) / rho(ig) - beta0(ig) - alpha0(ig) * znsoil(ig, 1) / rho(ig))
777            elseif (pqsurf(ig) > 0.D0) then
778                ! Assume that the surface is covered by water ice
779                flux(ig, 0) = D_mid(ig, 1) / midlayer_dz(ig, 0) * (znsoil(ig, 1) - qsat_surf(ig) * rhosurf(ig))
780            endif
781           
782            ! Check if the ground would take up water from the surface but there is none
783            if ((.not. exchange(ig)) .and. (pqsurf(ig) == 0.D0) .and. (flux(ig, 0) < 0.D0)) then
784                flux(ig, 0) = 0.D0
785            endif
786           
787            ! Calculate the flux in all other layers
788            do ik = 1, nsoil - 1
789                flux(ig, ik) = D_inter(ig, ik) * (znsoil(ig, ik + 1) - znsoil(ig, ik)) / midlayer_dz(ig, ik)
790            enddo
791           
792            ! Calculate dztot1 which describes the change in ztot1 (water vapor and ice)
793            do ik = 1, nsoil - 1
794                dztot1(ik) = (flux(ig, ik) - flux(ig, ik - 1)) / interlayer_dz(ig, ik) &
795                           - A(ig, ik) / interlayer_dz(ig, ik) * znsoil(ig, ik) &
796                           + B(ig, ik) / interlayer_dz(ig, ik)
797            enddo
798           
799            dztot1(nsoil) = -flux(ig, nsoil - 1) / interlayer_dz(ig, nsoil) &
800                          - A(ig, nsoil) / interlayer_dz(ig, nsoil) * znsoil(ig, nsoil) &
801                          + B(ig, nsoil) / interlayer_dz(ig, nsoil)
802           
803            ! Condensation / sublimation
804            do ik = 1, nsoil  ! loop over all
805                if (ice_index_flag(ik)) then  ! if there is ice
806                   
807                    ! Compute ice content
808                    ice(ig, ik) = ztot1(ig, ik) + dztot1(ik) * ptimestep - porosity(ig, ik) * nsatsoil(ig, ik)
809                   
810                    if (ice(ig, ik) < 0.D0) then  ! if all the ice is used up
811                       
812                        ! Set the ice content to zero
813                        ice(ig, ik) = 0.D0
814                       
815                        ! Change the water vapor from the previous timestep. (Watch out! could go wrong)
816                        znsoilprev(ig, ik) = ztot1(ig, ik) / porosity_prev(ig, ik)
817                       
818                        ! Remove the ice flag and raise the sublimation flag
819                        ice_index_flag(ik) = .false.
820                        sublimation_flag = .true.
821                    endif
822                   
823                elseif (znsoil(ig, ik) > nsatsoil(ig, ik)) then  ! if there is condensation
824                   
825                    if (.not. condensation_flag(ik)) then
826                        ! Raise the ice and sublimation flags
827                        ice_index_flag(ik) = .true.
828                        sublimation_flag = .true.
829                        condensation_flag(ik) = .true.
830                    endif
831                endif
832               
833                ! Calculate the difference between total water content and ice + vapor content (only used for output)
834                diff(ig, ik) = ice(ig, ik) + porosity(ig, ik) * znsoil(ig, ik) &
835                             + adswater(ig, ik) - ztot1(ig, ik) - dztot1(ik) * ptimestep
836            enddo  ! loop over all layers
837        enddo  ! end first loop while sublimation_flag (condensation / sublimation)
838       
839        if (exchange(ig)) then  ! if there is exchange
840           
841            ! Calculate the temporary mixing ratio above the surface
842            zq1temp2(ig) = beta0(ig) + alpha0(ig) * znsoil(ig, 1) / rho(ig)
843            ! Calculate the flux from the subsurface
844            zdqsdifrego(ig) = porosity_ice_free(ig, 1) * pb(ig, 1) / ptimestep * (zq1temp2(ig) - znsoil(ig, 1) / rho(ig))
845           
846        else
847            ! Calculate the flux from the subsurface
848            zdqsdifrego(ig) = D_mid(ig, 1) / midlayer_dz(ig, 0) * (znsoil(ig, 1) - qsat_surf(ig) * rhosurf(ig))
849            if ((pqsurf(ig) == 0.D0) .and. (zdqsdifrego(ig) < 0.D0)) then
850                zdqsdifrego(ig) = 0.D0
851            endif
852        endif
853       
854        ! Special case where there is not enough ice on the surface to supply the subsurface for the whole timestep
855        ! (when exchange with the atmosphere is disabled): the upper boundary condition becomes a flux condition
856        ! (and not qsat_surf) and all the remaining surface ice is sublimated and transferred to the subsurface.
857        ! The actual change in surface ice happens in a higher subroutine
858        ! =====================================================================================================
859       
860        if ((.not. exchange(ig)) &
861            .and. ((-zdqsdifrego(ig) * ptimestep) > (pqsurf(ig) + pdqsdifpot(ig) * ptimestep)) &
862            .and. ((pqsurf(ig) + pdqsdifpot(ig) * ptimestep) > 0.D0)) then
863           
864            ! Calculate a new flux from the subsurface
865            zdqsdifrego(ig) = -(pqsurf(ig) + pdqsdifpot(ig) * ptimestep) / ptimestep
866           
867            do ik = 1, nsoil
868               
869                ! Calculate A and B coefficients - modified 2020
870                if (.not. over_mono_sat_flag(ig, ik)) then  ! Assume cell below the monolayer saturation
871                    ! Calculate A and B coefficients (first segment of the bilinear function)
872                    A(ig, ik) = E(ig, ik) * interlayer_dz(ig, ik)
873                    B(ig, ik) = interlayer_dz(ig, ik) * F(ig, ik) * adswprev(ig, ik)
874                else  ! Assume cell over the monolayer saturation - added 2020
875                    ! Calculate A and B coefficients (second segment of the bilinear function)
876                    A(ig, ik) = E2(ig, ik) * interlayer_dz(ig, ik)
877                    B(ig, ik) = interlayer_dz(ig, ik) * F2(ig, ik) * adswprev(ig, ik) &
878                              + interlayer_dz(ig, ik) * (F2(ig, ik) * Kd2(ig, ik) * c0(ig, ik) * ptimestep - Kd2(ig, ik) * c0(ig, ik))
879                endif
880               
881                ! Initialize the ice
882                ice(ig, ik) = iceprev(ig, ik)
883                if (iceprev(ig, ik) == 0.D0) then
884                    ice_index_flag(ik) = .false.
885                else
886                    ice_index_flag(ik) = .true.
887                endif
888            enddo
889           
890            ! Loop while there is new sublimation
891            sublimation_flag = .true.
892            sublim_n = 0
893            do while (sublimation_flag)
894                sublim_n = sublim_n + 1
895                if (sublim_n > 100) then
896                    print *, "special case sublimation not converging in call ", n
897                    print *, "might as well stop now"
898                    stop
899                endif
900               
901                ! Reset the sublimation flag
902                sublimation_flag = .false.
903               
904                ! Loop until good values accounting for monolayer saturation are found
905                recompute_all_cells_ads_flag = .true.
906                do while (recompute_all_cells_ads_flag)
907                   
908                    ! Reset loop flag
909                    recompute_all_cells_ads_flag = .false.
910                   
911                    ! Calculate the Delta, Alpha, and Beta coefficients in the top layer
912                    zdelta(ig, 1) = A(ig, 1) + porosity(ig, 1) * C(ig, 1) + D_inter(ig, 1) / midlayer_dz(ig, 1)
913                   
914                    zalpha(ig, 1) = D_inter(ig, 1) / midlayer_dz(ig, 1) * 1.D0 / zdelta(ig, 1)
915                   
916                    zbeta(ig, 1) = (porosity_prev(ig, 1) * C(ig, 1) * znsoilprev2(ig, 1) + B(ig, 1) - zdqsdifrego(ig)) / zdelta(ig, 1)
917                   
918                    ! Check for ice
919                    if (ice_index_flag(1)) then
920                        ! Set the alpha coefficient to zero
921                        zalpha(ig, 1) = 0.D0
922                        ! Set the beta coefficient to the number density at saturation pressure
923                        zbeta(ig, 1) = nsatsoil(ig, 1)
924                    endif
925                   
926                    do ik = 2, nsoil - 1  ! loop over all other layers
927                       
928                        ! Calculate the Delta, Alpha, and Beta coefficients in the layer
929                        zdelta(ig, ik) = A(ig, ik) + porosity(ig, ik) * C(ig, ik) + D_inter(ig, ik) / midlayer_dz(ig, ik) &
930                                       + D_inter(ig, ik - 1) / midlayer_dz(ig, ik - 1) * (1.D0 - zalpha(ig, ik - 1))
931                       
932                        zalpha(ig, ik) = D_inter(ig, ik) / midlayer_dz(ig, ik) * 1.D0 / zdelta(ig, ik)
933                       
934                        zbeta(ig, ik) = (D_inter(ig, ik - 1) / midlayer_dz(ig, ik - 1) * zbeta(ig, ik - 1) &
935                                       + porosity_prev(ig, ik) * C(ig, ik) * znsoilprev2(ig, ik) + B(ig, ik)) / zdelta(ig, ik)
936                       
937                        ! Check for ice
938                        if (ice_index_flag(ik)) then
939                            ! Set the alpha coefficient to zero
940                            zalpha(ig, ik) = 0.D0
941                            ! Set the beta coefficient to the number density at saturation pressure
942                            zbeta(ig, ik) = nsatsoil(ig, ik)
943                        endif
944                    enddo
945                   
946                    ! Calculate the preliminary amount of water vapor in the bottom layer
947                    if (ice_index_flag(nsoil)) then
948                        ! Set the vapor number density to saturation
949                        znsoil(ig, nsoil) = nsatsoil(ig, nsoil)
950                    else
951                        ! Calculate the vapor number density in the lowest layer
952                        znsoil(ig, nsoil) = (D_inter(ig, nsoil - 1) / midlayer_dz(ig, nsoil - 1) * zbeta(ig, nsoil - 1) &
953                                           + porosity_prev(ig, nsoil) * C(ig, nsoil) * znsoilprev2(ig, nsoil) + B(ig, nsoil)) &
954                                          / (porosity(ig, nsoil) * C(ig, nsoil) &
955                                           + D_inter(ig, nsoil - 1) / midlayer_dz(ig, nsoil - 1) * (1.D0 - zalpha(ig, nsoil - 1)) &
956                                           + A(ig, nsoil))
957                    endif
958                   
959                    ! Calculate the preliminary amount of adsorbed water
960                    if (.not. over_mono_sat_flag(ig, nsoil)) then  ! modified 2024
961                        adswater_temp(ig, nsoil) = (Ka(ig, nsoil) * ptimestep * znsoil(ig, nsoil) + adswprev(ig, nsoil)) &
962                                                 / (1.D0 + ptimestep * Kd(ig, nsoil))
963                    else
964                        adswater_temp(ig, nsoil) = (Ka2(ig, nsoil) * ptimestep * znsoil(ig, nsoil) + adswprev(ig, nsoil) &
965                                                 + ptimestep * c0(ig, nsoil) * Kd2(ig, nsoil)) &
966                                                 / (1.D0 + ptimestep * Kd2(ig, nsoil))
967                    endif
968                   
969                    do ik = nsoil - 1, 1, -1  ! backward loop over all layers
970                       
971                        znsoil(ig, ik) = zalpha(ig, ik) * znsoil(ig, ik + 1) + zbeta(ig, ik)
972                       
973                        if (.not. over_mono_sat_flag(ig, ik)) then  ! modified 2024
974                            adswater_temp(ig, ik) = (Ka(ig, ik) * ptimestep * znsoil(ig, ik) + adswprev(ig, ik)) &
975                                                  / (1.D0 + ptimestep * Kd(ig, ik))
976                        else
977                            adswater_temp(ig, ik) = (Ka2(ig, ik) * ptimestep * znsoil(ig, ik) + adswprev(ig, ik) &
978                                                   + ptimestep * c0(ig, ik) * Kd2(ig, ik)) &
979                                                   / (1.D0 + ptimestep * Kd2(ig, ik))
980                        endif
981                    enddo
982                   
983                    ! Check for any saturation
984                    do ik = 1, nsoil
985                        ! Change of coefficients
986                        recompute_cell_ads_flag(ik) = .false.  ! Assume there is no change of coefficients
987                       
988                        if (adswater_temp(ig, ik) > adswater_sat_mono) then
989                           
990                            print *, "NOTICE: over monolayer saturation"
991                           
992                            if (.not. over_mono_sat_flag(ig, ik)) then
993                                ! If the cell enters this scope, it means that the cell is over the monolayer
994                                ! saturation after calculation, but the coefficients assume it is below.
995                                ! Therefore, the cell needs to be recomputed
996                               
997                                over_mono_sat_flag(ig, ik) = .true.
998                                recompute_cell_ads_flag(ik) = .true.  ! There is a change of coefficients
999                               
1000                                ! Change the A and B coefficients
1001                                A(ig, ik) = E2(ig, ik) * interlayer_dz(ig, ik)
1002                                B(ig, ik) = interlayer_dz(ig, ik) * F2(ig, ik) * adswprev(ig, ik) &
1003                                          + interlayer_dz(ig, ik) * (F2(ig, ik) * Kd2(ig, ik) * c0(ig, ik) * ptimestep - Kd2(ig, ik) * c0(ig, ik))
1004                            endif
1005                        else
1006                            if (over_mono_sat_flag(ig, ik)) then
1007                                ! If the cell enters this scope, it means that the cell is below the monolayer
1008                                ! saturation after calculation, but the coefficients assume it is above.
1009                                ! Therefore, the cell needs to be recomputed
1010                               
1011                                over_mono_sat_flag(ig, ik) = .false.
1012                                recompute_cell_ads_flag(ik) = .true.  ! There is a change of coefficients
1013                               
1014                                ! Calculate A and B coefficients (reset to first segment of the bilinear function)
1015                                A(ig, ik) = E(ig, ik) * interlayer_dz(ig, ik)
1016                                B(ig, ik) = interlayer_dz(ig, ik) * F(ig, ik) * adswprev(ig, ik)
1017                            endif
1018                        endif
1019                    enddo
1020                   
1021                    ! Raise the saturation flag if any layer has saturated
1022                    do ik = 1, nsoil
1023                        if (recompute_cell_ads_flag(ik)) then
1024                            recompute_all_cells_ads_flag = .true.
1025                        else
1026                            adswater(ig, ik) = adswater_temp(ig, ik)  ! if no recomputing is needed, store the value
1027                        endif
1028                    enddo
1029                enddo  ! end while loop (adsorption saturation)
1030               
1031                ! Set the flux to the previously calculated value for the top layer
1032                flux(ig, 0) = zdqsdifrego(ig)
1033               
1034                ! Calculate the flux for all other layers
1035                do ik = 1, nsoil - 1
1036                    flux(ig, ik) = D_inter(ig, ik) * (znsoil(ig, ik + 1) - znsoil(ig, ik)) / midlayer_dz(ig, ik)
1037                enddo
1038               
1039                ! Calculate the change in ztot1
1040                do ik = 1, nsoil - 1
1041                    dztot1(ik) = (flux(ig, ik) - flux(ig, ik - 1)) / interlayer_dz(ig, ik) &
1042                               - A(ig, ik) / interlayer_dz(ig, ik) * znsoil(ig, ik) &
1043                               + B(ig, ik) / interlayer_dz(ig, ik)
1044                enddo
1045               
1046                dztot1(nsoil) = -flux(ig, nsoil - 1) / interlayer_dz(ig, nsoil) &
1047                              - A(ig, nsoil) / interlayer_dz(ig, nsoil) * znsoil(ig, nsoil) &
1048                              + B(ig, nsoil) / interlayer_dz(ig, nsoil)
1049               
1050                ! Condensation / sublimation
1051                do ik = 1, nsoil
1052                    if (ice_index_flag(ik)) then
1053                       
1054                        ! Compute ice content
1055                        ice(ig, ik) = ztot1(ig, ik) + dztot1(ik) * ptimestep - porosity(ig, ik) * nsatsoil(ig, ik)
1056                       
1057                        if (ice(ig, ik) < 0.D0) then  ! if all the ice is used up
1058                           
1059                            ! Set the ice content to zero
1060                            ice(ig, ik) = 0.D0
1061                           
1062                            if (znsoil(ig, ik) > nsatsoil(ig, ik)) then
1063                                print *, "WARNING! complete sublimation, but vapor is oversaturated"
1064                                print *, "special case loop in cell", ig, ik, "will be suppressed"
1065                            else
1066                                ! Change the water vapor from the previous timestep. (Watch out! could go wrong)
1067                                znsoilprev2(ig, ik) = ztot1(ig, ik) / porosity_prev(ig, ik)
1068                               
1069                                ! Remove the ice flag and raise the sublimation flag
1070                                ice_index_flag(ik) = .false.
1071                                sublimation_flag = .true.
1072                            endif
1073                        endif
1074                       
1075                    elseif (znsoil(ig, ik) > nsatsoil(ig, ik)) then  ! if there is new ice through condensation
1076                        if (.not. condensation_flag(ik)) then
1077                            ! Raise the ice and sublimation flags
1078                            ice_index_flag(ik) = .true.
1079                            sublimation_flag = .true.
1080                            condensation_flag(ik) = .true.
1081                        endif
1082                    endif
1083                enddo
1084            enddo  ! end first loop while (condensation / sublimation)
1085        endif  ! Special case for all ice on the surface is used up
1086       
1087        do ik = 1, nsoil
1088           
1089            diff(ig, ik) = ice(ig, ik) + porosity(ig, ik) * znsoil(ig, ik) &  ! only used for output
1090                         + adswater(ig, ik) - adswprev(ig, ik) &
1091                         - ztot1(ig, ik) - dztot1(ik) * ptimestep
1092           
1093            ! Calculate the total amount of water
1094            ztot1(ig, ik) = porosity(ig, ik) * znsoil(ig, ik) + ice(ig, ik)
1095            h2otot(ig, ik) = adswater(ig, ik) + ztot1(ig, ik)
1096        enddo
1097    endif  ! if there is no polar cap
1098enddo  ! loop over all gridpoints
1099
1100! Check for choking condition
1101do ig = 1, ngrid
1102    if (.not. watercaptag(ig)) then
1103        do ik = 1, nsoil - 1
1104            if (ice(ig, ik) / (rho_H2O_ice * porosity_ice_free(ig, ik)) > choke_fraction) then  ! if the ice is over saturation or choke_fraction
1105                if (flux(ig, ik - 1) > 0.D0) then
1106                    if (.not. close_top(ig, ik) .and. print_closure_warnings) then
1107                        print *, "NOTICE: closing top of soil layer due to inward flux", ig, ik
1108                    endif
1109                    close_top(ig, ik) = .true.
1110                elseif (flux(ig, ik - 1) < 0.D0) then
1111                    if (close_top(ig, ik) .and. print_closure_warnings) then
1112                        print *, "NOTICE: opening top of soil layer due to outward flux", ig, ik
1113                    endif
1114                    close_top(ig, ik) = .false.
1115                endif
1116               
1117                if (flux(ig, ik) < 0.D0) then
1118                    if (.not. close_bottom(ig, ik) .and. print_closure_warnings) then
1119                        print *, "NOTICE: closing bottom of soil layer due to inward flux", ig, ik
1120                    endif
1121                    close_bottom(ig, ik) = .true.
1122                elseif (flux(ig, ik) > 0.D0) then
1123                    if (close_bottom(ig, ik) .and. print_closure_warnings) then
1124                        print *, "NOTICE: opening bottom of soil layer due to outward flux", ig, ik
1125                    endif
1126                    close_bottom(ig, ik) = .false.
1127                endif
1128               
1129            else  ! opening condition that ice content has fallen sufficiently
1130                if ((close_top(ig, ik) .or. close_bottom(ig, ik)) .and. print_closure_warnings) then
1131                    print *, "NOTICE: Reopening soil layer due to decrease in ice", ig, ik
1132                endif
1133                close_top(ig, ik) = .false.
1134                close_bottom(ig, ik) = .false.
1135            endif
1136        enddo
1137    endif
1138enddo
1139
1140! Computation of total mass
1141! =========================
1142
1143do ig = 1, ngrid
1144    ! Initialize the masses to zero
1145    mass_h2o(ig) = 0.D0
1146    mass_ice(ig) = 0.D0
1147   
1148    if (.not. watercaptag(ig)) then
1149        do ik = 1, nsoil
1150            ! Calculate the total water and ice mass
1151            mass_h2o(ig) = mass_h2o(ig) + h2otot(ig, ik) * interlayer_dz(ig, ik)
1152            mass_ice(ig) = mass_ice(ig) + ice(ig, ik) * interlayer_dz(ig, ik)
1153           
1154            ! Calculate how close the water vapor content is to saturizing the adsorbed water
1155            if (choice_ads /= 0) preduite(ig, ik) = znsoil(ig, ik) / nsat(ig, ik)
1156           
1157            ! Write the results to the return variable
1158            pqsoil(ig, ik, igcm_h2o_vap_soil) = znsoil(ig, ik)
1159            pqsoil(ig, ik, igcm_h2o_ice_soil) = ice(ig, ik)
1160            pqsoil(ig, ik, igcm_h2o_vap_ads) = adswater(ig, ik)
1161           
1162            if (close_top(ig, ik)) then
1163                close_out(ig, ik) = 1
1164            elseif (close_bottom(ig, ik)) then
1165                close_out(ig, ik) = -1
1166            else
1167                close_out(ig, ik) = 0
1168            endif
1169        enddo
1170    endif
1171   
1172    if (watercaptag(ig)) then
1173        do ik = 1, nsoil
1174            saturation_water_ice(ig, ik) = -1
1175        enddo
1176    endif
1177   
1178    ! Convert the logical flag exchange to a numeric output
1179    if (watercaptag(ig)) then
1180        exch(ig) = -2.D0
1181    elseif (exchange(ig)) then
1182        exch(ig) = 1.D0
1183    else
1184        exch(ig) = -1.D0
1185    endif
1186enddo
1187
1188! Calculate the global total value
1189mass_h2o_tot = 0.D0
1190mass_ice_tot = 0.D0
1191do ig = 1, ngrid
1192    mass_h2o_tot = mass_h2o_tot + mass_h2o(ig) * cell_area(ig)
1193    mass_ice_tot = mass_ice_tot + mass_ice(ig) * cell_area(ig)
1194enddo
1195
1196! Increment the call number
1197n = n + 1
1198
1199! -----------------------------------------------------------------------
1200!      Output in diagfi and diagsoil
1201! -----------------------------------------------------------------------
1202
1203! Reformat flux, because it has an unusual shape
1204do ig = 1, ngrid
1205    nsurf(ig) = rhosurf(ig) * pq(ig, 1, igcm_h2o_vap)
1206   
1207    do ik = 1, nsoil - 1
1208        var_flux_soil(ig, ik) = flux(ig, ik)
1209    enddo
1210    var_flux_soil(ig, nsoil) = 0.D0
1211enddo
1212
1213#ifndef MESOSCALE
1214if (writeoutput) then
1215    zalpha(1, nsoil) = 0.D0
1216    zbeta(1, nsoil) = 0.D0
1217   
1218    call write_output("flux_soillayer", "flux of water between the soil layers", "kg m-2 s-1", var_flux_soil)
1219    call write_output("ice_saturation_soil", "Water ice saturation in the soil layers", "Percent", saturation_water_ice)
1220    call write_output("mass_h2o_soil", "Mass of subsurface water column at each point", "kg m-2", mass_h2o)
1221    call write_output("mass_ice_soil", "Mass of subsurface ice at each point", "kg m-2", mass_ice)
1222    call write_output("znsoil", "Water vapor soil concentration", "kg.m - 3 of pore air", znsoil)
1223    call write_output("nsatsoil", "subsurface water vapor saturation density", "kg/m^3", real(nsatsoil))
1224    call write_output("nsurf", "surface water vapor density", "kg/m^3", real(nsurf))
1225    call write_output("adswater", "subsurface adsorbed water", "kg/m^3", real(adswater))
1226    call write_output("flux_rego", 'flux of water from the regolith', 'kg/m^2', zdqsdifrego)
1227endif
1228#endif
1229END
Note: See TracBrowser for help on using the repository browser.