MODULE SOIL_MOD use LAKE_DATATYPES, only : ireals, iintegers use NUMERICS, only : PROGONKA, STEP use NUMERIC_PARAMS, only : vector_length contains SUBROUTINE COMSOILFORLAKE !COMSOILFORLAKE specifies parameters of soil according to soil type use NUMERIC_PARAMS use DRIVING_PARAMS use ARRAYS use ARRAYS_SOIL implicit none real(kind=ireals) :: b(1:Num_Soil) real(kind=ireals) :: psi_max(1:Num_Soil) real(kind=ireals) :: Porosity(1:Num_Soil) real(kind=ireals) :: gamma_max(1:Num_Soil) real(kind=ireals) :: lambda_max(1:Num_Soil) real(kind=ireals) :: W_0(1:Num_Soil) real(kind=ireals) :: W_m(1:Num_Soil) real(kind=ireals) :: pow integer(kind=iintegers) :: i, j logical :: firstcall data firstcall /.true./ SAVE if (firstcall) then ! allocate (AL(1:ns+2),DLT(1:ns+2),DVT(1:ns+2),DL(1:ns+2), !& ALV(1:ns+2),DV(1:ns+2),Z(1:ns+2),T(1:ns+2),WL(1:ns+2), !& WV(1:ns+2),WI(1:ns+2),dens(1:ns+2)) endif !I=1 ! SAND !I=2 ! LOAMY SAND !I=3 ! SANDY LOAM !I=4 ! LOAM !I=5 ! SILT LOAM !I=6 ! SANDY CLAY LOAM !I=7 ! CLAY LOAM !I=8 ! SILTY CLAY LOAM !I=9 ! SANDY CLAY !I=10! SILTY CLAY !I=11! CLAY !---------------------------------------------------------------- ! NN b psi_max Por gamma_max lambda_max W_0 W_m !---------------------------------------------------------------- ! 1 4.05 3.50 0.395 0.01760 0.29800 0.02 0.01 ! 2 4.38 1.78 0.410 0.01560 0.13900 0.05 0.02 ! 3 4.90 7.18 0.435 0.00340 0.13700 0.08 0.03 ! 4 5.39 14.6 0.451 0.00069 0.06190 0.20 0.08 ! 5 5.30 56.6 0.485 0.00072 0.20400 0.18 0.07 ! 6 7.12 8.63 0.420 0.00063 0.03070 0.13 0.06 ! 7 8.52 36.1 0.476 0.00024 0.03720 0.27 0.12 ! 8 7.75 14.6 0.477 0.00017 0.01240 0.24 0.11 ! 9 10.4 6.16 0.426 0.00021 0.00641 0.23 0.10 ! 10 10.4 17.4 0.492 0.00010 0.00755 0.30 0.15 ! 11 11.4 18.6 0.482 0.00013 0.00926 0.40 0.20 !----------------------------------------------------------------- zsoil(1) = 0. if (UpperLayer > 0.) then pow = log(UpperLayer/depth%par)/log(1.d0/float(ns-1)) do i = 2, ns zsoil(i) = (1.*(i-1)/(ns-1))**pow*depth%par end do else do i = 2, ns zsoil(i) = (1.*(i-1)/(ns-1))*depth%par end do end if do i = 1, ns-1 dzs(i) = zsoil(i+1) - zsoil(i) end do do i = 1, ns if (i == 1) then dzss(i) = 0.5d0*dzs(i) elseif (i == ns) then dzss(i) = 0.5d0*dzs(i-1) else dzss(i) = 0.5d0*(dzs(i-1) + dzs(i)) endif end do !SoilType = 7 b(1) = 4.05 b(2) = 4.38 b(3) = 4.90 b(4) = 5.39 b(5) = 5.30 b(6) = 7.12 b(7) = 8.52 b(8) = 7.75 b(9) = 10.4 b(10)= 10.4 b(11)= 11.4 psi_max( 1) = 3.50/100. psi_max( 2) = 1.78/100. psi_max( 3) = 7.18/100. psi_max( 4) = 14.6/100. psi_max( 5) = 56.6/100. psi_max( 6) = 8.63/100. psi_max( 7) = 36.1/100. psi_max( 8) = 14.6/100. psi_max( 9) = 6.16/100. psi_max(10) = 17.4/100. psi_max(11) = 18.6/100. Porosity( 1) = 0.395 Porosity( 2) = 0.410 Porosity( 3) = 0.435 Porosity( 4) = 0.451 Porosity( 5) = 0.485 Porosity( 6) = 0.420 Porosity( 7) = 0.476 Porosity( 8) = 0.477 Porosity( 9) = 0.426 Porosity(10) = 0.492 Porosity(11) = 0.482 gamma_max( 1) = 0.01760/100. gamma_max( 2) = 0.01560/100. gamma_max( 3) = 0.00340/100. gamma_max( 4) = 0.00069/100. gamma_max( 5) = 0.00072/100. gamma_max( 6) = 0.00063/100. gamma_max( 7) = 0.00024/100. gamma_max( 8) = 0.00017/100. gamma_max( 9) = 0.00021/100. gamma_max(10) = 0.00010/100. gamma_max(11) = 0.00013/100. lambda_max( 1) = 0.29800/10000. lambda_max( 2) = 0.13900/10000. lambda_max( 3) = 0.13700/10000. lambda_max( 4) = 0.06190/10000. lambda_max( 5) = 0.20400/10000. lambda_max( 6) = 0.03070/10000. lambda_max( 7) = 0.03720/10000. lambda_max( 8) = 0.01240/10000. lambda_max( 9) = 0.00641/10000. lambda_max(10) = 0.00755/10000. lambda_max(11) = 0.00926/10000. W_0( 1) = 0.02 W_0( 2) = 0.05 W_0( 3) = 0.08 W_0( 4) = 0.20 W_0( 5) = 0.18 W_0( 6) = 0.13 W_0( 7) = 0.27 W_0( 8) = 0.24 W_0( 9) = 0.23 W_0(10) = 0.30 W_0(11) = 0.40 W_m( 1) = 0.01 W_m( 2) = 0.02 W_m( 3) = 0.03 W_m( 4) = 0.08 W_m( 5) = 0.07 W_m( 6) = 0.06 W_m( 7) = 0.12 W_m( 8) = 0.11 W_m( 9) = 0.10 W_m(10) = 0.15 W_m(11) = 0.20 if (SoilType%par > 0) then do j = 1, ns BH(j)= b(SoilType%par) ! PARAMETER B, DIMENSOINLESS PSIMAX(j) = - psi_max(SoilType%par) ! SAT. WATER POTENTIAL, M. POR(j) = Porosity(SoilType%par) ! POROSITY, DIMENSIONLESS FLWMAX(j) = gamma_max(SoilType%par) ! SAT. HYDR. CONDUCTIVITY, M/S DLMAX(j) = lambda_max(SoilType%par)! SAT. WATER DIFFUSIVITY, ?KG/(M*SEC) WLM0(j) = W_0(SoilType%par) ! MAXIMAL UNFREEZING WATER AT 0C WLM7(j) = W_m(SoilType%par) ! MAXIMAL UNFREEZING WATER AT T<<0C end do else write(*,*) 'LAKE: Soil type is not given: STOP' STOP !do j = 1, ns ! BH(j)= BH_soil! PARAMETER B, DIMENSOINLESS ! PSIMAX(j) = PSIMAX_soil ! SAT. WATER POTENTIAL, M. ! POR(j) = POR_soil ! POROSITY, DIMENSIONLESS ! FLWMAX(j) = FLWMAX_soil ! SAT. HYDR. CONDUCTIVITY, M/S ! DLMAX(j) = DLMAX_soil ! SAT. WATER DIFFUSIVITY, ?KG/(M*SEC) ! WLM0(j) = WLM0_soil ! MAXIMAL UNFREEZING WATER AT 0C ! WLM7(j) = WLM7_soil ! MAXIMAL UNFREEZING WATER AT T<<0C !end do end if rosdry(:) = 1.2E+3 if (firstcall) firstcall=.false. RETURN END SUBROUTINE COMSOILFORLAKE SUBROUTINE SOILFORLAKE(dt,a,b,c,d,is) !SOILFORLAKE calculates profiles of temperature, liquid and solid water !content in the soil under a lake use PHYS_CONSTANTS use METH_OXYG_CONSTANTS!, only : & !& methhydrdiss, & !& alphamh, & !& nch4_d_nh2o, & !& molmass_h2o use DRIVING_PARAMS use ARRAYS use ARRAYS_SOIL use ARRAYS_METHANE use ARRAYS_BATHYM use PHYS_FUNC!, only : & !& MELTPNT, & !& TEMPMHYDRDISS, & !& UNFRWAT, & !& WL_MAX, & !& MELTINGPOINT use ATMOS!, only : & !& pressure implicit none real(kind=ireals), intent(in) :: dt !integer(kind=iintegers), intent(in) :: ix, iy !integer(kind=iintegers), intent(in) :: nx, ny integer(kind=iintegers), intent(in) :: is ! Number of soil column !integer(kind=iintegers), intent(in) :: year, month, day !real(kind=ireals) , intent(in) :: hour !real(kind=ireals) , intent(in) :: phi !real(kind=ireals) , intent(in) :: extwat, extice !real(kind=ireals) , intent(in) :: fetch real(kind=ireals), intent(inout) :: a(1:vector_length) real(kind=ireals), intent(inout) :: b(1:vector_length) real(kind=ireals), intent(inout) :: c(1:vector_length) real(kind=ireals), intent(inout) :: d(1:vector_length) !real(kind=ireals) :: Temp(1:vector_length) real(kind=ireals) :: dzmean real(kind=ireals) :: ma, mi real(kind=ireals) :: wflow, wfhigh real(kind=ireals) :: lammoist1, lammoist2 real(kind=ireals) :: surplus real(kind=ireals) :: Potphenergy real(kind=ireals) :: watavailtofreeze real(kind=ireals) :: filtr_low real(kind=ireals) :: dhwfsoil1, dhwfsoil2, dhwfsoil3, dhwfsoil4 real(kind=ireals) :: max1 real(kind=ireals) :: work, mhsep real(kind=ireals), pointer :: hicemelt real(kind=ireals) :: alp(10) real(kind=ireals) :: psiit(10) real(kind=ireals), allocatable :: pressoil(:) integer(kind=iintegers) :: i, j, k integer(kind=iintegers) :: iter, iter3 logical :: firstcall data psiit/6,3,7,2,5,4,8,1,0,0/ !/3,2,4,1,0,0,0,0,0,0/ data firstcall /.true./ SAVE !open (133, file=dir_out//'\dhwfsoil.dat', status = 'unknown') !PARAMETERS OF ITERATIONAL PROCESS ma = 10.5 !5.5 mi = 4.5 do i = 1, 8 alp(i) = 2*(mi+ma-(ma-mi)*cos((2*psiit(i)-1)/16*pi))**(-1) enddo allocate (pressoil(1:ns)) do i = 1, ns pressoil(i) = pressure + row0*g*(h1 + zsoil(i)) enddo if (tricemethhydr%par > 0.) then hicemelt => methhydrdiss else hicemelt => Lwi endif !do i=1, ns ! wlmax_i = POR(i)*ROW0/(rosdry(i)*(1-por(i))) ! BB1 = BH(i) + 2. ! csoil(i) = cr+WL1(i)*CW+WI1(i)*CI ! rosoil(i) = rosdry(i)*(1-por(i))*(1+wi1(i)+wl1(i)) ! ARG = (WL1(i)+WI1(i))/wlmax_i ! ARG = max(ARG,1.d-2) ! PSI = PSIMAX(i)*(ARG)**(-BH(i)) ! PF = log(-PSI*100.)/log(10.d0) ! IF(PF>5.1) THEN ! lamsoil(i) = 4.1E-4*418. ! ELSE ! lamsoil(i) = exp(-PF-2.7)*418. ! END IF ! wlmax_i = POR(i)*ROW0/(rosdry(i)*(1-por(i))) - wi1(i)*row0_d_roi ! ARG = (WL1(i))/wlmax_i ! ARG = max(ARG,1.d-2) ! lammoist(i) = dlmax(i)*ARG**BB1 !end do !do i=1, ns-1 ! wlmax_i=WL_MAX(por(i+1),rosdry(i+1),wi1(i+1)) ! if (wl1(i+1)/wlmax_i>0.98.or.wlmax_i<0.01) then ! filtr(i) = 0 ! else ! wlmax_i = (POR(i)+POR(i+1))*ROW0/((rosdry(i)+rosdry(i+1))*& !& (1-(por(i)+por(i+1))/2)) - (wi1(i)+wi1(i+1))/2*row0_d_roi ! filtr(i) = (flwmax(i+1)+flwmax(i))/2*((wl1(i+1)+& !& wl1(i))/2/wlmax_i)**(bh(i+1)+bh(i)+3) ! endif !enddo !SPLITTING-UP METHOD FOR TEMPERATURE EQUATION: !STEP 1: HEAT DIFFUSION !do i = 1, ns-1 ! lammoist1 = 0.5*(lammoist(i)+lammoist(i+1)) ! wsoil(i) = ( - lammoist1*(wl1(i+1)-wl1(i))/dzs(i) + & ! & filtr(i) ) *0.5*(rosdry(i)+rosdry(i+1))* & ! & (1-0.5*(por(i)+por(i+1)) )/row0 !enddo !SPLITTING-UP METHOD FOR MOISTURE EQUATION: !STEP 1: MOISTURE DIFFUSION Wflow = 0. dhwfsoil=0. dhwfsoil1=0. dhwfsoil2=0. dhwfsoil3=0. dhwfsoil4=0. if ((l1 /= 0.and. h1 == 0.).or.ls1/=0.or. & & (hs1/=0.and.l1==0.and.h1==0)) then Wfhigh = 0 !c(1)=1 !b(1)=1 !d(1)=0 c(1) = -1-dt*(lammoist(1)+lammoist(2))/(dzs(1)**2) b(1) = -dt*(lammoist(1)+lammoist(2))/(dzs(1)**2) d(1) = -wl1(1,is) endif if (h1 /= 0.and.ls1 == 0) then c(1)=1 b(1)=0 d(1)=WL_MAX(por(1),rosdry(1),wi1(1,is),tricemethhydr%par) !dhwfsoil1 = dt*(wl1(2)-wl1(1))*rosdry(1)*(1-por(1))/row0 !& /dzs(1)*(lammoist(1)+lammoist(2))/2 !- !& (WL_MAX(por(1),rosdry(1),wi1(1))-wl1(1)) VS,23.09.07 !& *rosdry(1)*(1-por(1))*dzss(1)/row0 VS,23.09.07 endif lammoist1 = (lammoist(ns-1)+lammoist(ns))/2 !c(ns)=-lammoist1/dzs(ns-1) !a(ns)=-lammoist1/dzs(ns-1) !d(ns)=Wflow c(ns) = -1-2*dt*lammoist1/dzs(ns-1)**2 a(ns) = -2*dt*lammoist1/dzs(ns-1)**2 d(ns) = -wl1(ns,is) do i=2,ns-1 lammoist2 = (lammoist(i)+lammoist(i+1))/2 lammoist1 = (lammoist(i-1)+lammoist(i))/2 dzmean = (dzs(i-1)+dzs(i))/2 a(i)=-dt/dzmean*lammoist1/dzs(i-1) b(i)=-dt/dzmean*lammoist2/dzs(i) c(i)=-dt/dzmean*(lammoist1/dzs(i-1) + & & lammoist2/dzs(i))-1 d(i)=-wl1(i,is) !wl2(i) = wl1(i)+dt*(lammoist2/dzs(i)*(wl1(i+1)-wl1(i))- !& lammoist1/dzs(i-1)*(wl1(i)-wl1(i-1)))/dzmean enddo call PROGONKA(a,b,c,d,wl2,1,ns) if (h1 /= 0.and.ls1 == 0) then lammoist1 = (lammoist(1)+lammoist(2))/2. dhwfsoil1 = -(wl2(1)*(dzs(1)/(2*dt)+lammoist1/dzs(1)) - & & wl2(2)*lammoist1/dzs(1)-wl1(1,is)*dzs(1)/(2*dt)) * & & rosdry(1)*(1-por(1))/row0*dt endif !STEP 2 OF SPLITTING-UP METHOD FOR MOISTURE EQUATION: !EVOLUTION OF MOISTURE DUE TO GRAVITATIONAL INFILTRATION do i=2,ns-1 wl3(i) = wl2(i) + dt*(filtr(i-1)-filtr(i))/dzss(i) enddo if ((h1==0.and.l1/=0).or.ls1 /= 0) then wl3(1) = wl2(1) + dt*(-filtr(1)+0)/dzss(1) endif if (h1/=0.and.ls1 == 0) then wl3(1) = WL_MAX(por(1),rosdry(1),wi1(1,is),tricemethhydr%par) dhwfsoil2 = - filtr(1)*rosdry(1)*(1-por(1))/row0*dt endif filtr_low = 0 wl3(ns) = wl2(ns) + dt*(-filtr_low+filtr(ns-1))/dzss(ns) do i=1,ns if (wl3(i)>WL_MAX(por(i),rosdry(i),wi1(i,is),tricemethhydr%par)) then surplus=wl3(i)-WL_MAX(por(i),rosdry(i),wi1(i,is),tricemethhydr%par) cy1:do j=1,ns if (WL_MAX(por(j),rosdry(j),wi1(j,is),tricemethhydr%par)-wl3(j)>0) then if (WL_MAX(por(j),rosdry(j),wi1(j,is),tricemethhydr%par) - wl3(j) > & & surplus*rosdry(i)*(1-por(i))*dzss(i) / & & (rosdry(j)*(1-por(j))*dzss(j))) then wl3(j)=wl3(j)+surplus*rosdry(i)*(1-por(i))*dzss(i) / & & (rosdry(j)*(1-por(j))*dzss(j)) surplus=0 exit cy1 else surplus = surplus - & & (WL_MAX(por(j),rosdry(j),wi1(j,is),tricemethhydr%par)-wl3(j)) * & & (rosdry(j)*(1-por(j))*dzss(j)) / & & (rosdry(i)*(1-por(i))*dzss(i)) wl3(j)=WL_MAX(por(j),rosdry(j),wi1(j,is),tricemethhydr%par) endif endif enddo cy1 dhwfsoil3 = dhwfsoil3 + surplus*rosdry(i)*(1-por(i))*dzss(i)/row0 wl3(i) = WL_MAX(por(i),rosdry(i),wi1(i,is),tricemethhydr%par) endif if(wl3(i)<0) then if (i/=1) then do j=i-1,1,-1 if (wl3(j)>-wl3(i)*rosdry(i)*(1-por(i))*dzss(i) / & & (rosdry(j)*(1-por(j))*dzss(j))) then wl3(j)=wl3(j)+wl3(i)*rosdry(i)*(1-por(i))*dzss(i) / & & (rosdry(j)*(1-por(j))*dzss(j)) goto 1 endif enddo endif if (i/=ns) then do j=i+1,ns if (wl3(j)>-wl3(i)*rosdry(i)*(1-por(i))*dzss(i) / & & (rosdry(j)*(1-por(j))*dzss(j))) then wl3(j)=wl3(j)+wl3(i)*rosdry(i)*(1-por(i))*dzss(i) / & & (rosdry(j)*(1-por(j))*dzss(j)) goto 1 endif enddo endif !dhwfsoil = dhwfsoil - abs(wl4(i))*rosdry(i)*(1-por(i))*dzss(i)/row 1 wl3(i)=0. endif enddo ! STEP 3 OF SPLITTING-UP METHOD : PHASE PROCESSES mhsep = (1. + tricemethhydr%par*alphamh) 20 c2: do i = 1, ns work = MELTINGPOINT(Sals1(i,is)/wl3(i),pressoil(i),tricemethhydr%par) if (wi1(i,is) > 0 .and. Tsoil2(i) > work + 0.01) then Potphenergy = (Tsoil2(i) - (work + 0.01)) * & & csoil(i)*rosoil(i)*dzss(i) if (Potphenergy >= wi1(i,is)*rosdry(i)*dzss(i)*(1-por(i))*hicemelt) then wl4(i,is) = wl3(i) + wi1(i,is)/mhsep wi2(i,is) = 0.d0 Tsoil3(i,is) = work + 0.01 + & & (Potphenergy-(wi1(i,is)*rosdry(i)*dzss(i)* & & (1 - por(i))*hicemelt))/(csoil(i)*rosoil(i)*dzss(i)) else wl4(i,is) = wl3(i) + Potphenergy / & & (rosdry(i)*dzss(i)*(1 - por(i))*hicemelt)/mhsep wi2(i,is) = wi1(i,is) - Potphenergy / & & (rosdry(i)*dzss(i)*(1 - por(i))*hicemelt) Tsoil3(i,is) = work + 0.01 endif else if (wl3(i) >= 0 .and. Tsoil2(i) < work - 0.01) then Potphenergy = - (Tsoil2(i) - work + 0.01) * & & csoil(i)*rosoil(i)*dzss(i) watavailtofreeze = (wl3(i) - UNFRWAT(Tsoil2(i),i)) * & & rosdry(i)*dzss(i)*(1 - por(i))*mhsep*hicemelt if (watavailtofreeze < 0) then !cc = csoil(i)*rosoil(i)*dzss(i) !cc1 = rosdry(i)*dzss(i)*(1-por(i))*Lwi !bb = (-Potphenergy-0.1*cc-wl3(i)*cc1)/cc !aa = cc1/cc !call phase_iter(aa,bb,i,Tsoil3(i)) Tsoil3(i,is) = Tsoil2(i) + watavailtofreeze/(csoil(i)*rosoil(i)*dzss(i)) wi2(i,is) = wi1(i,is) + (wl3(i) - UNFRWAT(Tsoil2(i),i))*mhsep wl4(i,is) = UNFRWAT(Tsoil2(i),i) cycle c2 endif if (Potphenergy >= watavailtofreeze) then Tsoil3(i,is) = work - 0.01 - & & (Potphenergy - watavailtofreeze) / & & (csoil(i)*rosoil(i)*dzss(i)) wi2(i,is) = wi1(i,is) + (wl3(i) - UNFRWAT(Tsoil2(i),i))*mhsep wl4(i,is) = UNFRWAT(Tsoil2(i),i) else wl4(i,is) = wl3(i) - Potphenergy/(rosdry(i)*dzss(i)*(1 - por(i))*hicemelt)/mhsep wi2(i,is) = wi1(i,is) + Potphenergy/(rosdry(i)*dzss(i)*(1 - por(i))*hicemelt) Tsoil3(i,is) = work - 0.01 endif else wl4(i,is) = wl3(i) wi2(i,is) = wi1(i,is) Tsoil3(i,is) = Tsoil2(i) endif endif enddo c2 max1 = 0. do i = 1, ns if (Tsoil3(i,is) < & & MELTINGPOINT(Sals1(i,is)/wl4(i,is),pressoil(i),tricemethhydr%par) - 0.01 & &.and. abs(wl4(i,is) - UNFRWAT(Tsoil3(i,is),i)) > max1) then max1 = abs(wl4(i,is) - UNFRWAT(Tsoil3(i,is),i)) endif enddo if (max1 > 0.01 .and. iter3 < 20) then !wl3=(wl4+wl3)/2. !wi1=(wi2+wi1)/2. !Tsoil2=(Tsoil3+Tsoil2)/2. wl3 = wl3 + alp(iter+1)*(wl4(:,is)-wl3) wi1(:,is) = wi1(:,is) + & & alp(iter+1)*(wi2(:,is) - wi1(:,is)) Tsoil2 = Tsoil2 + alp(iter+1)*(Tsoil3(:,is)-Tsoil2) iter = iter + 1 iter3 = iter3 + 1 if(iter == 8) iter = 0 goto 20 else iter = 0 iter3 = 0 endif !evol=0 do i = 1, ns if (wi2(i,is) < 0) then wl4(i,is) = wl4(i,is) + wi2(i,is)/mhsep wi2(i,is) = 0 endif enddo ! Methane generation due to methane hydrate dissociation do i = 1, ns methgenmh(i) = - tricemethhydr%par*(wi2(i,is) - wi1(i,is))*1.d+3 / & & (dt*mhsep*molmass_h2o)*nch4_d_nh2o*rosdry(i)*(1. - por(i)) enddo do i=1,ns if (wl4(i,is) > & & POR(i)*ROW0/(rosdry(i)*(1-por(i))) - wi2(i,is)*row0_d_roi) then surplus = wl4(i,is) - & & (POR(i)*ROW0/(rosdry(i)*(1-por(i))) - wi2(i,is)*row0_d_roi) c3:do j=1,ns if (POR(j)*ROW0/(rosdry(j)*(1-por(j))) - wi2(j,is)*row0_d_roi - & & wl4(j,is) > 0) then if (POR(j)*ROW0/(rosdry(j)*(1-por(j))) - wi2(j,is)*row0_d_roi - & & wl4(j,is) > surplus*rosdry(i)*(1 - por(i))*dzss(i) / & & (rosdry(j)*(1-por(j))*dzss(j))) then wl4(j,is)=wl4(j,is)+surplus*rosdry(i)*(1-por(i))*dzss(i) / & & (rosdry(j)*(1-por(j))*dzss(j)) surplus=0 exit c3 else surplus=surplus-(POR(j)*ROW0/(rosdry(j)*(1-por(j))) - & & wi2(j,is)*row0_d_roi-wl4(j,is)) * & & (rosdry(j)*(1-por(j))*dzss(j)) / & & (rosdry(i)*(1-por(i))*dzss(i)) wl4(j,is) = & & POR(j)*ROW0/(rosdry(j)*(1-por(j))) - wi2(j,is)*row0_d_roi endif endif enddo c3 dhwfsoil4 = dhwfsoil4 + surplus*rosdry(i)*(1-por(i))*dzss(i)/row0 wl4(i,is) = & & POR(i)*ROW0/(rosdry(i)*(1-por(i))) - wi2(i,is)*row0_d_roi endif if(wl4(i,is) < 0) then if (i/=1) then do j=i-1,1,-1 if (wl4(j,is) > - wl4(i,is)*rosdry(i)*(1-por(i))*dzss(i) / & & (rosdry(j)*(1-por(j))*dzss(j))) then wl4(j,is) = wl4(j,is) + & & wl4(i,is)*rosdry(i)*(1-por(i))*dzss(i) / & & (rosdry(j)*(1-por(j))*dzss(j)) goto 2 endif enddo endif if (i/=ns) then do j=i+1,ns if (wl4(j,is) > -wl4(i,is)*rosdry(i)*(1-por(i))*dzss(i) / & & (rosdry(j)*(1-por(j))*dzss(j))) then wl4(j,is) = wl4(j,is) + & & wl4(i,is)*rosdry(i)*(1-por(i))*dzss(i) / & & (rosdry(j)*(1-por(j))*dzss(j)) goto 2 endif enddo endif !dhwfsoil = dhwfsoil - abs(wl4(i))*rosdry(i)*(1-por(i))*dzss(i)/row 2 wl4(i,is) = 0 endif enddo !!!!! II. FREEZING AND MELTING IN CASE OF TSOIL<MELTING POINT (O C)!!!!! !do i=1, ns ! if (Tsoil3(i)<-1.) then ! wi3(i) = wi2(i) + (wl4(i)-unfrwat(Tsoil3(i),i)) ! wl5(i) = unfrwat(Tsoil3(i),i) ! Tsoil4(i) = Tsoil3(i) + & ! (wl4(i)-unfrwat(Tsoil3(i),i))*rosdry(i)*dzss(i)*(1-por(i))*Lwi/& ! (csoil(i)*rosoil(i)*dzss(i)) ! else ! wi3(i) = wi2(i) ! wl5(i) = wl4(i) ! Tsoil4(i) = Tsoil3(i) ! end if ! if (wl5(i)>POR(i)*ROW/(rosdry(i)*(1-por(i))) - wi3(i)*row/roi) then ! surplus = wl5(i)-(POR(i)*ROW/(rosdry(i)*(1-por(i))) - wi3(i)*row/roi) ! dhwfsoil = dhwfsoil + surplus*rosdry(i)*(1-por(i))*dzss(i)/row ! wl5(i) = POR(i)*ROW/(rosdry(i)*(1-por(i))) - wi3(i)*row/roi ! endif ! if(wl5(i)<0) then ! dhwfsoil = dhwfsoil - abs(wl5(i))*rosdry(i)*(1-por(i))*dzss(i)/row ! wl5(i)=0 ! endif !enddo ! evol=0 ! evol1=0 ! do i=1,ns ! evol=evol+(Tsoil3(i)-Tsoil1(i))*rosoil(i)*csoil(i)*dzss(i) ! evol1=evol1+(wi2(i)-wi1(i))*rosdry(i)*(1-por(i))*dzss(i)*Lwi ! enddo dhwfsoil = dhwfsoil1 + dhwfsoil2 + dhwfsoil3 + dhwfsoil4 Tsoil1(:,is) = Tsoil3(:,is) wl1 (:,is) = wl4 (:,is) wi1 (:,is) = wi2 (:,is) ! Diagnostic calculation of air content, kg/kg ! (air mass per unit mass of the dry soil) ! assuming that the air occupies all the pore space ! free from liquid water and ice do i = 1, ns wa(i) = por(i)*roa0/((1.-por(i))*rosdry(i)) - & & roa0_d_row0*wl1(i,is) - roa0_d_roi*wi1(i,is) wa(i) = max(wa(i), 0.d0) enddo deallocate(pressoil) if (firstcall) firstcall=.false. RETURN END SUBROUTINE SOILFORLAKE SUBROUTINE SOIL_COND_HEAT_COEF(is) use ARRAYS_SOIL, only : rosdry,csoil,rosoil,lamsoil, & lammoist,filtr,wsoil,por,bh,wl1,wi1,psimax,flwmax,dlmax,dzs use ARRAYS_GRID, only : nsoilcols use DRIVING_PARAMS, only : ns, tricemethhydr use PHYS_CONSTANTS, only : & & row0, & & cw, & & ci, & & roi, & & row0_d_roi use PHYS_FUNC, only : & & WL_MAX, & & SOIL_COND_JOHANSEN use METH_OXYG_CONSTANTS, only : & & cpmethhydr implicit none ! Input variables integer(kind=iintegers), intent(in) :: is real(kind=ireals), parameter :: cr = 0.2*4180.d0 real(kind=ireals) :: wlmax_i real(kind=ireals) :: bb1 real(kind=ireals) :: arg real(kind=ireals) :: psi real(kind=ireals) :: pf real(kind=ireals) :: lammoist1 real(kind=ireals), save, pointer :: cimh integer(kind=iintegers) :: i logical, save :: firstcall = .true. if (firstcall) then if (tricemethhydr%par > 0.) then cimh => cpmethhydr else cimh => ci endif endif !rosdry(:) = 1200. !2400. do i = 1, ns wlmax_i = POR(i)*ROW0/(rosdry(i)*(1-por(i))) BB1 = BH(i) + 2.d0 csoil(i) = (cr + wl1(i,is)*CW + wi1(i,is)*cimh) !*1.d-3 !1.d-3 - for sensitivity experiment rosoil(i) = rosdry(i)*(1 - por(i))*(1 + wi1(i,is) + wl1(i,is)) ! ARG = (WL1(i)+WI1(i))/wlmax_i ! ARG = max(ARG,1.d-2) ! PSI = PSIMAX(i)*(ARG)**(-BH(i)) ! PF = log(-PSI*100.)/log(10.d0) ! if(PF>5.1) then ! lamsoil(i) = 4.1E-4*418. ! else ! lamsoil(i) = exp(-PF-2.7)*418. ! end if lamsoil(i) = SOIL_COND_JOHANSEN(wl1(i,is),wi1(i,is),rosdry(i),por(i)) wlmax_i = WL_MAX(por(i),rosdry(i),wi1(i,is),tricemethhydr%par) ARG = (wl1(i,is))/wlmax_i ARG = max(ARG,1.d-2) lammoist(i) = dlmax(i)*ARG**BB1 end do do i = 1, ns-1 wlmax_i = WL_MAX(por(i+1),rosdry(i+1),wi1(i+1,is),tricemethhydr%par) if (wlmax_i < 0.01) then !wl1(i+1,is)/wlmax_i>0.98.or. filtr(i) = 0 else wlmax_i = WL_MAX(0.5*(por(i)+por(i+1)),0.5*(rosdry(i)+rosdry(i+1)), & & 0.5*(wi1(i,is) + wi1(i+1,is)),tricemethhydr%par) filtr(i) = 0.5*(flwmax(i+1)+flwmax(i))*(0.5*(wl1(i+1,is) + & & wl1(i,is))/wlmax_i)**(bh(i+1)+bh(i)+3) endif enddo do i = 1, ns-1 lammoist1 = 0.5*(lammoist(i)+lammoist(i+1)) wsoil(i) = ( - lammoist1*(wl1(i+1,is) - wl1(i,is))/dzs(i) + & & filtr(i) ) *0.5*(rosdry(i)+rosdry(i+1))* & & (1. - 0.5*(por(i)+por(i+1)) )/row0 enddo if (firstcall) firstcall = .false. END SUBROUTINE SOIL_COND_HEAT_COEF SUBROUTINE SOILCOLSTEMP(gs,gsp,dt,ls,ftot,ch4_pres_atm, & & ddz,ddzi,zsoilcols, & & wst,SR,a,b,c,d,add_to_winter, & & bathymwater,bathymice, & & bathymdice,bathymsoil, & & soilflux,fdiffbot, contr) ! Subroutine calculates temperature in soil columns, ! excepting for the lowest column, assuming ! nsoilcols = M+1 use LAKE_DATATYPES, only : & & iintegers, ireals use DRIVING_PARAMS, only : soilcolconjtype use T_SOLVER_MOD, only : & & T_DIFF use ATMOS, only : & & pressure, wind10 use PHYS_CONSTANTS, only : & & cw_m_row0, z0_bot use PHYS_FUNC, only : & & LOGFLUX, TEMPWATR use ARRAYS_BATHYM, only : bathym, dhw, dhw0, layers_type use ARRAYS_SOIL, only : csoil, rosoil, lamsoil, Tsoil3, Tsoil2, Tsoil1, & & wl4,wi2,wa,Sals1,rosdry,por,lsm,dzs,zsoil,rosoil use ARRAYS_GRID, only : ddz05, gridsize_type, gridspacing_type use ARRAYS_METHANE, only : veg,TgrAnn,methgenmh,qwater,lammeth, & & fplant,febul0, fdiff_lake_surf, & & plant_sum,bull_sum,oxid_sum,rprod_sum, anox, & & rprod_total_oldC,rprod_total_newC, & & ice_meth_oxid_total, & & h_talik,tot_ice_meth_bubbles,rootss use ARRAYS_WATERSTATE, only : Tw2, waterstate_type use ARRAYS_TURB, only: eps1 use ARRAYS_OXYGEN, only : sodbot use ARRAYS, only : gas, dt_inv use METHANE_MOD, only : METHANE use METH_OXYG_CONSTANTS, only : CH4_exp_growth implicit none ! Input variables type(gridsize_type), intent(inout) :: gs type(gridspacing_type), intent(in) :: gsp type(layers_type), intent(in) :: ls real(kind=ireals), intent(in) :: dt !> timestep, st real(kind=ireals), intent(inout) :: ftot real(kind=ireals), intent(in) :: ch4_pres_atm real(kind=ireals), intent(in) :: ddz(1:gs%M), ddzi(1:gs%Mice), zsoilcols(1:gs%nsoilcols+1) type(waterstate_type), intent(in) :: wst real(kind=ireals), intent(in) :: SR(0:gs%M+1) ! Shortwave radiation type(bathym), intent(in) :: bathymwater(1:gs%M+1), bathymice(1:gs%Mice+1) type(bathym), intent(in) :: bathymdice(1:gs%Mice+1), bathymsoil(1:gs%nsoilcols+1) integer(kind=iintegers), intent(in) :: contr(1:2) real(kind=ireals), intent(inout), dimension(1:vector_length) :: a, b, c, d logical, intent(inout) :: add_to_winter ! Output variables real(kind=ireals), intent(inout) :: soilflux(1:gs%nsoilcols), fdiffbot(1:gs%nsoilcols) ! Local variables integer(kind=iintegers), parameter :: bcswitch = 1 !1 - continuity of flux and temperature !2 - continuity of flux, calculated from surface layer theory integer(kind=iintegers) :: is, i ! Number of soil column real(kind=ireals) :: Tsoilsurf(1:gs%nsoilcols), qsoilsurf(1:gs%nsoilcols) real(kind=ireals) :: exchcoef, Tws, qwaters real(kind=ireals), allocatable :: work(:), work1(:) integer(kind=iintegers), allocatable :: iwork(:) real(kind=ireals) :: xx if ((ls%l1 /= 0. .or. ls%ls1 /= 0) .and. bcswitch == 2) then print*, "bcswitch == 2 is not operational when & &l1 /= 0. .or. ls1 /= 0", ls%l1, ls%ls1 STOP endif if (bcswitch == 2) then allocate(work1(1:gs%nsoilcols)) allocate(iwork(1:gs%nsoilcols)) if (soilcolconjtype == 1) then forall(is=1:gs%nsoilcols-1) work1(is) = bathymsoil(is)%dzSLc forall(is=1:gs%nsoilcols-1) iwork(is) = bathymsoil(is)%icent elseif (soilcolconjtype == 2) then forall(is=1:gs%nsoilcols-1) work1(is) = bathymsoil(is)%dzSL forall(is=1:gs%nsoilcols-1) iwork(is) = bathymsoil(is)%itop endif endif if (contr(1) == 1) then ! Heat equation in soil columns if (bcswitch == 1) then ! Continuity of flux and temperature across soil-water interface if (soilcolconjtype == 1) then do is = 1, gs%nsoilcols-1 i = bathymsoil(is)%icent Tsoilsurf(is) = wst%Tw1(i) enddo elseif (soilcolconjtype == 2) then call TSURFSOILCOL(gs%M,gs%Mice,gs%nsoilcols,ls%h1,ls%l1,ls%ls1, & & ddz,ddzi,zsoilcols, & & wst%Tw1,wst%Ti1,wst%Tis1, & & bathymwater,bathymice,bathymdice,bathymsoil,& & Tsoilsurf) endif do is = 1, gs%nsoilcols-1 call SOIL_COND_HEAT_COEF(is) call T_DIFF(1,Tsoilsurf(is),dt,0,0,0,0,is,.false.) soilflux(is) = & & csoil(1)*rosoil(1)*dt_inv*0.5*dzs(1)*( Tsoil2(1) - Tsoil1(1,is) ) - & & 0.25* ( lamsoil(1) + lamsoil(2) ) * & & ( Tsoil2(2) + Tsoil1(2,is) - Tsoil2(1) - Tsoil1(1,is) )/dzs(1) call SOILFORLAKE(dt,a,b,c,d,is) enddo elseif (bcswitch == 2) then ! continuity of flux, calculated from surface layer theory above soil surface do is = 1, gs%nsoilcols-1 call SOIL_COND_HEAT_COEF(is) i = iwork(is) soilflux(is) = LOGFLUX(sqrt(wst%u1(i)*wst%u1(i) + wst%v1(i)*wst%v1(i)), & & Tsoil1(1,is) - wst%Tw1(i), work1(is), z0_bot, z0_bot, cw_m_row0, 1) + SR(i) call T_DIFF(1,soilflux(is),dt,0,0,0,0,is,.true.) call SOILFORLAKE(dt,a,b,c,d,is) enddo endif endif if (contr(2) == 1) then ! Methane equation in soil columns if (bcswitch == 1) then ! Continuity of flux and concentration across soil-water interface if (soilcolconjtype == 1) then do is = 1, gs%nsoilcols-1 i = bathymsoil(is)%icent qsoilsurf(is) = qwater(i,1) enddo elseif (soilcolconjtype == 2) then allocate (work(1:gs%Mice+1)); work = 0. call TSURFSOILCOL(gs%M,gs%Mice,gs%nsoilcols,ls%h1,ls%l1,ls%ls1, & & ddz,ddzi,zsoilcols, & & qwater(1,1),work,work, & & bathymwater,bathymice,bathymdice,bathymsoil,& & qsoilsurf) deallocate (work) endif allocate (work(0:gs%M+1)) do is = 1, gs%nsoilcols-1 gs%isoilcol = is call METHANE & & (gas,pressure,wind10,ch4_pres_atm,zsoil,Tsoil3(1,is),rosoil, & & work, work, & & wl4(1,is),wi2(1,is),wa,Sals1, & & rootss,rosdry,por,veg,qsoilsurf(is)*por(1),TgrAnn, methgenmh, & & ddz,ddz05, wst, lammeth, & & gsp%z_half(bathymsoil(is)%icent), & !0.5*(zsoilcols(is) + zsoilcols(is+1)), & & ls, dhw, dhw0, .false., .false., lsm, bathymwater, & & fplant, febul0(is), fdiffbot(is), ftot, fdiff_lake_surf, & & plant_sum,bull_sum,oxid_sum,rprod_sum, & & anox,gs,gsp,dt,eps1(1),sodbot, & & rprod_total_oldC, rprod_total_newC, ice_meth_oxid_total, & & h_talik,tot_ice_meth_bubbles,add_to_winter) enddo deallocate(work) elseif (bcswitch == 2) then! continuity of flux, calculated from surface layer theory above soil surface allocate (work(0:gs%M+1)) do is = 1, gs%nsoilcols-1 i = iwork(is) ! Exchange coefficient !exchcoef = LOGFLUX(sqrt(wst%u1(i)*wst%u1(i) + wst%v1(i)*wst%v1(i)), & !& qsoil(1,is)/por(1) - qwater(i,1), bathymsoil(is)%dzSL, z0_bot, z0_bot, 1._ireals,2) ! Methane concentration in water from similarity profile !qwaters = TEMPWATR(lammeth(i),bathymwater(i)%rad_int,qsoil(1,is)/por(1),exchcoef, & !& qwater(i,1), lammeth(i)*(qwater(i+1,1) - qwater(i,1))/(ddz(i)*h1)) ! Methane flux at the bottom ! Taking into account depletion of methane in top sediments if (CH4_exp_growth /= 0.) then xx = CH4_exp_growth*0.5*dzs(1) / ( (exp(CH4_exp_growth*0.5*dzs(1)) - 1.) * por(1) ) else xx = 1./por(1) endif fdiffbot(is) = LOGFLUX(sqrt(wst%u1(i)*wst%u1(i) + wst%v1(i)*wst%v1(i)), & & gas%qsoil(1,is)*xx - qwater(i,1), work1(is), & & z0_bot, z0_bot, 1._ireals,1) gs%isoilcol = is call METHANE & & (gas,pressure,wind10,ch4_pres_atm,zsoil,Tsoil3(1,is),rosoil, & & work, work, & & wl4(1,is),wi2(1,is),wa,Sals1, & & rootss,rosdry,por,veg,fdiffbot(is),TgrAnn, methgenmh, & & ddz,ddz05, wst, lammeth, & & gsp%z_half(bathymsoil(is)%icent), & !0.5*(zsoilcols(is) + zsoilcols(is+1)), & & ls, dhw, dhw0, .false., .true., lsm, bathymwater, & & fplant, febul0(is), fdiffbot(is), ftot, fdiff_lake_surf, & & plant_sum,bull_sum,oxid_sum,rprod_sum, & & anox,gs,gsp,dt,eps1(1),sodbot, & & rprod_total_oldC, rprod_total_newC, ice_meth_oxid_total, & & h_talik,tot_ice_meth_bubbles,add_to_winter) enddo deallocate(work) endif endif if (bcswitch == 2) then deallocate(work1) deallocate(iwork) endif END SUBROUTINE SOILCOLSTEMP SUBROUTINE TSURFSOILCOL(M,Mice,nsoilcols,h1,l1,ls1,ddz,ddzi,zsoilcols, & & Tw1,Ti1,Tis1, & & bathymwater,bathymice,bathymdice,bathymsoil, & & Tsoilsurf) ! Subroutine TSURFSOILCOL calculates mean temperature ! of a lake cross-section over specified depth intervals use NUMERIC_PARAMS!, only : & !& small_value, pi use ARRAYS_BATHYM, bathymwater_=>bathymwater,bathymice_=>bathymice, & & bathymsoil_=>bathymsoil,bathymdice_=>bathymdice,& & h1_=>h1,l1_=>l1,ls1_=>ls1!, only : & !& bathym implicit none !Input variables integer(kind=iintegers), intent(in) :: M, Mice, nsoilcols real(kind=ireals), intent(in) :: h1, l1, ls1 real(kind=ireals), intent(in) :: ddz(1:M), ddzi(1:Mice) real(kind=ireals), intent(in) :: zsoilcols(1:nsoilcols+1) real(kind=ireals), intent(in) :: Tw1(1:M+1) real(kind=ireals), intent(in) :: Ti1(1:Mice+1), Tis1(1:Mice+1) type(bathym), intent(in) :: bathymwater(1:M+1) , bathymice(1:Mice+1) type(bathym), intent(in) :: bathymdice(1:Mice+1), bathymsoil(1:nsoilcols+1) !Output variables real(kind=ireals), intent(out) :: Tsoilsurf(1:nsoilcols) ! Local variables integer(kind=iintegers) :: i, j, j0, j1, nl real(kind=ireals), allocatable :: Temp(:), z(:), per(:), dlx(:), dly(:), aell(:), bell(:) real(kind=ireals) :: pers,dz,aells,bells,areas,area,dlxs,dlys !type(bathym), allocatable :: bathymall(:) logical, save :: firstcall = .true. ! Water, ice and deep ice if (l1 > small_value .and. & & h1 > small_value .and. & & ls1 > small_value) then nl = 2*Mice + M allocate (Temp(1:nl+1), z(0:nl+1), per(0:nl+1), dlx(0:nl+1), dly(0:nl+1)) allocate (aell(0:nl+1), bell(0:nl+1)) ! allocate (bathymall(1:nl+1)) ! Ice top z(0) = 0. ; z(1) = 0.5*ddzi(1)*l1 aell(0) = 0.5*bathymice(1)%Lx ; aell(1) = 0.5*bathymice(1)%Lx_half bell(0) = 0.5*bathymice(1)%Ly ; bell(1) = 0.5*bathymice(1)%Ly_half Temp(1) = Ti1(1) j = 2 ! Ice interior do i = 2, Mice Temp(j) = Ti1(i) aell(j) = 0.5*bathymice(i)%Lx_half bell(j) = 0.5*bathymice(i)%Ly_half z(j) = z(j-1) + 0.5*(ddzi(i-1) + ddzi(i))*l1 j = j + 1 enddo ! Ice-water interface Temp(j) = Ti1(Mice+1) z(j) = z(j-1) + 0.5*(ddzi(Mice)*l1 + ddz(1)*h1) aell(j) = 0.5*bathymwater(1)%Lx_half bell(j) = 0.5*bathymwater(1)%Ly_half j = j + 1 ! Water interior do i = 2, M Temp(j) = Tw1(i) aell(j) = 0.5*bathymwater(i)%Lx_half bell(j) = 0.5*bathymwater(i)%Ly_half z(j) = z(j-1) + 0.5*(ddz(i-1) + ddz(i))*h1 j = j + 1 enddo ! Water-deepice interface Temp(j) = Tw1(M+1) z(j) = z(j-1) + 0.5*(ddz(M)*h1 + ddzi(1)*ls1) aell(j) = 0.5*bathymdice(1)%Lx_half bell(j) = 0.5*bathymdice(1)%Ly_half j = j + 1 ! Deepice interior do i = 2, Mice Temp(j) = Tis1(i) aell(j) = 0.5*bathymdice(i)%Lx_half bell(j) = 0.5*bathymdice(i)%Ly_half z(j) = z(j-1) + 0.5*(ddzi(i-1) + ddzi(i))*ls1 j = j + 1 enddo ! Deepice bottom Temp(j) = Tis1(Mice+1) z(j) = z(j-1) + 0.5*ddzi(Mice)*ls1 aell(j) = 0.5*bathymdice(Mice+1)%Lx bell(j) = 0.5*bathymdice(Mice+1)%Ly z(:) = z(:) + zsoilcols(nsoilcols+1) - h1 - l1 - ls1 endif ! Water and ice if (l1 > small_value .and. & & h1 > small_value .and. & & ls1 < small_value) then nl = Mice + M allocate (Temp(1:nl+1), z(0:nl+1), per(0:nl+1), dlx(0:nl+1), dly(0:nl+1)) allocate (aell(0:nl+1), bell(0:nl+1)) ! allocate (bathymall(1:nl+1)) ! Ice top z(0) = 0. ; z(1) = 0.5*ddzi(1)*l1 aell(0) = 0.5*bathymice(1)%Lx ; aell(1) = 0.5*bathymice(1)%Lx_half bell(0) = 0.5*bathymice(1)%Ly ; bell(1) = 0.5*bathymice(1)%Ly_half Temp(1) = Ti1(1) j = 2 do i = 2, Mice Temp(j) = Ti1(i) aell(j) = 0.5*bathymice(i)%Lx_half bell(j) = 0.5*bathymice(i)%Ly_half z(j) = z(j-1) + 0.5*(ddzi(i-1) + ddzi(i))*l1 j = j + 1 enddo ! Ice-water interface Temp(j) = Ti1(Mice+1) z(j) = z(j-1) + 0.5*(ddzi(Mice)*l1 + ddz(1)*h1) aell(j) = 0.5*bathymwater(1)%Lx_half bell(j) = 0.5*bathymwater(1)%Ly_half j = j + 1 ! Water interior do i = 2, M Temp(j) = Tw1(i) aell(j) = 0.5*bathymwater(i)%Lx_half bell(j) = 0.5*bathymwater(i)%Ly_half z(j) = z(j-1) + 0.5*(ddz(i-1) + ddz(i))*h1 j = j + 1 enddo ! Water bottom Temp(j) = Tw1(M+1) z(j) = z(j-1) + 0.5*ddz(M)*h1 aell(j) = 0.5*bathymwater(M+1)%Lx bell(j) = 0.5*bathymwater(M+1)%Ly z(:) = z(:) + zsoilcols(nsoilcols+1) - h1 - l1 endif ! Water and deep ice if (l1 < small_value .and. & & h1 > small_value .and. & & ls1 > small_value) then nl = Mice + M allocate (Temp(1:nl+1), z(0:nl+1), per(0:nl+1), dlx(0:nl+1), dly(0:nl+1)) allocate (aell(0:nl+1), bell(0:nl+1)) ! allocate (bathymall(1:nl+1)) ! Water top z(0) = 0. ; z(1) = 0.5*ddz(1)*h1 aell(0) = 0.5*bathymwater(1)%Lx ; aell(1) = 0.5*bathymwater(1)%Lx_half bell(0) = 0.5*bathymwater(1)%Ly ; bell(1) = 0.5*bathymwater(1)%Ly_half Temp(1) = Tw1(1) j = 2 ! Water interior do i = 2, M Temp(j) = Tw1(i) aell(j) = 0.5*bathymwater(i)%Lx_half bell(j) = 0.5*bathymwater(i)%Ly_half z(j) = z(j-1) + 0.5*(ddz(i-1) + ddz(i))*h1 j = j + 1 enddo ! Water-deepice interface Temp(j) = Tw1(M+1) z(j) = z(j-1) + 0.5*(ddz(M)*h1 + ddzi(1)*ls1) aell(j) = 0.5*bathymdice(1)%Lx_half bell(j) = 0.5*bathymdice(1)%Ly_half j = j + 1 ! Deep ice interior do i = 2, Mice Temp(j) = Tis1(i) aell(j) = 0.5*bathymdice(i)%Lx_half bell(j) = 0.5*bathymdice(i)%Ly_half z(j) = z(j-1) + 0.5*(ddzi(i-1) + ddzi(i))*ls1 j = j + 1 enddo ! Deepice bottom Temp(j) = Tis1(Mice+1) z(j) = z(j-1) + 0.5*ddzi(Mice)*ls1 aell(j) = 0.5*bathymdice(Mice+1)%Lx bell(j) = 0.5*bathymdice(Mice+1)%Ly z(:) = z(:) + zsoilcols(nsoilcols+1) - h1 - ls1 endif ! Water only if (l1 < small_value .and. & & h1 > small_value .and. & & ls1 < small_value) then nl = M allocate (Temp(1:nl+1), z(0:nl+1), per(0:nl+1), dlx(0:nl+1), dly(0:nl+1)) allocate (aell(0:nl+1), bell(0:nl+1)) ! allocate (bathymall(1:nl+1)) ! Water top z(0) = 0. ; z(1) = 0.5*ddz(1)*h1 aell(0) = 0.5*bathymwater(1)%Lx ; aell(1) = 0.5*bathymwater(1)%Lx_half bell(0) = 0.5*bathymwater(1)%Ly ; bell(1) = 0.5*bathymwater(1)%Ly_half Temp(1) = Tw1(1) j = 2 do i = 2, M Temp(j) = Tw1(i) aell(j) = 0.5*bathymwater(i)%Lx_half bell(j) = 0.5*bathymwater(i)%Ly_half z(j) = z(j-1) + 0.5*(ddz(i-1) + ddz(i))*h1 j = j + 1 enddo ! Water bottom Temp(j) = Tw1(M+1) z(j) = z(j-1) + 0.5*ddz(M)*h1 aell(j) = 0.5*bathymwater(M+1)%Lx bell(j) = 0.5*bathymwater(M+1)%Ly z(:) = z(:) + zsoilcols(nsoilcols+1) - h1 endif !! Cross-section parameters calculation, assuming elliptic shape !do i = 0, nl+1 ! per(i) = ELLAR(aell(i),bell(i)) !enddo !! Assuming cross-section area reduces with depth !do i = 0, nl ! dlx(i) = aell(i) - aell(i+1) ! dly(i) = bell(i) - bell(i+1) ! dlx(i) = sqrt(( z(i+1) - z(i) ) * ( z(i+1) - z(i) ) + dlx(i)*dlx(i)) ! dly(i) = sqrt(( z(i+1) - z(i) ) * ( z(i+1) - z(i) ) + dly(i)*dly(i)) !enddo do i = 1, nsoilcols-1 ! Except for the lowest soil column ! Seeking the gridcells falling into the depth interval of current soil column if (zsoilcols(i) < z(0)) then j0 = 1 else do j = 0, nl if (z(j) <= zsoilcols(i) .and. z(j+1) > zsoilcols(i)) then j0 = j+1 exit endif enddo endif do j = j0, nl if (z(j) <= zsoilcols(i+1) .and. z(j+1) > zsoilcols(i+1)) then j1 = j+1 exit endif enddo ! Integrating temperature over the range of depths of current soil column, ! assuming at least two numerical layers overlay with this range. ! The bottom temperature is areally-averaged. areas = 0. Tsoilsurf(i) = 0. ! Top numerical layer, overlapping with the soil column depth interval if (zsoilcols(i) > z(j0-1)) then ! Soil column top is inside the numerical layer !dz = z(j0) - zsoilcols(i) aells = 0.5*bathymsoil(i)%Lx; bells = 0.5*bathymsoil(i)%Ly !pers = ELLAR(aells,bells) !dlxs = sqrt((aells - aell(j0))*(aells - aell(j0)) + dz*dz) !dlys = sqrt((bells - bell(j0))*(bells - bell(j0)) + dz*dz) !area = 0.25*(per(j0) + pers)*(dlxs + dlys) area = pi*(aells*bells - aell(j0)*bell(j0)) Tsoilsurf(i) = Tsoilsurf(i) + Temp(j0)*area !(zsoilcols(i+1) - z(j1-1)) areas = areas + area else ! Soil column top is outside the numerical layer (j0 = 1) ! area = 0.25*(per(j0-1) + per(j0))*(dlx(j0-1) + dly(j0-1)) area = pi*(aell(j0-1)*bell(j0-1) - aell(j0)*bell(j0)) Tsoilsurf(i) = Tsoilsurf(i) + Temp(j0)*area !(z(j) - z(j-1)) areas = areas + area endif ! Interior numerical layers if (j0+1 <= j1-1) then do j = j0+1, j1-1 !area = 0.25*(per(j-1) + per(j))*(dlx(j-1) + dly(j-1)) area = pi*(aell(j-1)*bell(j-1) - aell(j)*bell(j)) Tsoilsurf(i) = Tsoilsurf(i) + Temp(j)*area !(z(j) - z(j-1)) areas = areas + area enddo endif ! Lowest numerical layer, overlapping with the soil column depth interval !dz = zsoilcols(i+1) - z(j1-1) aells = 0.5*bathymsoil(i+1)%Lx; bells = 0.5*bathymsoil(i+1)%Ly !pers = ELLAR(aells,bells) !dlxs = sqrt((aell(j1-1) - aells)*(aell(j1-1) - aells) + dz*dz) !dlys = sqrt((bell(j1-1) - bells)*(bell(j1-1) - bells) + dz*dz) !area = 0.25*(per(j1-1) + pers)*(dlxs + dlys) area = pi*(aell(j1-1)*bell(j1-1) - aells*bells) Tsoilsurf(i) = Tsoilsurf(i) + Temp(j1)*area !(zsoilcols(i+1) - z(j1-1)) areas = areas + area ! Averaging Tsoilsurf(i) = Tsoilsurf(i)/areas enddo deallocate(Temp, z, per, dlx, dly, aell, bell) !deallocate(bathymall) if (firstcall) firstcall = .false. contains FUNCTION ELLAR(a,b) ! Approximate formula for the ellipse perimeter implicit none real(kind=ireals) :: ELLAR real(kind=ireals), intent(in) :: a, b ELLAR = pi*(3.*(a + b) - sqrt( (3.*a + b)*(a + 3.*b) ) ) END FUNCTION ELLAR END SUBROUTINE TSURFSOILCOL SUBROUTINE LATERHEAT(ix,iy,gs,ls,btmw,btmi,btmdi,btms,gsp,soilflux,onlywater,lsh) !Subroutine LATERHEAT calculates heat sources from lateral heat exchange ! with soil columns for water, ice and deep ice layers use ARRAYS_BATHYM,ls_=>ls!, only : bathym, layers_type use ARRAYS_GRID,gs_=>gs,gsp_=>gsp!, only : gridsize_type, gridspacing_type use ARRAYS_SOIL,lsh_=>lsh,soilflux_=>soilflux!, only : lsh_type use NUMERIC_PARAMS!, only : & !& small_value implicit none ! Input variables integer(kind=iintegers), intent(in) :: ix, iy type(gridsize_type), intent(in) :: gs ! Gridsizes type(layers_type), intent(in) :: ls ! Layers thicknesses type(bathym), intent(in) :: btmw(1:gs%M+1), btmi(1:gs%Mice+1) !Bathymetries type(bathym), intent(in) :: btmdi(1:gs%Mice+1), btms(1:gs%nsoilcols+1) ! Bathymetries type(gridspacing_type), intent(in) :: gsp ! Grid spacing real(kind=ireals), intent(in) :: soilflux(1:gs%nsoilcols) ! Heat flux into soil, W/m**2 logical, intent(in) :: onlywater ! Indicates whether the lateral heat influx is calculated for water column only ! Input/output variables ! Output variables type(lsh_type), intent(inout) :: lsh ! Heat source from soil columns for water, ice and deep ice ! Local variables real(kind=ireals) :: offset real(kind=ireals), allocatable :: z(:), area(:) integer(kind=iintegers) :: i, j, i0, i1 ! Water layer exists if (ls%h1 > small_value) then offset = maxval(gsp%zsoilcols) - ls%h1 - STEP(ls%ls1 - small_value)*ls%ls1 allocate ( z(0:gs%M+1), area(0:gs%M+1) ) z(0) = offset ; area(0) = btmw(1)%area_int z(1:gs%M) = offset + gsp%z_half(1:gs%M) ; area(1:gs%M) = btmw(1:gs%M)%area_half z(gs%M+1) = offset + ls%h1 ; area(gs%M+1) = btmw(gs%M+1)%area_int lsh%water(:) = 0. waterscan : do j = 1, gs%nsoilcols-1 if ( OVERLAY(z(0),z(gs%M+1),gsp%zsoilcols(j,ix,iy),gsp%zsoilcols(j+1,ix,iy)) ) then if (z(0) <= gsp%zsoilcols(j,ix,iy)) then i0 = -1 do i = 1, gs%M+1 if ( z(i-1) < gsp%zsoilcols(j,ix,iy) .and. & & z(i) > gsp%zsoilcols(j,ix,iy) ) then i0 = i exit endif enddo else i0 = -1 endif if (i0 /= -1) then lsh%water(i0) = lsh%water(i0) + 1./btmw(i0)%area_int * & & ( area(i0) - btms(j)%area_int ) / (ls%h1*gsp%ddz05(i0-1)) * soilflux(j) endif if (z(gs%M+1) >= gsp%zsoilcols(j+1,ix,iy)) then i1 = -1 do i = 1, gs%M+1 if ( z(i-1) < gsp%zsoilcols(j+1,ix,iy) .and. & & z(i) > gsp%zsoilcols(j+1,ix,iy) ) then i1 = i exit endif enddo else i1 = -1 endif if (i1 /= -1) then lsh%water(i1) = + 1./btmw(i1)%area_int * & & ( btms(j+1)%area_int - area(i1-1) ) / (ls%h1*gsp%ddz05(i1-1)) * soilflux(j) endif forall ( i = 1:gs%M+1, z(i-1) >= gsp%zsoilcols(j,ix,iy) & & .and. z(i) <= gsp%zsoilcols(j+1,iy,iy) ) & & lsh%water(i) = + 1./btmw(i)%area_int * & & ( area(i) - area(i-1) )/ (ls%h1*gsp%ddz05(i-1)) * soilflux(j) if (z(gs%M+1) <= gsp%zsoilcols(j,ix,iy)) exit waterscan endif enddo waterscan deallocate(z,area) endif ! Ice layer exists if (ls%l1 > small_value .and. (.not. onlywater) ) then offset = maxval(gsp%zsoilcols) - ls%l1 & & - STEP(ls%ls1 - small_value)*ls%ls1 - STEP(ls%h1 - small_value)*ls%h1 allocate ( z(0:gs%Mice+1), area(0:gs%Mice+1) ) z(0) = offset ; area(0) = btmi(1)%area_int !print*, 'z0', z(0), ls%l1, gsp%ddzi05(gs%Mice), gsp%ddzi05(0) do i = 1, gs%Mice+1 z(i) = z(i-1) + gsp%ddzi05(i-1)*ls%l1 enddo area(1:gs%Mice) = btmi(1:gs%Mice)%area_half area(gs%Mice+1) = btmi(gs%Mice+1)%area_int lsh%ice(:) = 0. icescan : do j = 1, gs%nsoilcols-1 if ( OVERLAY(z(0),z(gs%Mice+1),gsp%zsoilcols(j,ix,iy),gsp%zsoilcols(j+1,ix,iy)) ) then if (z(0) <= gsp%zsoilcols(j,ix,iy)) then i0 = -1 do i = 1, gs%Mice+1 if ( z(i-1) < gsp%zsoilcols(j,ix,iy) .and. & & z(i) > gsp%zsoilcols(j,ix,iy) ) then i0 = i exit endif enddo else i0 = -1 endif if (i0 /= -1) then lsh%ice(i0) = lsh%ice(i0) + 1./btmi(i0)%area_int * & & ( area(i0) - btms(j)%area_int ) / (ls%l1*gsp%ddzi05(i0-1)) * soilflux(j) endif if (z(gs%Mice+1) >= gsp%zsoilcols(j+1,ix,iy)) then i1 = -1 do i = 1, gs%Mice+1 if ( z(i-1) < gsp%zsoilcols(j+1,ix,iy) .and. & & z(i) > gsp%zsoilcols(j+1,ix,iy) ) then i1 = i exit endif enddo else i1 = -1 endif if (i1 /= -1) then lsh%ice(i1) = + 1./btmi(i1)%area_int * & & ( btms(j+1)%area_int - area(i1-1) ) / (ls%l1*gsp%ddzi05(i1-1)) * soilflux(j) endif forall ( i = 1:gs%Mice+1, z(i-1) >= gsp%zsoilcols(j,ix,iy) & & .and. z(i) <= gsp%zsoilcols(j+1,iy,iy) ) & & lsh%ice(i) = + 1./btmi(i)%area_int * & & ( area(i) - area(i-1) )/ (ls%l1*gsp%ddzi05(i-1)) * soilflux(j) if ( z(gs%Mice+1) <= gsp%zsoilcols(j,ix,iy) ) exit icescan endif enddo icescan deallocate(z,area) endif ! Deep ice layer exists if (ls%ls1 > small_value .and. (.not. onlywater) ) then offset = maxval(gsp%zsoilcols) - ls%ls1 allocate ( z(0:gs%Mice+1), area(0:gs%Mice+1) ) z(0) = offset ; area(0) = btmdi(1)%area_int do i = 1, gs%Mice+1 z(i) = z(i-1) + gsp%ddzi05(i-1)*ls%ls1 enddo area(1:gs%Mice) = btmdi(1:gs%Mice)%area_half area(gs%Mice+1) = btmdi(gs%Mice+1)%area_int lsh%dice(:) = 0. dicescan : do j = 1, gs%nsoilcols-1 if ( OVERLAY(z(0),z(gs%Mice+1),gsp%zsoilcols(j,ix,iy),gsp%zsoilcols(j+1,ix,iy)) ) then if (z(0) <= gsp%zsoilcols(j,ix,iy)) then i0 = -1 do i = 1, gs%Mice+1 if ( z(i-1) < gsp%zsoilcols(j,ix,iy) .and. & & z(i) > gsp%zsoilcols(j,ix,iy) ) then i0 = i exit endif enddo else i0 = -1 endif if (i0 /= -1) then lsh%dice(i0) = lsh%dice(i0) + 1./btmdi(i0)%area_int * & & ( area(i0) - btms(j)%area_int ) / (ls%ls1*gsp%ddzi05(i0-1)) * soilflux(j) endif if (z(gs%Mice+1) >= gsp%zsoilcols(j+1,ix,iy)) then i1 = -1 do i = 1, gs%Mice+1 if ( z(i-1) < gsp%zsoilcols(j+1,ix,iy) .and. & & z(i) > gsp%zsoilcols(j+1,ix,iy) ) then i1 = i exit endif enddo else i1 = -1 endif if (i1 /= -1) then lsh%dice(i1) = + 1./btmdi(i1)%area_int * & & ( btms(j+1)%area_int - area(i1-1) ) / (ls%ls1*gsp%ddzi05(i1-1)) * soilflux(j) endif forall ( i = 1:gs%Mice+1, z(i-1) >= gsp%zsoilcols(j,ix,iy) & & .and. z(i) <= gsp%zsoilcols(j+1,iy,iy) ) & & lsh%dice(i) = + 1./btmdi(i)%area_int * & & ( area(i) - area(i-1) )/ (ls%ls1*gsp%ddzi05(i-1)) * soilflux(j) if ( z(gs%Mice+1) <= gsp%zsoilcols(j,ix,iy) ) exit dicescan endif enddo dicescan deallocate(z,area) endif contains FUNCTION OVERLAY(x1,x2,y1,y2) ! Function OVERLAY checks, if two intervals overlay ! x2>x1, y2>y1 implicit none logical :: OVERLAY real(kind=ireals), intent(in) :: x1, x2, y1, y2 OVERLAY = (y1 >= x1 .and. y2 <= x2) .or. & & (y1 <= x1 .and. y2 >= x2) .or. & & (y1 <= x1 .and. y2 > x1) .or. & & (y1 < x2 .and. y2 >= x2) END FUNCTION OVERLAY END SUBROUTINE LATERHEAT END MODULE SOIL_MOD