MODULE caldyn_kernels_mod USE icosa USE transfert_mod USE caldyn_kernels_base_mod IMPLICIT NONE PRIVATE PUBLIC :: compute_planetvel, compute_pvort, compute_geopot, & compute_caldyn_horiz, compute_caldyn_vert CONTAINS SUBROUTINE compute_planetvel(planetvel) USE wind_mod REAL(rstd),INTENT(OUT) :: planetvel(iim*3*jjm) REAL(rstd) :: ulon(iim*3*jjm) REAL(rstd) :: ulat(iim*3*jjm) REAL(rstd) :: lon,lat INTEGER :: ij DO ij=ij_begin_ext,ij_end_ext ulon(ij+u_right)=radius*omega*cos(lat_e(ij+u_right)) ulat(ij+u_right)=0 ulon(ij+u_lup)=radius*omega*cos(lat_e(ij+u_lup)) ulat(ij+u_lup)=0 ulon(ij+u_ldown)=radius*omega*cos(lat_e(ij+u_ldown)) ulat(ij+u_ldown)=0 END DO CALL compute_wind2D_perp_from_lonlat_compound(ulon, ulat, planetvel) END SUBROUTINE compute_planetvel SUBROUTINE compute_pvort(ps,u,theta_rhodz, rhodz,theta,qu,qv) USE icosa USE disvert_mod, ONLY : mass_dak, mass_dbk, caldyn_eta, eta_mass, ptop USE trace USE omp_para IMPLICIT NONE REAL(rstd),INTENT(IN) :: u(iim*3*jjm,llm) REAL(rstd),INTENT(IN) :: ps(iim*jjm) REAL(rstd),INTENT(IN) :: theta_rhodz(iim*jjm,llm) REAL(rstd),INTENT(INOUT) :: rhodz(iim*jjm,llm) REAL(rstd),INTENT(OUT) :: theta(iim*jjm,llm) REAL(rstd),INTENT(OUT) :: qu(iim*3*jjm,llm) REAL(rstd),INTENT(OUT) :: qv(iim*2*jjm,llm) INTEGER :: i,j,ij,l REAL(rstd) :: etav,hv, m CALL trace_start("compute_pvort") ! IF(caldyn_eta==eta_mass) THEN ! CALL wait_message(req_ps) ! COM00 ! ELSE ! CALL wait_message(req_mass) ! COM00 ! END IF ! CALL wait_message(req_theta_rhodz) ! COM01 IF(caldyn_eta==eta_mass) THEN ! Compute mass & theta DO l = ll_begin,ll_end ! CALL test_message(req_u) !DIR$ SIMD DO ij=ij_begin_ext,ij_end_ext m = mass_dak(l)+(ps(ij)*g+ptop)*mass_dbk(l) ! ps is actually Ms rhodz(ij,l) = m/g theta(ij,l) = theta_rhodz(ij,l)/rhodz(ij,l) ENDDO ENDDO ELSE ! Compute only theta DO l = ll_begin,ll_end ! CALL test_message(req_u) !DIR$ SIMD DO ij=ij_begin_ext,ij_end_ext theta(ij,l) = theta_rhodz(ij,l)/rhodz(ij,l) ENDDO ENDDO END IF ! CALL wait_message(req_u) ! COM02 !!! Compute shallow-water potential vorticity DO l = ll_begin,ll_end !DIR$ SIMD DO ij=ij_begin_ext,ij_end_ext etav= 1./Av(ij+z_up)*( ne_rup * u(ij+u_rup,l) & + ne_left * u(ij+t_rup+u_left,l) & - ne_lup * u(ij+u_lup,l) ) hv = Riv2(ij,vup) * rhodz(ij,l) & + Riv2(ij+t_rup,vldown) * rhodz(ij+t_rup,l) & + Riv2(ij+t_lup,vrdown) * rhodz(ij+t_lup,l) qv(ij+z_up,l) = ( etav+fv(ij+z_up) )/hv etav = 1./Av(ij+z_down)*( ne_ldown * u(ij+u_ldown,l) & + ne_right * u(ij+t_ldown+u_right,l) & - ne_rdown * u(ij+u_rdown,l) ) hv = Riv2(ij,vdown) * rhodz(ij,l) & + Riv2(ij+t_ldown,vrup) * rhodz(ij+t_ldown,l) & + Riv2(ij+t_rdown,vlup) * rhodz(ij+t_rdown,l) qv(ij+z_down,l) =( etav+fv(ij+z_down) )/hv ENDDO !DIR$ SIMD DO ij=ij_begin,ij_end qu(ij+u_right,l) = 0.5*(qv(ij+z_rdown,l)+qv(ij+z_rup,l)) qu(ij+u_lup,l) = 0.5*(qv(ij+z_up,l)+qv(ij+z_lup,l)) qu(ij+u_ldown,l) = 0.5*(qv(ij+z_ldown,l)+qv(ij+z_down,l)) END DO ENDDO CALL trace_end("compute_pvort") END SUBROUTINE compute_pvort !************** caldyn_horiz = caldyn_fast + caldyn_slow + caldyn_coriolis *************** SUBROUTINE compute_caldyn_horiz(u,rhodz,qu,theta,pk,geopot, hflux,convm, dtheta_rhodz, du) USE icosa USE disvert_mod USE trace USE omp_para IMPLICIT NONE REAL(rstd),INTENT(IN) :: u(iim*3*jjm,llm) ! prognostic "velocity" REAL(rstd),INTENT(IN) :: rhodz(iim*jjm,llm) REAL(rstd),INTENT(IN) :: qu(iim*3*jjm,llm) REAL(rstd),INTENT(IN) :: theta(iim*jjm,llm) ! potential temperature REAL(rstd),INTENT(INOUT) :: pk(iim*jjm,llm) ! Exner function REAL(rstd),INTENT(IN) :: geopot(iim*jjm,llm+1) ! geopotential REAL(rstd),INTENT(OUT) :: hflux(iim*3*jjm,llm) ! hflux in kg/s REAL(rstd),INTENT(OUT) :: convm(iim*jjm,llm) ! mass flux convergence REAL(rstd),INTENT(OUT) :: dtheta_rhodz(iim*jjm,llm) REAL(rstd),INTENT(OUT) :: du(iim*3*jjm,llm) REAL(rstd) :: cor_NT(iim*jjm,llm) ! NT coriolis force u.(du/dPhi) REAL(rstd) :: urel(3*iim*jjm,llm) ! relative velocity REAL(rstd) :: Ftheta(3*iim*jjm,llm) ! theta flux REAL(rstd) :: berni(iim*jjm,llm) ! Bernoulli function REAL(rstd) :: uu_right, uu_lup, uu_ldown INTEGER :: i,j,ij,l REAL(rstd) :: ww,uu CALL trace_start("compute_caldyn_horiz") ! CALL wait_message(req_theta_rhodz) DO l = ll_begin, ll_end !!! Compute mass and theta fluxes ! IF (caldyn_conserv==energy) CALL test_message(req_qu) !DIR$ SIMD DO ij=ij_begin_ext,ij_end_ext uu_right=0.5*(rhodz(ij,l)+rhodz(ij+t_right,l))*u(ij+u_right,l) uu_lup=0.5*(rhodz(ij,l)+rhodz(ij+t_lup,l))*u(ij+u_lup,l) uu_ldown=0.5*(rhodz(ij,l)+rhodz(ij+t_ldown,l))*u(ij+u_ldown,l) uu_right= uu_right*le_de(ij+u_right) uu_lup = uu_lup *le_de(ij+u_lup) uu_ldown= uu_ldown*le_de(ij+u_ldown) hflux(ij+u_right,l)=uu_right hflux(ij+u_lup,l) =uu_lup hflux(ij+u_ldown,l)=uu_ldown ! hflux(ij+u_right,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_right,l))*u(ij+u_right,l)*le(ij+u_right) ! hflux(ij+u_lup,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_lup,l))*u(ij+u_lup,l)*le(ij+u_lup) ! hflux(ij+u_ldown,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_ldown,l))*u(ij+u_ldown,l)*le(ij+u_ldown) Ftheta(ij+u_right,l)=0.5*(theta(ij,l)+theta(ij+t_right,l))*hflux(ij+u_right,l) Ftheta(ij+u_lup,l)=0.5*(theta(ij,l)+theta(ij+t_lup,l))*hflux(ij+u_lup,l) Ftheta(ij+u_ldown,l)=0.5*(theta(ij,l)+theta(ij+t_ldown,l))*hflux(ij+u_ldown,l) ENDDO !!! compute horizontal divergence of fluxes !DIR$ SIMD DO ij=ij_begin,ij_end ! convm = -div(mass flux), sign convention as in Ringler et al. 2012, eq. 21 convm(ij,l)= -1./Ai(ij)*(ne_right*hflux(ij+u_right,l) + & ne_rup*hflux(ij+u_rup,l) + & ne_lup*hflux(ij+u_lup,l) + & ne_left*hflux(ij+u_left,l) + & ne_ldown*hflux(ij+u_ldown,l) + & ne_rdown*hflux(ij+u_rdown,l)) ! signe ? attention d (rho theta dz) ! dtheta_rhodz = -div(flux.theta) dtheta_rhodz(ij,l)=-1./Ai(ij)*(ne_right*Ftheta(ij+u_right,l) + & ne_rup*Ftheta(ij+u_rup,l) + & ne_lup*Ftheta(ij+u_lup,l) + & ne_left*Ftheta(ij+u_left,l) + & ne_ldown*Ftheta(ij+u_ldown,l) + & ne_rdown*Ftheta(ij+u_rdown,l)) ENDDO END DO !!! Compute potential vorticity (Coriolis) contribution to du SELECT CASE(caldyn_conserv) CASE(energy) ! energy-conserving TRiSK ! CALL wait_message(req_qu) ! COM03 DO l=ll_begin,ll_end !DIR$ SIMD DO ij=ij_begin,ij_end uu = wee(ij+u_right,1,1)*hflux(ij+u_rup,l)*(qu(ij+u_right,l)+qu(ij+u_rup,l))+ & wee(ij+u_right,2,1)*hflux(ij+u_lup,l)*(qu(ij+u_right,l)+qu(ij+u_lup,l))+ & wee(ij+u_right,3,1)*hflux(ij+u_left,l)*(qu(ij+u_right,l)+qu(ij+u_left,l))+ & wee(ij+u_right,4,1)*hflux(ij+u_ldown,l)*(qu(ij+u_right,l)+qu(ij+u_ldown,l))+ & wee(ij+u_right,5,1)*hflux(ij+u_rdown,l)*(qu(ij+u_right,l)+qu(ij+u_rdown,l))+ & wee(ij+u_right,1,2)*hflux(ij+t_right+u_ldown,l)*(qu(ij+u_right,l)+qu(ij+t_right+u_ldown,l))+ & wee(ij+u_right,2,2)*hflux(ij+t_right+u_rdown,l)*(qu(ij+u_right,l)+qu(ij+t_right+u_rdown,l))+ & wee(ij+u_right,3,2)*hflux(ij+t_right+u_right,l)*(qu(ij+u_right,l)+qu(ij+t_right+u_right,l))+ & wee(ij+u_right,4,2)*hflux(ij+t_right+u_rup,l)*(qu(ij+u_right,l)+qu(ij+t_right+u_rup,l))+ & wee(ij+u_right,5,2)*hflux(ij+t_right+u_lup,l)*(qu(ij+u_right,l)+qu(ij+t_right+u_lup,l)) du(ij+u_right,l) = .5*uu uu = wee(ij+u_lup,1,1)*hflux(ij+u_left,l)*(qu(ij+u_lup,l)+qu(ij+u_left,l)) + & wee(ij+u_lup,2,1)*hflux(ij+u_ldown,l)*(qu(ij+u_lup,l)+qu(ij+u_ldown,l)) + & wee(ij+u_lup,3,1)*hflux(ij+u_rdown,l)*(qu(ij+u_lup,l)+qu(ij+u_rdown,l)) + & wee(ij+u_lup,4,1)*hflux(ij+u_right,l)*(qu(ij+u_lup,l)+qu(ij+u_right,l)) + & wee(ij+u_lup,5,1)*hflux(ij+u_rup,l)*(qu(ij+u_lup,l)+qu(ij+u_rup,l)) + & wee(ij+u_lup,1,2)*hflux(ij+t_lup+u_right,l)*(qu(ij+u_lup,l)+qu(ij+t_lup+u_right,l)) + & wee(ij+u_lup,2,2)*hflux(ij+t_lup+u_rup,l)*(qu(ij+u_lup,l)+qu(ij+t_lup+u_rup,l)) + & wee(ij+u_lup,3,2)*hflux(ij+t_lup+u_lup,l)*(qu(ij+u_lup,l)+qu(ij+t_lup+u_lup,l)) + & wee(ij+u_lup,4,2)*hflux(ij+t_lup+u_left,l)*(qu(ij+u_lup,l)+qu(ij+t_lup+u_left,l)) + & wee(ij+u_lup,5,2)*hflux(ij+t_lup+u_ldown,l)*(qu(ij+u_lup,l)+qu(ij+t_lup+u_ldown,l)) du(ij+u_lup,l) = .5*uu uu = wee(ij+u_ldown,1,1)*hflux(ij+u_rdown,l)*(qu(ij+u_ldown,l)+qu(ij+u_rdown,l)) + & wee(ij+u_ldown,2,1)*hflux(ij+u_right,l)*(qu(ij+u_ldown,l)+qu(ij+u_right,l)) + & wee(ij+u_ldown,3,1)*hflux(ij+u_rup,l)*(qu(ij+u_ldown,l)+qu(ij+u_rup,l)) + & wee(ij+u_ldown,4,1)*hflux(ij+u_lup,l)*(qu(ij+u_ldown,l)+qu(ij+u_lup,l)) + & wee(ij+u_ldown,5,1)*hflux(ij+u_left,l)*(qu(ij+u_ldown,l)+qu(ij+u_left,l)) + & wee(ij+u_ldown,1,2)*hflux(ij+t_ldown+u_lup,l)*(qu(ij+u_ldown,l)+qu(ij+t_ldown+u_lup,l)) + & wee(ij+u_ldown,2,2)*hflux(ij+t_ldown+u_left,l)*(qu(ij+u_ldown,l)+qu(ij+t_ldown+u_left,l)) + & wee(ij+u_ldown,3,2)*hflux(ij+t_ldown+u_ldown,l)*(qu(ij+u_ldown,l)+qu(ij+t_ldown+u_ldown,l)) + & wee(ij+u_ldown,4,2)*hflux(ij+t_ldown+u_rdown,l)*(qu(ij+u_ldown,l)+qu(ij+t_ldown+u_rdown,l)) + & wee(ij+u_ldown,5,2)*hflux(ij+t_ldown+u_right,l)*(qu(ij+u_ldown,l)+qu(ij+t_ldown+u_right,l)) du(ij+u_ldown,l) = .5*uu ENDDO ENDDO CASE(enstrophy) ! enstrophy-conserving TRiSK DO l=ll_begin,ll_end !DIR$ SIMD DO ij=ij_begin,ij_end uu = wee(ij+u_right,1,1)*hflux(ij+u_rup,l)+ & wee(ij+u_right,2,1)*hflux(ij+u_lup,l)+ & wee(ij+u_right,3,1)*hflux(ij+u_left,l)+ & wee(ij+u_right,4,1)*hflux(ij+u_ldown,l)+ & wee(ij+u_right,5,1)*hflux(ij+u_rdown,l)+ & wee(ij+u_right,1,2)*hflux(ij+t_right+u_ldown,l)+ & wee(ij+u_right,2,2)*hflux(ij+t_right+u_rdown,l)+ & wee(ij+u_right,3,2)*hflux(ij+t_right+u_right,l)+ & wee(ij+u_right,4,2)*hflux(ij+t_right+u_rup,l)+ & wee(ij+u_right,5,2)*hflux(ij+t_right+u_lup,l) du(ij+u_right,l) = qu(ij+u_right,l)*uu uu = wee(ij+u_lup,1,1)*hflux(ij+u_left,l)+ & wee(ij+u_lup,2,1)*hflux(ij+u_ldown,l)+ & wee(ij+u_lup,3,1)*hflux(ij+u_rdown,l)+ & wee(ij+u_lup,4,1)*hflux(ij+u_right,l)+ & wee(ij+u_lup,5,1)*hflux(ij+u_rup,l)+ & wee(ij+u_lup,1,2)*hflux(ij+t_lup+u_right,l)+ & wee(ij+u_lup,2,2)*hflux(ij+t_lup+u_rup,l)+ & wee(ij+u_lup,3,2)*hflux(ij+t_lup+u_lup,l)+ & wee(ij+u_lup,4,2)*hflux(ij+t_lup+u_left,l)+ & wee(ij+u_lup,5,2)*hflux(ij+t_lup+u_ldown,l) du(ij+u_lup,l) = qu(ij+u_lup,l)*uu uu = wee(ij+u_ldown,1,1)*hflux(ij+u_rdown,l)+ & wee(ij+u_ldown,2,1)*hflux(ij+u_right,l)+ & wee(ij+u_ldown,3,1)*hflux(ij+u_rup,l)+ & wee(ij+u_ldown,4,1)*hflux(ij+u_lup,l)+ & wee(ij+u_ldown,5,1)*hflux(ij+u_left,l)+ & wee(ij+u_ldown,1,2)*hflux(ij+t_ldown+u_lup,l)+ & wee(ij+u_ldown,2,2)*hflux(ij+t_ldown+u_left,l)+ & wee(ij+u_ldown,3,2)*hflux(ij+t_ldown+u_ldown,l)+ & wee(ij+u_ldown,4,2)*hflux(ij+t_ldown+u_rdown,l)+ & wee(ij+u_ldown,5,2)*hflux(ij+t_ldown+u_right,l) du(ij+u_ldown,l) = qu(ij+u_ldown,l)*uu ENDDO ENDDO CASE DEFAULT STOP END SELECT !!! Compute bernouilli term = Kinetic Energy + geopotential IF(boussinesq) THEN DO l=ll_begin,ll_end !DIR$ SIMD DO ij=ij_begin,ij_end berni(ij,l) = pk(ij,l) + 1/(4*Ai(ij))*( & le_de(ij+u_right)*u(ij+u_right,l)**2 + & le_de(ij+u_rup)*u(ij+u_rup,l)**2 + & le_de(ij+u_lup)*u(ij+u_lup,l)**2 + & le_de(ij+u_left)*u(ij+u_left,l)**2 + & le_de(ij+u_ldown)*u(ij+u_ldown,l)**2 + & le_de(ij+u_rdown)*u(ij+u_rdown,l)**2 ) ! from now on pk contains the vertically-averaged geopotential pk(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1)) ENDDO ENDDO ELSE ! compressible DO l=ll_begin,ll_end !DIR$ SIMD DO ij=ij_begin,ij_end berni(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1)) & + 1/(4*Ai(ij))*( & le_de(ij+u_right)*u(ij+u_right,l)**2 + & le_de(ij+u_rup)*u(ij+u_rup,l)**2 + & le_de(ij+u_lup)*u(ij+u_lup,l)**2 + & le_de(ij+u_left)*u(ij+u_left,l)**2 + & le_de(ij+u_ldown)*u(ij+u_ldown,l)**2 + & le_de(ij+u_rdown)*u(ij+u_rdown,l)**2 ) ENDDO ENDDO END IF ! Boussinesq/compressible !!! Add gradients of Bernoulli and Exner functions to du DO l=ll_begin,ll_end !DIR$ SIMD DO ij=ij_begin,ij_end du(ij+u_right,l) = du(ij+u_right,l) + ( & 0.5*(theta(ij,l)+theta(ij+t_right,l)) & *( ne_right*pk(ij,l)+ne_left*pk(ij+t_right,l)) & + ne_right*berni(ij,l)+ne_left*berni(ij+t_right,l) ) du(ij+u_lup,l) = du(ij+u_lup,l) + ( & 0.5*(theta(ij,l)+theta(ij+t_lup,l)) & *( ne_lup*pk(ij,l)+ne_rdown*pk(ij+t_lup,l)) & + ne_lup*berni(ij,l)+ne_rdown*berni(ij+t_lup,l) ) du(ij+u_ldown,l) = du(ij+u_ldown,l) + ( & 0.5*(theta(ij,l)+theta(ij+t_ldown,l)) & *( ne_ldown*pk(ij,l)+ne_rup*pk(ij+t_ldown,l)) & + ne_ldown*berni(ij,l)+ne_rup*berni(ij+t_ldown,l) ) ENDDO ENDDO CALL trace_end("compute_caldyn_horiz") END SUBROUTINE compute_caldyn_horiz END MODULE caldyn_kernels_mod