!/===========================================================================/ ! Copyright (c) 2007, The University of Massachusetts Dartmouth ! Produced at the School of Marine Science & Technology ! Marine Ecosystem Dynamics Modeling group ! All rights reserved. ! ! FVCOM has been developed by the joint UMASSD-WHOI research team. For ! details of authorship and attribution of credit please see the FVCOM ! technical manual or contact the MEDM group. ! ! ! This file is part of FVCOM. For details, see http://fvcom.smast.umassd.edu ! The full copyright notice is contained in the file COPYRIGHT located in the ! root directory of the FVCOM code. This original header must be maintained ! in all distributed versions. ! ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ! THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ! PURPOSE ARE DISCLAIMED. ! !/---------------------------------------------------------------------------/ ! CVS VERSION INFORMATION ! $Id$ ! $Name$ ! $Revision$ !/===========================================================================/ !------------------------------------------------------------------------------ # if defined (HEATING_CALCULATED) subroutine coare40vn(u,zu,t,zt,rh,zq,PA,ts,Rl,Rs,tau,hsb,hlb,lat,zi,rain,cp,sigH,fmiss,USR,DTER,Cdn_10) ! Siqi Li, 2021-01-27 !subroutine coare40vn(u,zu,t,zt,rh,zq,P,ts,Rl,Rs,tau,hsb,hlb,lat,zi,rain,cp,sigH,fmiss,USR,DTER) ! No-vectorized verion - Revised from the vectorized of coare40vn.m ! Zhongxiang Wu ! 4/8/2016 ! Calibrated by Siqi Li on July, 2017 ! Vectorized version of COARE 3 code (Fairall et al, 2003) with ! modification based on the CLIMODE, MBL and CBLAST experiments ! (Edson et al., JPO, 43, 2013). ! ! The current version of the code includes the wind-speed, wave-age and ! sea-state dependent parameterizations of the Charnock variabile as ! described in Edson et al. (2013). The parameterization is chosen by the ! inputed values of ! cp = phase speed of dominant waves (m/s) ! sigH = significant wave height (m) ! ! An important component of this code is whether the inputed ts ! represents the skin temperature of a near surface temperature. ! How this variable is treated is determined by the jcool parameter: ! set jcool=1 if Ts is bulk ocean temperature (default), ! jcool=0 if Ts is true ocean skin temperature. !******************************************************************** ! ! The code assumes u,t,rh,ts are vectors; ! sensor heights zu,zt,zl, latitude lat, and PBL height zi are constants; ! air pressure P and radiation Rs,Rl may be vectors or constants. ! Default values are assigned for P,Rs,Rl,lat,and zi if these data are not ! available. Input NaNs to indicate no data. Defaults should be set to ! representative regional values if possible. ! ! Inputs: ! ! u = relative wind speed (m/s) at heigth zu ! zu = height of wind speed measurement (m) ! t = bulk air temperature (degC) at height zt ! zt = height of temperature measurement (m) ! rh = relative humidity (%) at height zq ! zq = height of relative humidity measurement (m) !---> Siqi Li, 2021-01-27 ! P = surface air pressure (mb) (default = 1015) (removed) ! P = surface air pressure (Pa) (default = 101500) !<--- Siqi Li, 2021-01-27 ! ts = water temperature (degC) see jcool below ! Rs = downward shortwave radiation (W/m^2) (default = 150) ! Rl = downward longwave radiation (W/m^2) (default = 370) ! lat = latitude (default = +45 N) ! zi = PBL height (m) (default = 600m) ! rain = rain rate (mm/hr) - not required for turbulent flux estimates, ! set to NaN if unavailable. ! cp = phase speed of dominant waves (m/s) ! sigH = significant wave height (m) ! ! The user controls the output. This is currently set as: ! ! A=[usr tau hsb hlb hbb hsbb wbar tsr qsr zot zoq Cd Ch Ce L ! 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ! zet dter dqer tkt Urf Trf Qrf RHrf UrfN Rnl Le rhoa UN U10 U10N ! 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ! Cdn_10 Chn_10 Cen_10 RF Qs Evap T10 Q10 RH10]; ! 31 32 33 34 35 36 37 38 39 ! where ! ! usr = friction velocity that includes gustiness (m/s) ! tau = wind stress (N/m^2) ! hsb = sensible heat flux into ocean (W/m^2) ! hlb = latent heat flux into ocean (W/m^2) ! hbb = buoyany flux into ocean (W/m^2) ! hsbb = "sonic" buoyancy flux measured directly by sonic anemometer ! wbar = the vertical velocity required to "Webb Correct" direct ! covariance fluxes ! tsr = temperature scaling parameter (K) ! qsr = specific humidity scaling parameter (g/Kg) ! zot = thermal roughness length (m) ! zoq = moisture roughness length (m) ! Cd = wind stress transfer (drag) coefficient at height zu ! Ch = sensible heat transfer coefficient (Stanton number) at height zu ! Ce = latent heat transfer coefficient (Dalton number) at height zu ! L = Obukhov length scale (m) ! zet = Monin-Obukhov stability parameter zu/L ! dter = cool-skin temperature depression (degC) ! dqer = cool-skin humidity depression (degC) ! tkt = cool-skin thickness (m) ! Urf = wind speed at reference height (user can select height below) ! Trf = temperature at reference height ! Qrf = specific humidity at reference height ! RHrf = relative humidity at reference height ! UrfN = neutral value of wind speed at reference height ! Rnl = Upwelling IR radiation computed by COARE ! Le = latent heat of vaporization ! rhoa = density of air ! UN = neutral value of wind speed at zu ! U10 = wind speed adjusted to 10 m ! UN10 = neutral value of wind speed at 10m !Cdn_10 = neutral value of drag coefficient at 10m !Chn_10 = neutral value of Stanton number at 10m !Cen_10 = neutral value of Dalton number at 10m ! RF = sensible heat flux due to rain (W/m^2) ! Qs = surface value of specific humidity (g/kg) without cool skin ! correction ! Evap = evaporation rate from surface in mm/hr ! T10 = temperarure at 10 m ! Q10 = specific humidity at 10 m ! RH10 = relative humidity at 10 m ! ! Notes: 1) u is the relative wind speed, i.e., the magnitude of the ! difference between the wind (at zu) and ocean surface current ! vectors. ! 2) Set jcool=0 in code if ts is true surface skin temperature, ! otherwise ts is assumed the bulk temperature and jcool=1. ! 3) Set P=NaN to assign default value if no air pressure data ! available. ! 4) Set Rs=NaN, Rl=NaN if no radiation data available. This assigns ! default values to Rs, Rl so that cool skin option can be applied. ! 5) Set lat=NaN and/or zi=NaN to assign default values if latitude ! and/or PBL height not given. ! 6) The code to compute the heat flux caused by precipitation is ! included if rain data is available (default is no rain). ! 7) Code updates the cool-skin temperature depression dter and thickness ! tkt during iteration loop for consistency. ! 8) Number of iterations set to nits = 6. ! Reference: ! ! Fairall, C.W., E.F. Bradley, J.E. Hare, A.A. Grachev, and J.B. Edson (2003), ! Bulk parameterization of air sea fluxes: updates and verification for the ! COARE algorithm, J. Climate, 16, 571-590. ! ---------------------------------------------------------- use mod_prec USE MOD_HEATFLUX,ONLY : HEATING_FRESHWATER implicit none real(SP) :: u,zu,t,zt,rh,zq,P,ts,Rs,Rl,tau,hsb,hlb,lat,zi,rain,cp,sigH,fmiss real(SP) :: PA ! Siqi Li, 2021-01-27 real(SP) :: Pdef,Rsdef,Rldef,Latdef,Zidef real(SP) :: us,Qs,Q,Pv real(SP) :: zref,Beta,von,fdg,tdk,grav real(SP) :: Rgas,Le,cpa,cpv,rhoa,rhodry,visa,lapse real(SP) :: Al,be,cpw,rhow,visw,tcw,bigc,wetc real(SP) :: Rns,Rnl real(SP) :: rovcp,du,dt,dq,ta,tv,ug,dter,dqer,ut,u10,usr,zo10 real(SP) :: Cd10,Ch10,Ct10,zot10,Cd,Ct,CC,Ribcu,Ribu,zetu real(SP) :: L10,gf,tsr,qsr,tkt real(SP) :: charn,charnC,umax,a1,a2,A,B,charnW,Ad,Bd,zoS,charnS real(SP) :: zet,L,zo,rr,zoq,zot,cdhf,cqhf,cthf,tvsr,tssr,Bf real(SP) :: qout,dels,qcol,alq,xlamx,sst,usr50,tsr50,qsr50,L50,zet50 real(SP) :: dter50,dqer50,tkt50,u10N,hbb,hsbb,wbar,Evap,Ch,Ce real(SP) :: Cdn_10,Chn_10,Cen_10,zrf_u,zrf_t,zrf_q real(SP) :: psi,psi10,psirf,psiT,psi10T,psirfT,psirfQ real(SP) :: S,S10,Urf,UN,UrfN,UN2,U10N2,UrfN2 real(SP) :: dwat,dtmp,dqs_dt,alfac,RF,T10,Trf,TN,T10N,TrfN,TN2,T10N2,TrfN2 real(SP) :: SSQ,Q10,Qrf,QN,Q10N,QrfN,QN2,Q10N2,QrfN2,RHrf,RH10 real(SP) :: qsat26sea,qsat26lake,grvf,psiu_26f,psit_26f,RHcalc integer :: i,nits,jcool integer :: waveage,seastate data Pdef,Rsdef,Rldef,Latdef,Zidef/ & 101300,150, 370, 45, 600/ ! Siqi Li, 2021-01-27 ! 1030,150, 370, 45, 600/ ! convert input to column vectors !u=u(:);t=t(:);rh=rh(:);P=P(:);ts=ts(:); !Rs=Rs(:);Rl=Rl(:);lat=lat(:);zi=zi(:); !zu=zu(:);zt=zt(:);zq=zq(:); !rain=rain(:); !N=length(u); jcool = 1 ! set local variables to default values if input is NaN if(abs(p-fmiss) < 0.00001_SP) p =pdef if(abs(Rs-fmiss) < 0.00001_SP) Rs =Rsdef if(abs(Rl-fmiss) < 0.00001_SP) Rl =Rldef if(abs(Lat-fmiss) < 0.00001_SP) Lat=Latdef if(abs(Zi-fmiss) < 0.00001_SP) Zi =Zidef P = PA/100.0_SP ! Siqi Li, 2021-01-27 waveage=0 seastate=0 !---> Siqi Li, 2021-01-27 if(abs(cp) > 1.0E-6_SP) then waveage=1 if(abs(sigh) > 1.0E-6_SP) seastate=1 endif ! if(abs(cp) > 0.0) then ! waveage=1 ! if(abs(sigh) > 0.0) seastate=1 ! endif !<--- Siqi Li, 2021-01-27 !************************************************************************ ! Check on which parameterization you are using. You can remove the ! pause once you are familiar with how the code selects the ! appropriate parameterization based on the input variables. !************************************************************************ !---> Siqi Li, 2021-01-27 ! if (waveage.eq.1 .and. seastate.eq.1) & ! print *,' Use the seastate dependent parameterization.' ! if (waveage.eq.1 .and. seastate.eq.0) & ! print *, ' Use the waveage dependent parameterization.' !<--- Siqi Li, 2021-01-27 ! input variable u is assumed relative wind speed (magnitude of difference ! between wind and surface current vectors). to follow orginal Fairall code, set ! surface current speed us=0. if us data are available, construct u prior to ! using this code. us = 0.0_SP ! convert rh to specific humidity IF(.NOT. HEATING_FRESHWATER)THEN Qs = qsat26sea(ts,P)/1000.0_SP ! surface water specific humidity (g/kg) ! Siqi Li, 2021-01-27: I think the unit is kg/kg ELSE Qs = qsat26lake(ts,P)/1000.0_SP ! surface water specific humidity (g/kg) ! Siqi Li, 2021-01-27: I think the unit is kg/kg END IF call qsat26air(t,P,rh,Q,Pv) ! specific humidity of air (g/kg) Q=Q/1000.0_SP ! specific humidity of air (kg/kg) !*********** set constants ********************************************** zref=10.0_SP Beta = 1.2_SP von = 0.4_SP fdg = 1.0_SP ! Turbulent Prandtl number tdk = 273.16_SP grav = grvf(lat) !*********** air constants ********************************************** Rgas = 287.05_SP Le = (2.501_SP-.00237_SP*ts)*1e6_SP cpa = 1004.67_SP cpv = cpa*(1.0_SP+0.84_SP*Q) rhoa = P*100.0_SP/(Rgas*(t+tdk)*(1.0_SP+0.61_SP*Q)) rhodry = (P-Pv)*100.0_SP/(Rgas*(t+tdk)) visa = 1.326e-5_SP*(1.0_SP+6.542e-3_SP*t+8.301e-6_SP*t**2-4.84e-9_SP*t**3) lapse=grav/cpa !*********** cool skin constants *************************************** Al = 2.1e-5_SP*(ts+3.2_SP)**0.79_SP IF(.NOT. HEATING_FRESHWATER)THEN be = 0.026_SP ELSE !!MDR salinity expansion coefficient, BE, to zero for freshwater ! confirmed by email with CW Fairall 4-24-2013 be = 0.0_SP END IF cpw = 4000._SP IF(.NOT. HEATING_FRESHWATER)THEN rhow = 1022._SP ELSE rhow = 1000._SP !MDR, freshwater density END IF visw = 1e-6_SP tcw = 0.6_SP bigc = 16._SP*grav*cpw*(rhow*visw)**3/(tcw**2*rhoa**2) wetc = 0.622_SP*Le*Qs/(Rgas*(ts+tdk)**2) !*********** net radiation fluxes *************************************** IF(.NOT. HEATING_FRESHWATER)THEN Rns = 0.945_SP*Rs ! albedo correction ELSE Rns = Rs !Mark Rowe, remove albedo here because albedo is included in forcings END IF Rnl = 0.97_SP*(5.67e-8_SP*(ts-0.3_SP*jcool+tdk)**4-Rl) ! initial value !**************** begin bulk loop ******************************************** !*********** first guess ************************************************ rovcp=Rgas/cpa lapse=grav/cpa du = u-us dt = ts-t-lapse*zt dq = Qs-Q ta = t+tdk tv = ta*(1.0_SP+0.61_SP*Q) ug = 0.5_SP dter = 0.3_SP dqer = dter*wetc ut = sqrt(du**2+ug**2) u10 = ut*log(10.0_SP/1e-4_SP)/log(zu/1e-4_SP) usr = 0.035_SP*u10 zo10 = 0.011_SP*usr**2/grav + 0.11_SP*visa/usr Cd10 = (von/log(10.0_SP/zo10))**2 Ch10 = 0.00115_SP Ct10 = Ch10/sqrt(Cd10) zot10 = 10._SP/exp(von/Ct10) Cd = (von/log(zu/zo10))**2 Ct = von/log(zt/zot10) CC = von*Ct/Cd Ribcu = -zu/(zi*0.004_SP*Beta**3) Ribu = -grav*zu/ta*((dt-dter*jcool)+.61_SP*ta*dq)/ut**2 !(ta*(tu**2)) in 26z if(Ribu.lt.0.0_SP) then zetu=CC*Ribu/(1.0_SP+Ribu/Ribcu) else zetu = CC*Ribu*(1.0_SP+27.0_SP/9.0_SP*Ribu/CC) ! zetu=CC*Ribu/(1.+27/(9*Ribu*cc)) ! in 26z endif !!! Late ---- what for this ! k50=find(zetu>50) ! stable with very thin M-O length relative to zu L10 = zu/zetu gf=ut/du usr = ut*von/(log(zu/zo10)-psiu_26f(zu/L10)) !---> Changed by Siqi Li ! tsr = -(dt-dter*jcool)*von*fdg/(log(zt/zot10)-psit_26(zt/L10)) tsr = -(dt-dter*jcool)*von*fdg/(log(zt/zot10)-psit_26f(zt/L10)) ! qsr = -(dq-dqer*jcool)*von*fdg/(log(zq/zot10)-psit_26(zq/L10)) qsr = -(dq-dqer*jcool)*von*fdg/(log(zq/zot10)-psit_26f(zq/L10)) !<--- Changed by Siqi Li tkt = 0.001_SP !********************************************************** ! The Charnock variable for COARE 3.0 !********************************************************** if(ut.gt.10.0_SP) then charn=0.011_SP+(ut-10.0_SP)/(18._SP-10._SP)*(0.018_SP-0.011_SP) elseif(ut.gt.18._SP) then charn=0.018_SP else charn = 0.011_SP endif !********************************************************** ! The following gives the new formulation for the ! Charnock variable in COARE 3.5 !********************************************************** charnC=0.11_SP umax=19._SP a1=0.0017_SP a2=-0.0050_SP if(u10.gt.umax) then !wind-speed dependent coefficients charnC=a1*umax+a2 else charnC=a1*u10+a2 endif A=0.114_SP !wave-age dependent coefficients B=0.622_SP charnW=A*(usr/cp)**B Ad=0.091_SP !Sea-state/wave-age dependent coefficients Bd=2.0_SP zoS=sigH*Ad*(usr/cp)**Bd charnS=zoS*grav/usr/usr nits=10 ! number of iterations ! Note: nits=1 in 26z_v1.0 !************** bulk loop ************************************************** do i=1,nits zet=von*grav*zu/tv*(tsr +0.61_SP*ta*qsr)/(usr**2) if (waveage.eq.1) then if (seastate.eq.1) then charn=charnS else charn=charnW endif else charn=charnC endif L=zu/zet zo=charn*usr*usr/grav+0.11_SP*visa/usr ! surface roughness !---> Siqi Li, 2021-01-17 ! Add the upper and lower limits for zo based on Davis et al. 2008. ! Only when wave is considered. if (waveage == 1) then zo = MAX(zo, 0.125E-6_SP) zo = MIN(zo, 2.850E-3_SP) end if !<--- Siqi Li, 2021-01-17 rr=zo*usr/visa ! zoq=min(1.6e-4_SP,6e-3_SP/rr**1.6_SP) !These thermal roughness lengths give # if !defined (DOUBLE_PRECISION) zoq=amin1(1.6e-4_SP,6.e-3_SP/rr**1.6_SP) !These thermal roughness lengths give # else zoq=dmin1(1.6e-4_SP,6.e-3_SP/rr**1.6_SP) !These thermal roughness lengths give # endif zot=zoq !Stanton and Dalton numbers for COARE 4.0 cdhf=von/(log(zu/zo)-psiu_26f(zu/L)) !---> Changed by Siqi Li ! cqhf=von*fdg/(log(zq/zoq)-psit_26(zq/L)) cqhf=von*fdg/(log(zq/zoq)-psit_26f(zq/L)) ! cthf=von*fdg/(log(zt/zot)-psit_26(zt/L)) cthf=von*fdg/(log(zt/zot)-psit_26f(zt/L)) !<--- Changed by Siqi Li usr=ut*cdhf qsr=-(dq-dqer*jcool)*cqhf tsr=-(dt-dter*jcool)*cthf tvsr=tsr+0.61_SP*ta*qsr tssr=tsr+0.51_SP*ta*qsr Bf=-grav/tv*usr*tvsr if(Bf.gt.0.0_SP) then ! ug=max(0.2,Beta*(Bf*zi)**0.333) # if !defined (DOUBLE_PRECISION) ug=amax1(0.2_SP,Beta*(Bf*zi)**0.333_SP) # else ug=dmax1(0.2_SP,Beta*(Bf*zi)**0.333_SP) # endif else ug=0.2_SP endif ut=sqrt(du**2+ug**2) gf=ut/du hsb=-rhoa*cpa*usr*tsr hlb=-rhoa*Le*usr*qsr qout=Rnl+hsb+hlb dels=Rns*(0.065_SP+11._SP*tkt-6.6e-5_SP/tkt*(1-exp(-tkt/8.0e-4_SP))) qcol=qout-dels alq=Al*qcol+be*hlb*cpw/Le xlamx=6.0_SP ! tkt=min(0.01, xlamx*visw/(sqrt(rhoa/rhow)*usr)) # if !defined (DOUBLE_PRECISION) tkt=amin1(0.01_SP, xlamx*visw/(sqrt(rhoa/rhow)*usr)) # else tkt=dmin1(0.01_SP, xlamx*visw/(sqrt(rhoa/rhow)*usr)) # endif if(alq.gt.0.0_SP) then xlamx=6._SP/(1._SP+(bigc*alq/usr**4)**0.75_SP)**0.333_SP tkt=xlamx*visw/(sqrt(rhoa/rhow)*usr) endif dter=qcol*tkt/tcw sst=ts-dter IF(.NOT. HEATING_FRESHWATER)THEN dqer=Qs-qsat26sea(sst,P)/1000._SP !wetc.*dter ELSE dqer=Qs-qsat26lake(sst,P)/1000._SP !wetc.*dter END IF Rnl=0.97_SP*(5.67e-8_SP*(ts-dter*jcool+tdk)**4-Rl) ! update dter if (i.eq.1) then ! save first iteration solution for case of zetu>50 if(zetu.gt.50._SP) then ! stable with very thin M-O length relative to zu usr50=usr tsr50=tsr qsr50=qsr L50=L zet50=zet dter50=dter dqer50=dqer tkt50=tkt endif end if u10N = usr/von/gf*log(10._SP/zo) if (waveage.eq.1) then if (seastate.eq.1) then zoS=sigH*Ad*(usr/cp)**Bd-0.11_SP*visa/usr charnS=zoS*grav/usr/usr else charnW=A*(usr/cp)**B end if else charnC=a1*u10N+a2 if(u10N.gt.umax)then charnC=a1*umax+a2 endif end if end do ! insert first iteration solution for case with zetu>50 if(zetu.gt.50._SP) then usr=usr50 tsr=tsr50 qsr=qsr50 L=L50 zet=zet50 dter=dter50 dqer=dqer50 tkt=tkt50 endif !**************** compute fluxes ******************************************** tau=rhoa*usr*usr/gf ! wind stress hsb=-rhoa*cpa*usr*tsr ! sensible heat flux hlb=-rhoa*Le*usr*qsr ! latent heat flux hbb=-rhoa*cpa*usr*tvsr ! buoyancy flux hsbb=-rhoa*cpa*usr*tssr ! sonic heat flux wbar=1.61_SP*hlb/Le/(1._SP+1.61_SP*Q)/rhoa+hsb/rhoa/cpa/ta !Useful for Webb Correction !hlwebb=rhoa*wbar*Q*Le Evap=1000._SP*hlb/Le/1000._SP*3600._SP !mm/hour !***** compute transfer coeffs relative to ut @ meas. ht ******************** Cd=tau/rhoa/ut/max(.1_SP,du) Ch=-usr*tsr/ut/(dt-dter*jcool) Ce=-usr*qsr/(dq-dqer*jcool)/ut !*** compute 10-m neutral coeff relative to ut (output if needed) ************ !---> Siqi Li, 2021-01-27 : there is no need to time 1000. Cdn_10=von**2./log(10._SP/zo)**2 Chn_10=von**2*fdg/log(10._SP/zo)/log(10._SP/zot) Cen_10=von**2*fdg/log(10._SP/zo)/log(10._SP/zoq) ! Cdn_10=1000*von**2./log(10./zo)**2 ! Chn_10=1000*von**2*fdg/log(10./zo)/log(10./zot) ! Cen_10=1000*von**2*fdg/log(10./zo)/log(10./zoq) !<--- Siqi Li, 2021-01-27 !*** compute 10-m neutral coeff relative to ut (output if needed) ************ ! Find the stability functions !******************************** zrf_u=2._SP !User defined reference heights to zrf_t=2._SP !compute values at zrf. zrf_q=2._SP psi=psiu_26f(zu/L) psi10=psiu_26f(10._SP/L) psirf=psiu_26f(zrf_u/L) psiT=psit_26f(zt/L) psi10T=psit_26f(10._SP/L) psirfT=psit_26f(zrf_t/L) psirfQ=psit_26f(zrf_q/L) gf=ut/du !********************************************************* ! Determine the wind speeds relative to ocean surface ! Note that usr is the friction velocity that includes ! gustiness usr = sqrt(Cd) S, which is equation (18) in ! Fairall et al. (1996) !********************************************************* S = ut U = du S10 = S + usr/von*(log(10._SP/zu)-psi10+psi) U10 = S10/gf ! or U10 = U + usr/von/gf*(log(10/zu)-psi10+psi) Urf = U + usr/von/gf*(log(zrf_u/zu)-psirf+psi) UN = U + psi*usr/von/gf U10N = U10 + psi10*usr/von/gf UrfN = Urf + psirf*usr/von/gf UN2 = usr/von/gf*log(zu/zo) U10N2 = usr/von/gf*log(10._SP/zo) UrfN2 = usr/von/gf*log(zrf_u/zo) !******** rain heat flux (save to use if desired) ***************************** if(rain.gt.0._SP) then dwat=2.11e-5_SP*((t+tdk)/tdk)**1.94_SP !! water vapour diffusivity dtmp=(1._SP + 3.309e-3_SP*t - 1.44e-6_SP*t*t)*0.02411_SP/(rhoa*cpa) !! heat diffusivity dqs_dt=Q*Le/(Rgas*(t+tdk)**2) !! Clausius-Clapeyron alfac= 1._SP/(1._SP+0.622_SP*(dqs_dt*Le*dwat)/(cpa*dtmp)) !! wet bulb factor RF= rain*alfac*cpw*((ts-t-dter*jcool)+ & (Qs-Q-dqer*jcool)*Le/cpa)/3600._SP else RF=0._SP end if lapse=grav/cpa SST=ts-dter*jcool T = t T10 = T + tsr/von*(log(10._SP/zt)-psi10T+psiT) + lapse*(zt-10._SP) Trf = T + tsr/von*(log(zrf_t/zt)-psirfT+psiT) + lapse*(zt-zrf_t) TN = T + psiT*tsr/von T10N = T10 + psi10T*tsr/von TrfN = Trf + psirfT*tsr/von TN2 = SST + tsr/von*log(zt/zot)-lapse*zt T10N2 = SST + tsr/von*log(10._SP/zot)-lapse*10._SP TrfN2 = SST + tsr/von*log(zrf_t/zot)-lapse*zrf_t IF(.NOT. HEATING_FRESHWATER)THEN dqer=(Qs-qsat26sea(SST,P)/1000._SP)*jcool !wetc*dter*jcool ELSE dqer=(Qs-qsat26lake(SST,P)/1000._SP)*jcool !wetc*dter*jcool END IF SSQ=Qs-dqer SSQ=SSQ*1000._SP Q=Q*1000._SP qsr=qsr*1000._SP Q10 = Q + qsr/von*(log(10._SP/zq)-psi10T+psiT) Qrf = Q + qsr/von*(log(zrf_q/zq)-psirfQ+psiT) QN = Q + psiT*qsr/von/sqrt(gf) Q10N = Q10 + psi10T*qsr/von QrfN = Qrf + psirfQ*qsr/von QN2 = SSQ + qsr/von*log(zq/zoq) Q10N2 = SSQ + qsr/von*log(10._SP/zoq) QrfN2 = SSQ + qsr/von*log(zrf_q/zoq) RHrf=RHcalc(Trf,P,Qrf/1000._SP) RH10=RHcalc(T10,P,Q10/1000._SP) !--->Siqi Li hsb=-hsb hlb=-hlb !<---Siqi Li !**************** output **************************************************** !A=[usr tau hsb hlb hbb hsbb wbar tsr qsr zot zoq Cd Ch Ce L zet dter dqer tkt Urf Trf Qrf RHrf UrfN Rnl Le rhoa UN U10 U10N Cdn_10 Chn_10 Cen_10 RF Qs Evap T10 Q10 RH10 gf] ! 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40] end subroutine coare40vn !------------------------------------------------------------------------------ ! function psi=psit_26(zet) function psit_26f(zet) use mod_prec ! computes temperature structure function implicit none real(SP) :: zet real(SP) :: dzet,x,psik,psic,f real(SP) :: psit_26f ! dzet=min(50.,0.35*zet) ! stable # if !defined (DOUBLE_PRECISION) dzet=amin1(50._SP,0.35_SP*zet) ! stable # else dzet=dmin1(50._SP,0.35_SP*zet) ! stable # endif psit_26f=-((1._SP+0.6667_SP*zet)**1.5+0.6667_SP*(zet-14.28_SP)*exp(-dzet)+8.525_SP) ! k=find(zet<0) ! unstable if(zet.lt.0.0_SP) then ! unstable x=(1._SP-16._SP*zet)**0.5 psik=2._SP*log((1._SP+x)/2._SP) x=(1._SP-34.15_SP*zet)**0.3333 psic=1.5_SP*log((1._SP+x+x**2)/3._SP)-sqrt(3._SP) & *atan((1._SP+2._SP*x)/sqrt(3._SP))+4._SP*atan(1._SP)/sqrt(3._SP) f=zet**2./(1._SP+zet**2) psit_26f=(1._SP-f)*psik+f*psic endif end function psit_26f !------------------------------------------------------------------------------ ! function psi=psiu_26(zet) function psiu_26f(zet) use mod_prec ! computes velocity structure function implicit none real(SP) :: zet real(SP) :: a,b,c,d,dzet,x,psik,psic,f real(SP) :: psiu_26f ! dzet=min(50.,0.35*zet) ! stable # if !defined (DOUBLE_PRECISION) dzet=amin1(50._SP,0.35_SP*zet) ! stable # else dzet=dmin1(50._SP,0.35_SP*zet) ! stable # endif a=0.7_SP b=3._SP/4._SP c=5._SP d=0.35_SP psiu_26f=-(a*zet+b*(zet-c/d)*exp(-dzet)+b*c/d) ! k=find(zet<0) ! unstable if(zet.lt.0._SP) then ! unstable x=(1._SP-16._SP*zet)**0.25 psik=2.0_SP*log((1.0_SP+x)/2.0_SP)+log((1.0_SP+x*x)/2.0_SP)-2.0_SP*atan(x)+2.0_SP*atan(1.0_SP) x=(1._SP-10.15_SP*zet)**0.3333 psic=1.5_SP*log((1._SP+x+x**2)/3._SP)-sqrt(3._SP) & *atan((1._SP+2._SP*x)/sqrt(3._SP))+4.0_SP*atan(1._SP)/sqrt(3._SP) f=zet**2./(1._SP+zet**2) psiu_26f=(1._SP-f)*psik+f*psic endif end function psiu_26f !------------------------------------------------------------------------------ ! function psi=psiu_40(zet) function psiu_40(zet) use mod_prec ! computes velocity structure function implicit none real(SP) :: zet real(SP) :: a,b,c,d,dzet,x,psik,psic,f real(SP) :: psiu_40 ! dzet=min(50.,0.35*zet) ! stable # if !defined (DOUBLE_PRECISION) dzet=amin1(50._SP,0.35_SP*zet) ! stable # else dzet=dmin1(50._SP,0.35_SP*zet) ! stable # endif a=1._SP b=3._SP/4._SP c=5._SP d=0.35_SP psiu_40=-(a*zet+b*(zet-c/d)*exp(-dzet)+b*c/d) !k=find(zet<0) ! unstable if(zet.lt.0._SP) then x=(1._SP-18._SP*zet)**0.25 psik=2._SP*log((1._SP+x)/2._SP)+log((1._SP+x*x)/2._SP)-2._SP*atan(x)+2._SP*atan(1._SP) x=(1._SP-10._SP*zet)**0.3333 psic=1.5_SP*log((1._SP+x+x**2)/3._SP)-sqrt(3.0_SP) & *atan((1._SP+2._SP*x)/sqrt(3._SP))+4.0_SP*atan(1._SP)/sqrt(3._SP) f=zet**2./(1._SP+zet**2) psiu_40=(1._SP-f)*psik+f*psic endif end function psiu_40 !------------------------------------------------------------------------------ ! function exx=bucksat(T,P) function bucksat(T,P) use mod_prec ! computes saturation vapor pressure [mb] ! given T [degC] and P [mb] implicit none real(SP) :: T,P real(SP) :: bucksat bucksat=6.1121_SP*exp(17.502_SP*T/(T+240.97_SP))*(1.0007_SP+3.46e-6_SP*P) end function bucksat !------------------------------------------------------------------------------ !function qs=qsat26sea(T,P) function qsat26sea(T,P) use mod_prec ! computes surface saturation specific humidity [g/kg] ! given T [degC] and P [mb] implicit none real(SP) :: T,P real(SP) :: ex,es,bucksat real(SP) :: qsat26sea ex=bucksat(T,P) es=0.98_SP*ex ! reduction at sea surface qsat26sea=622._SP*es/(P-0.378_SP*es) end function qsat26sea !------------------------------------------------------------------------------ !function qs=qsat26lake(T,P) function qsat26lake(T,P) use mod_prec ! computes surface saturation specific humidity [g/kg] ! given T [degC] and P [mb] implicit none real(SP) :: T,P real(SP) :: ex,es,bucksat real(SP) :: qsat26lake ex=bucksat(T,P) !JQI es=0.98*ex ! reduction at sea surface es=1.0_SP*ex ! reduction at sea surface !MDR, don't apply 0.98 for freshwater qsat26lake=622._SP*es/(P-0.378_SP*es) end function qsat26lake !------------------------------------------------------------------------------ subroutine qsat26air(T,P,rh,q,em) use mod_prec ! computes saturation specific humidity [g/kg] ! given T [degC] and P [mb] implicit none real(SP) :: T,P,rh real(SP) :: es,bucksat real(SP) :: q,em es=bucksat(T,P) em=0.01_SP*rh*es q=622._SP*em/(P-0.378_SP*em) end subroutine qsat26air !------------------------------------------------------------------------------ ! function g=grv(lat) function grvf(lat) use mod_prec ! computes g [m/sec**2] given lat in deg implicit none real(SP) :: lat real(SP) :: c1,c2,c3,c4,gamma,phi,x real(SP) :: grvf real(SP), parameter :: pi=3.1415926_SP gamma=9.7803267715_SP c1=0.0052790414_SP c2=0.0000232718_SP c3=0.0000001262_SP c4=0.0000000007_SP phi=lat*pi/180._SP x=sin(phi) grvf=gamma*(1._SP+c1*x**2+c2*x**4+c3*x**6+c4*x**8) end function grvf !------------------------------------------------------------------------------ ! function RHrf=RHcalc(T,P,Q) function RHcalc(T,P,Q) use mod_prec ! computes relative humidity given T,P, & Q implicit none real(SP) :: T,P,Q real(SP) :: es,em real(SP) :: RHcalc es=6.1121_SP*exp(17.502_SP*T/(T+240.97_SP))*(1.0007_SP+3.46e-6_SP*P) em=Q*P/(0.378_SP*Q+0.622_SP) RHcalc=100._SP*em/es end function RHcalc # endif ! ----------------------------------------------