module mod_icestate_srfbudget implicit none ! ==================================================================== ! Routines for calculating the surface energy budget in the icestate ! model. This is done by expressing the budget as 4th order polynomials. ! This might seem awkward if we consider calculating heat fluxes, but is ! useful when we want to solve for surface temperature of the ice ! ==================================================================== contains ! ==================================================================== ! Routine for calculating ice surface temperature using atmospheric ! heat fluxes and conductive and thermal inertia heat fluxes. ! The routine uses function calls for different flux components ! and sets the heat balance up as a function of surface temperature. ! The routine sets up and solves: ! ! a(0) + a(1)*T^1 + a(2)*T^2 + a(3)*T^3 + a(4)*T^4 =0 ! ! For now we onlys olve a linear equation ! -------------------------------------------------------------------- ! Note: In this manner it is easy to iterate and/or use Newton solver ! ==================================================================== elemental function srftemp_ice(icem,t_old,relhum,tair,wind,qsw,slp,clouds,rlat,tml) use mod_icestate implicit none type(t_ice), intent(in) :: icem real, intent(in) :: relhum, tair, wind, qsw, slp, clouds, rlat, tml,t_old ! a(n) is coefficient of T^n. Equation to be solved is sum(a(n)T^n) = 0 real, dimension(0:4) :: a real :: rhoair,vpair,vpsrf,qair,qsrf real :: srftemp_ice ! Density, vapour pressure and humidities. rhoair = slp / (gasconst * tair) vpair = vapp(aice ,bice ,tair) vpsrf = vapp(aice,bice,icem%tsrf) qair = relhum*humid(slp,vpair) qsrf = humid(slp,vpsrf) ! Components of the surface budget a=0 a(0) = qsw a = a + turbulent(icem%tsrf,qsrf,tair,qair,rhoair,wind) a = a + longwave(tair,clouds,vpair,rlat) a = a + heatconduction(icem,tml) a = a + heatinertia(icem,t_old) if ( all(abs(a(3:4))epsil1) then if (icem%nlay>1) then #if defined(SSNOWD) && defined (HEAT_CONDUC) !Effects of snow cover heterogneities are included via the conduction ! correction factor icem%hsnw = average_depth(icem) rkeq = corr_factor(icem)*rkice*rksnw / (rkice*icem%hsnw + rksnw*icem%hice/(2*icem%nlay)) #else rkeq = rkice*rksnw / (rkice*icem%hsnw + rksnw*icem%hice/(2*icem%nlay)) #endif tbot = icem%vtp(icem%nlay) else #if defined(SSNOWD) && defined (HEAT_CONDUC) icem%hsnw = average_depth(icem) rkeq = corr_factor(icem) *rkice*rksnw / (rkice*icem%hsnw + rksnw*icem%hice) #else rkeq = rkice*rksnw / (rkice*icem%hsnw + rksnw*icem%hice) #endif tbot = tml end if end if ! Linear dependence... heatconduction = 0. heatconduction(0) = rkeq*tbot heatconduction(1) = -rkeq end function heatconduction ! ==================================================================== ! Thermal inertia heat flux routine . Calculate the coefficients ! for a polynomial in T (surface temperature) which describe ! conductive heat flux. ! ==================================================================== pure function heatinertia(icem,t_old) use mod_icestate implicit none type(t_ice), intent(in) :: icem real , intent(in) :: t_old real :: fqinert,rkeq,rksnw real :: heatinertia(0:4) ! Snow conductivity rksnw = rkice*(icem%rhosnw / rhow)**1.885 ! Calculate heat conductivity and heat inertia factors (cond. factor ! is used because we treat snow with no heat capacity, we assume linear ! effective vtp in the snow and ice) fqinert=0. if (icem%fice>epsil1) then if (icem%nlay>1) then rkeq = rkice*rksnw / (rkice*icem%hsnw + rksnw*icem%hice/(2*icem%nlay)) fqinert = .5*(icem%hice/(2*icem%nlay))*rhoice*cpice*rkeq / (dtt*rkice/(icem%hice/(2*icem%nlay))) else rkeq = rkice*rksnw / (rkice*icem%hsnw + rksnw*icem%hice) fqinert = .5*icem%hice*rhoice*cpice*rkeq / (dtt*rkice/icem%hice) end if end if ! Linear dependence.. heatinertia=0. heatinertia(0) = fqinert*t_old ! Old surf temp for inertia ... heatinertia(1) = -fqinert end function heatinertia ! ==================================================================== ! Routine to get evaporation over water. ! ==================================================================== pure function evaporation(tair,tsrf,wind,slp,relhum,rhosw) use mod_icestate implicit none real, intent(in) :: wind,tair,tsrf,slp,rhosw,relhum real :: evaporation real :: clatent,fqlat,dtemp,rhoair,vpair,vpsrf,qair,qsrf integer :: iturb,jturb rhoair = slp / (gasconst * tair) ! Vapour pressure and humidity of air over the surface vpair = vapp(awater ,bwater ,tair) qair = relhum*humid(slp,vpair) ! Vapour pressure and humidity of the air over the surface vpsrf = vapp(awater,bwater,tsrf) qsrf = humid(slp,vpsrf) dtemp = tair-tsrf iturb = min(16,int(wind * .5) + 1) jturb = max(1,min(29,int((dtemp + 7.) *2.) +1)) clatent = clat(iturb,jturb) evaporation = rhoair * hosubl * clatent * wind * max(0.,qsrf-qair) * hocondi / rhosw end function evaporation ! ======================================================================= ! Defines vapour pressure function (vapp has unit pa; tx is temp in k). ! ! ======================================================================= elemental FUNCTION vapp(ax,bx,tx) implicit none REAL :: vapp REAL, INTENT(in) :: ax,bx,tx vapp = 611. * 10.**(ax * (tx - 273.16)/(tx - bx)) END FUNCTION vapp ! ======================================================================= ! Defines specific humidity (dimensionless). ! ! ======================================================================= elemental FUNCTION humid(px,ex) implicit none REAL :: humid REAL, intent(in) :: px,ex humid = .622 * ex / (px - .378 * ex) END FUNCTION humid ! ======================================================================= ! =========================== clat_turbm ================================ ! ======================================================================= ! ! Read numerical values of the latent transfer coefficient based ! on the tabelled values in isemer et al, j clim., p. 1180, 1989 ! note: ! i-index gives the wind at 10m height ! from 0 to 30 m/s in intervals of 2 m/s ! j-index gives the virtual air-sea temperature difference at 10m ! height ! from -7 to +7 deg c in intervals of .5 deg c ! for all but the equatorial and sub-equatorial waters, virtual ! temp is close to real temp (see gill, 1982, p. 41) ! ! PURPOSE ! ------- ! Computes turbulent heat exchange coefficient as a function of wind ! and the temperature difference between marine surface and ! atmospheric mixed layer. ! ! EXTERNALS ! --------- ! Called by procedures : th/thermf ! Calls procedures : none ! ! AUTHOR ! ------ ! Paul Budgell, 1994 ! ! MODIFIED ! -------- ! David Salas y Melia, nov. 1996 ! subroutine clat_turbm(clatx) use mod_icestate implicit none REAL, DIMENSION(16,29), INTENT(out) :: clatx CHARACTER(80) :: filename REAL :: d_wind,d_temp REAL, DIMENSION(16,29) :: clat1 integer :: i,j, iossum, ios logical :: ex ! READ data file filename = 'iwh_tabulated.dat' inquire(exist=ex,file=trim(filename)) if (.not. ex) then if (mnproc==1) print *,'Can not find '//trim(filename) call xcstop('(mod_icestate_srfbdget:clat_turbm)') end if iossum=0 OPEN(10,file = TRIM(filename)) DO j = 1,29 DO i = 1,16 READ(10,*,iostat=ios) d_wind,d_temp,clat1(i,j) clat1(i,j) = clat1(i,j) * 1.E-3 iossum=iossum+ios END DO END DO CLOSE(10) if (iossum/=0) then if (mnproc==1) print *,'Error reading '//trim(filename) call xcstop('(mod_icestate_srfbdget:clat_turbm)') end if ! let i = 1 represent wind speeds in the interval [0, 2) m/s ! i = 2 represent wind speeds in the interval [2, 4) m/s ... DO j = 1,29 DO i = 1,15 clatx(i,j) = .5 * (clat1(i,j) + clat1(i+1,j)) END DO clatx(16,j) = clatx(15,j) END DO ! let j = 1 represent temp differences in the interval [-7, -6.5) m/s ! j = 2 represent temp differences in the interval [-6.5, -6) m/s ... DO i = 1,16 DO j = 1,28 clatx(i,j) = .5 * (clat1(i,j) + clat1(i,j+1)) END DO clatx(i,29) = clatx(i,28) END DO end subroutine clat_turbm end module mod_icestate_srfbudget