- Timestamp:
- 01/13/16 17:36:50 (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
codes/icosagcm/trunk/src/caldyn_kernels_hevi.f90
r366 r368 6 6 PRIVATE 7 7 8 REAL(rstd), PARAMETER :: pbot=1e5, Phi_bot=0., rho_bot=1e6 ! FIXME 9 10 LOGICAL, PARAMETER :: debug_hevi_solver = .FALSE. 11 8 12 PUBLIC :: compute_theta, compute_pvort_only, compute_caldyn_slow, & 9 13 compute_caldyn_solver, compute_caldyn_fast … … 12 16 13 17 SUBROUTINE compute_theta(ps,theta_rhodz, rhodz,theta) 14 USE icosa15 18 USE disvert_mod, ONLY : mass_dak, mass_dbk, caldyn_eta, eta_mass, ptop 16 19 USE exner_mod … … 52 55 53 56 SUBROUTINE compute_pvort_only(u,rhodz,qu,qv) 54 USE icosa55 57 USE exner_mod 56 58 USE trace … … 121 123 END SUBROUTINE compute_pvort_only 122 124 125 SUBROUTINE compute_NH_geopot(tau, m_ik, m_il, theta, W_il, Phi_il) 126 USE omp_para 127 USE disvert_mod 128 IMPLICIT NONE 129 REAL(rstd),INTENT(IN) :: tau ! solve Phi-tau*dPhi/dt = Phi_rhs 130 REAL(rstd),INTENT(IN) :: m_ik(iim*jjm,llm) 131 REAL(rstd),INTENT(IN) :: m_il(iim*jjm,llm+1) 132 REAL(rstd),INTENT(IN) :: theta(iim*jjm,llm) 133 REAL(rstd),INTENT(IN) :: W_il(iim*jjm,llm+1) ! vertical momentum 134 REAL(rstd),INTENT(INOUT) :: Phi_il(iim*jjm,llm+1) ! geopotential 135 136 REAL(rstd) :: Phi_star_il(iim*jjm,llm+1) 137 REAL(rstd) :: p_ik(iim*jjm,llm) ! pressure 138 REAL(rstd) :: R_il(iim*jjm,llm+1) ! rhs of tridiag problem 139 REAL(rstd) :: x_il(iim*jjm,llm+1) ! solution of tridiag problem 140 REAL(rstd) :: A_ik(iim*jjm,llm) ! off-diagonal coefficients of tridiag problem 141 REAL(rstd) :: B_il(iim*jjm,llm+1) ! diagonal coefficients of tridiag problem 142 REAL(rstd) :: C_ik(iim*jjm,llm) ! Thomas algorithm 143 REAL(rstd) :: D_il(iim*jjm,llm+1) ! Thomas algorithm 144 REAL(rstd) :: gamma, rho_ij, X_ij, Y_ij 145 REAL(rstd) :: wil, tau2_g, g2, gm2, ml_g2, c2_mik 146 147 INTEGER :: iter, ij, l 148 149 ! FIXME : vertical OpenMP parallelism will not work 150 151 tau2_g=tau*tau/g 152 g2=g*g 153 gm2 = g**-2 154 gamma = 1./(1.-kappa) 155 156 ! compute Phi_star 157 DO l=1,llm+1 158 !DIR$ SIMD 159 DO ij=ij_begin_ext,ij_end_ext 160 Phi_star_il(ij,l) = Phi_il(ij,l) + tau*g2*(W_il(ij,l)/m_il(ij,l)-tau) 161 ENDDO 162 ENDDO 163 164 ! Newton-Raphson iteration : Phi_il contains current guess value 165 DO iter=1,2 ! 2 iterations should be enough 166 167 ! Compute pressure, A_ik 168 DO l=1,llm 169 !DIR$ SIMD 170 DO ij=ij_begin_ext,ij_end_ext 171 rho_ij = (g*m_ik(ij,l))/(Phi_il(ij,l+1)-Phi_il(ij,l)) 172 X_ij = (cpp/preff)*kappa*theta(ij,l)*rho_ij 173 p_ik(ij,l) = preff*(X_ij**gamma) 174 c2_mik = gamma*p_ik(ij,l)/(rho_ij*m_ik(ij,l)) ! c^2 = gamma*R*T = gamma*p/rho 175 A_ik(ij,l) = c2_mik*(tau/g*rho_ij)**2 176 ENDDO 177 ENDDO 178 179 ! Compute residual, B_il 180 ! bottom interface l=1 181 !DIR$ SIMD 182 DO ij=ij_begin_ext,ij_end_ext 183 ml_g2 = gm2*m_il(ij,1) 184 B_il(ij,1) = A_ik(ij,1) + ml_g2 + tau2_g*rho_bot 185 R_il(ij,1) = ml_g2*( Phi_il(ij,1)-Phi_star_il(ij,1)) & 186 + tau2_g*( p_ik(ij,1)-pbot+rho_bot*(Phi_il(ij,1)-Phi_bot) ) 187 ENDDO 188 ! inner interfaces 189 DO l=2,llm 190 !DIR$ SIMD 191 DO ij=ij_begin_ext,ij_end_ext 192 ml_g2 = gm2*m_il(ij,l) 193 B_il(ij,l) = A_ik(ij,l)+A_ik(ij,l-1) + ml_g2 194 R_il(ij,l) = ml_g2*( Phi_il(ij,l)-Phi_star_il(ij,l)) & 195 + tau2_g*(p_ik(ij,l)-p_ik(ij,l-1)) 196 ! consistency check : if Wil=0 and initial state is in hydrostatic balance 197 ! then Phi_star_il(ij,l) = Phi_il(ij,l) - tau^2*g^2 198 ! and residual = tau^2*(ml+(1/g)dl_pi)=0 199 ENDDO 200 ENDDO 201 ! top interface l=llm+1 202 !DIR$ SIMD 203 DO ij=ij_begin_ext,ij_end_ext 204 ml_g2 = gm2*m_il(ij,llm+1) 205 B_il(ij,llm+1) = A_ik(ij,llm) + ml_g2 206 R_il(ij,llm+1) = ml_g2*( Phi_il(ij,llm+1)-Phi_star_il(ij,llm+1)) & 207 + tau2_g*( ptop-p_ik(ij,llm) ) 208 ENDDO 209 210 ! FIXME later 211 ! the lines below modify the tridiag problem 212 ! for flat, rigid boundary conditions at top and bottom : 213 ! zero out A(1), A(llm), R(1), R(llm+1) 214 ! => x(l)=0 at l=1,llm+1 215 DO ij=ij_begin_ext,ij_end_ext 216 A_ik(ij,1) = 0. 217 A_ik(ij,llm) = 0. 218 R_il(ij,1) = 0. 219 R_il(ij,llm+1) = 0. 220 ENDDO 221 222 IF(debug_hevi_solver) THEN ! print Linf(residual) 223 PRINT *, '[hevi_solver] R,p', iter, MAXVAL(ABS(R_il)), MAXVAL(p_ik) 224 END IF 225 226 ! Solve -A(l-1)x(l-1) + B(l)x(l) - A(l)x(l+1) = R(l) using Thomas algorithm 227 ! Forward sweep : 228 ! C(0)=0, C(l) = -A(l) / (B(l)+A(l-1)C(l-1)), 229 ! D(0)=0, D(l) = (R(l)+A(l-1)D(l-1)) / (B(l)+A(l-1)C(l-1)) 230 ! bottom interface l=1 231 !DIR$ SIMD 232 DO ij=ij_begin_ext,ij_end_ext 233 X_ij = 1./B_il(ij,1) 234 C_ik(ij,1) = -A_ik(ij,1) * X_ij 235 D_il(ij,1) = R_il(ij,1) * X_ij 236 ENDDO 237 ! inner interfaces/layers 238 DO l=2,llm 239 !DIR$ SIMD 240 DO ij=ij_begin_ext,ij_end_ext 241 X_ij = 1./(B_il(ij,l) + A_ik(ij,l-1)*C_ik(ij,l-1)) 242 C_ik(ij,l) = -A_ik(ij,l) * X_ij 243 D_il(ij,l) = (R_il(ij,l)+A_ik(ij,l-1)*D_il(ij,l-1)) * X_ij 244 ENDDO 245 ENDDO 246 ! top interface l=llm+1 247 !DIR$ SIMD 248 DO ij=ij_begin_ext,ij_end_ext 249 X_ij = 1./(B_il(ij,llm+1) + A_ik(ij,llm)*C_ik(ij,llm)) 250 D_il(ij,llm+1) = (R_il(ij,llm+1)+A_ik(ij,llm)*D_il(ij,llm)) * X_ij 251 ENDDO 252 253 ! Back substitution : 254 ! x(i) = D(i)-C(i)x(i+1), x(N+1)=0 255 ! + Newton-Raphson update 256 x_il=0. ! FIXME 257 ! top interface l=llm+1 258 !DIR$ SIMD 259 DO ij=ij_begin_ext,ij_end_ext 260 x_il(ij,llm+1) = D_il(ij,llm+1) 261 Phi_il(ij,llm+1) = Phi_il(ij,llm+1) - x_il(ij,llm+1) 262 ENDDO 263 ! lower interfaces 264 DO l=llm,1,-1 265 !DIR$ SIMD 266 DO ij=ij_begin_ext,ij_end_ext 267 x_il(ij,l) = D_il(ij,l) - C_ik(ij,l)*x_il(ij,l+1) 268 Phi_il(ij,l) = Phi_il(ij,l) - x_il(ij,l) 269 ENDDO 270 ENDDO 271 272 IF(debug_hevi_solver) THEN 273 PRINT *, '[hevi_solver] A,B', iter, MAXVAL(ABS(A_ik)),MAXVAL(ABS(B_il)) 274 PRINT *, '[hevi_solver] C,D', iter, MAXVAL(ABS(C_ik)),MAXVAL(ABS(D_il)) 275 DO l=1,llm+1 276 WRITE(*,'(A,I2.1,I3.2,E9.2)'), '[hevi_solver] x', iter,l, MAXVAL(ABS(x_il(:,l))) 277 END DO 278 END IF 279 280 END DO ! Newton-Raphson 281 282 END SUBROUTINE compute_NH_geopot 283 123 284 SUBROUTINE compute_caldyn_solver(tau,rhodz,theta,pk, geopot,W, dPhi,dW) 124 USE icosa125 285 USE disvert_mod 126 286 USE exner_mod 127 287 USE trace 128 288 USE omp_para 129 USE disvert_mod130 289 IMPLICIT NONE 131 290 REAL(rstd),INTENT(IN) :: tau ! "solve" Phi-tau*dPhi/dt = Phi_rhs … … 138 297 REAL(rstd),INTENT(OUT) :: dPhi(iim*jjm,llm+1) 139 298 140 INTEGER :: ij,l141 INTEGER :: ij_omp_begin_ext, ij_omp_end_ext142 REAL(rstd) :: gamma, rho_ij, X_ij, Y_ij, m_il299 REAL(rstd) :: m_il(iim*jjm,llm+1) ! rhodz averaged to interfaces 300 REAL(rstd) :: gamma, rho_ij, X_ij, Y_ij 301 INTEGER :: ij, l 143 302 144 303 CALL trace_start("compute_caldyn_solver") 145 304 146 CALL distrib_level(ij_end_ext-ij_begin_ext+1,ij_omp_begin_ext,ij_omp_end_ext) 147 ij_omp_begin_ext=ij_omp_begin_ext+ij_begin_ext-1 148 ij_omp_end_ext=ij_omp_end_ext+ij_begin_ext-1 149 150 IF(tau>0) THEN 151 PRINT *, 'No implicit solver for NH yet' 152 STOP 305 ! FIXME : vertical OpenMP parallelism will not work 306 307 ! average m_ik to interfaces => m_il 308 !DIR$ SIMD 309 DO ij=ij_begin_ext,ij_end_ext 310 m_il(ij,1) = .5*rhodz(ij,1) 311 ENDDO 312 DO l=2,llm 313 !DIR$ SIMD 314 DO ij=ij_begin_ext,ij_end_ext 315 m_il(ij,l) = .5*(rhodz(ij,l-1)+rhodz(ij,l)) 316 ENDDO 317 ENDDO 318 !DIR$ SIMD 319 DO ij=ij_begin_ext,ij_end_ext 320 m_il(ij,llm+1) = .5*rhodz(ij,llm) 321 ENDDO 322 323 IF(tau>0) THEN ! solve implicit problem for geopotential 324 CALL compute_NH_geopot(tau, rhodz, m_il, theta, W, geopot) 153 325 END IF 154 326 … … 158 330 ! Cp/Cv = 1/(1-kappa) 159 331 gamma = 1./(1.-kappa) 160 DO l= ll_begin,ll_end161 !DIR$ SIMD 162 DO ij=ij_ omp_begin_ext,ij_omp_end_ext332 DO l=1,llm 333 !DIR$ SIMD 334 DO ij=ij_begin_ext,ij_end_ext 163 335 rho_ij = (g*rhodz(ij,l))/(geopot(ij,l+1)-geopot(ij,l)) 164 336 X_ij = (cpp/preff)*kappa*theta(ij,l)*rho_ij … … 170 342 ENDDO 171 343 172 ! Compute tendencies for geopotential and vertical momentum173 DO l= ll_beginp1,ll_end174 !DIR$ SIMD 175 DO ij=ij_ omp_begin_ext,ij_omp_end_ext176 m_il = .5*(rhodz(ij,l)+rhodz(ij,l-1))177 dW(ij,l) = (1./g)*(pk(ij,l-1)-pk(ij,l)) - m_il178 dPhi(ij,l) = g*g*W(ij,l)/m_il 344 ! Update W, compute tendencies for geopotential and vertical momentum 345 DO l=2,llm 346 !DIR$ SIMD 347 DO ij=ij_begin_ext,ij_end_ext 348 dW(ij,l) = (1./g)*(pk(ij,l-1)-pk(ij,l)) - m_il(ij,l) 349 W(ij,l) = W(ij,l)+tau*dW(ij,l) ! update W 350 dPhi(ij,l) = g*g*W(ij,l)/m_il(ij,l) 179 351 ENDDO 180 352 ! PRINT *,'Max dPhi', l,ij_begin,ij_end, MAXVAL(abs(dPhi(ij_begin:ij_end,l))) … … 191 363 ENDDO 192 364 ! Upper BC p=ptop 193 ! DO ij=ij_omp_begin_ext,ij_omp_end_ext194 ! dPhi(ij,llm+1) = W(ij,llm+1)/rhodz(ij,llm)195 ! dW(ij,llm+1) = (1./g)*(pk(ij,llm)-ptop) - .5*rhodz(ij,llm)196 ! ENDDO365 ! DO ij=ij_omp_begin_ext,ij_omp_end_ext 366 ! dPhi(ij,llm+1) = W(ij,llm+1)/rhodz(ij,llm) 367 ! dW(ij,llm+1) = (1./g)*(pk(ij,llm)-ptop) - .5*rhodz(ij,llm) 368 ! ENDDO 197 369 198 370 ! Compute Exner function (needed by compute_caldyn_fast) 199 DO l= ll_begin,ll_end200 !DIR$ SIMD 201 DO ij=ij_ omp_begin_ext,ij_omp_end_ext371 DO l=1,llm 372 !DIR$ SIMD 373 DO ij=ij_begin_ext,ij_end_ext 202 374 pk(ij,l) = cpp*((pk(ij,l)/preff)**kappa) ! other formulae possible if exponentiation is slow 203 375 ENDDO
Note: See TracChangeset
for help on using the changeset viewer.