10#include "scaleFElib.h"
21 use scale_const,
only: &
25 cpdry => const_cpdry, &
26 cvdry => const_cvdry, &
55 module procedure hydrostaic_build_rho_xyz_dry
56 module procedure hydrostaic_build_rho_xyz_moist
68 private :: gmres_hydro_core
69 private :: eval_ax, eval_ax_lin
70 private :: cal_del_flux, cal_del_flux_lin
71 private :: construct_pmatinv
88 Temp0, PRES_sfc, x, y, z, lcmesh3D, elem )
94 real(rp),
intent(out) :: dens_hyd(elem%np,lcmesh3d%nea)
95 real(rp),
intent(out) :: pres_hyd(elem%np,lcmesh3d%nea)
96 real(rp),
intent(in) :: x(elem%np,lcmesh3d%ne)
97 real(rp),
intent(in) :: y(elem%np,lcmesh3d%ne)
98 real(rp),
intent(in) :: z(elem%np,lcmesh3d%ne)
99 real(rp),
intent(in) :: temp0
100 real(rp),
intent(in) :: pres_sfc
106 h0 = rdry * temp0 / grav
109 do ke=lcmesh3d%NeS, lcmesh3d%NeE
110 pres_hyd(:,ke) = pres_sfc * exp( - z(:,ke) / h0 )
111 dens_hyd(:,ke) = pres_hyd(:,ke) / ( rdry * temp0 )
130 DENS_hyd, PRES_hyd, &
131 PotTemp0, PRES_sfc, x, y, z, lcmesh3D, elem )
137 real(rp),
intent(out) :: dens_hyd(elem%np,lcmesh3d%nea)
138 real(rp),
intent(out) :: pres_hyd(elem%np,lcmesh3d%nea)
139 real(rp),
intent(in) :: x(elem%np,lcmesh3d%ne)
140 real(rp),
intent(in) :: y(elem%np,lcmesh3d%ne)
141 real(rp),
intent(in) :: z(elem%np,lcmesh3d%ne)
142 real(rp),
intent(in) :: pottemp0
143 real(rp),
intent(in) :: pres_sfc
147 real(rp) :: exner(elem%np)
148 real(rp) :: exner_sfc
155 exner_sfc = (pres_sfc / pres00)**rovcp
158 do ke=lcmesh3d%NeS, lcmesh3d%NeE
160 exner(:) = exner_sfc - grav / (cpdry * pottemp0) * z(:,ke)
161 pres_hyd(:,ke) = pres00 * exner(:)**cpovr
162 dens_hyd(:,ke) = pres_hyd(:,ke) / ( rdry * exner(:) * pottemp0 )
182 DENS_hyd, PRES_hyd, &
183 BruntVaisalaFreq, PotTemp0, PRES_sfc, x, y, z, lcmesh3D, elem )
189 real(rp),
intent(out) :: dens_hyd(elem%np,lcmesh3d%nea)
190 real(rp),
intent(out) :: pres_hyd(elem%np,lcmesh3d%nea)
191 real(rp),
intent(in) :: x(elem%np,lcmesh3d%ne)
192 real(rp),
intent(in) :: y(elem%np,lcmesh3d%ne)
193 real(rp),
intent(in) :: z(elem%np,lcmesh3d%ne)
194 real(rp),
intent(in) :: bruntvaisalafreq
195 real(rp),
intent(in) :: pottemp0
196 real(rp),
intent(in) :: pres_sfc
200 real(rp) :: pt(elem%np)
201 real(rp) :: exner(elem%np)
202 real(rp) :: exner_sfc
209 exner_sfc = (pres_sfc / pres00)**rovcp
212 do ke=lcmesh3d%NeS, lcmesh3d%NeE
215 pt(:) = pottemp0 * exp( bruntvaisalafreq**2 / grav * z(:,ke) )
216 exner(:) = exner_sfc + grav**2 / ( cpdry * bruntvaisalafreq**2 ) * ( 1.0_rp / pt(:) - 1.0_rp / pottemp0 )
218 pres_hyd(:,ke) = pres00 * exner(:)**cpovr
219 dens_hyd(:,ke) = pres_hyd(:,ke) / ( rdry * exner(:) * pt(:) )
239 DENS_hyd, PRES_hyd, &
240 TLAPS, Temp0, PRES_sfc, x, y, z, lcmesh3D, elem )
246 real(rp),
intent(out) :: dens_hyd(elem%np,lcmesh3d%nea)
247 real(rp),
intent(out) :: pres_hyd(elem%np,lcmesh3d%nea)
248 real(rp),
intent(in) :: x(elem%np,lcmesh3d%ne)
249 real(rp),
intent(in) :: y(elem%np,lcmesh3d%ne)
250 real(rp),
intent(in) :: z(elem%np,lcmesh3d%ne)
251 real(rp),
intent(in) :: tlaps
252 real(rp),
intent(in) :: temp0
253 real(rp),
intent(in) :: pres_sfc
258 real(rp) :: temp(elem%np)
261 fac = grav / ( rdry * tlaps )
264 do ke=lcmesh3d%NeS, lcmesh3d%NeE
265 temp(:) = temp0 * ( 1.0_rp - tlaps / temp0 * z(:,ke) )
266 pres_hyd(:,ke) = pres00 * ( temp(:) / temp0 )**fac
267 dens_hyd(:,ke) = pres_hyd(:,ke) / ( rdry * temp(:) )
287 DENS_hyd, PRES_hyd, &
288 PTLAPS, PotTemp0, PRES_sfc, x, y, z, lcmesh3D, elem )
294 real(rp),
intent(out) :: dens_hyd(elem%np,lcmesh3d%nea)
295 real(rp),
intent(out) :: pres_hyd(elem%np,lcmesh3d%nea)
296 real(rp),
intent(in) :: x(elem%np,lcmesh3d%ne)
297 real(rp),
intent(in) :: y(elem%np,lcmesh3d%ne)
298 real(rp),
intent(in) :: z(elem%np,lcmesh3d%ne)
299 real(rp),
intent(in) :: ptlaps
300 real(rp),
intent(in) :: pottemp0
301 real(rp),
intent(in) :: pres_sfc
305 real(rp) :: pt(elem%np)
306 real(rp) :: exner(elem%np)
307 real(rp) :: exner_sfc
314 exner_sfc = (pres_sfc / pres00)**rovcp
317 do ke=lcmesh3d%NeS, lcmesh3d%NeE
320 pt(:) = pottemp0 + ptlaps * z(:,ke)
321 exner(:) = exner_sfc - grav / ( cpdry * ptlaps ) * log( 1.0_rp + ptlaps / pottemp0 * z(:,ke) )
323 pres_hyd(:,ke) = pres00 * exner(:)**cpovr
324 dens_hyd(:,ke) = pres_hyd(:,ke) / ( rdry * exner(:) * pt(:) )
343 subroutine hydrostaic_build_rho_xyz_dry( &
345 DENS_hyd, PRES_hyd, &
347 x, y, z, lcmesh, elem, &
354 real(RP),
intent(out) :: DDENS(elem%Np,lcmesh%NeA)
355 real(RP),
intent(in) :: DENS_hyd(elem%Np,lcmesh%NeA)
356 real(RP),
intent(in) :: PRES_hyd(elem%Np,lcmesh%NeA)
357 real(RP),
intent(in) :: x(elem%Np,lcmesh%Ne)
358 real(RP),
intent(in) :: y(elem%Np,lcmesh%Ne)
359 real(RP),
intent(in) :: z(elem%Np,lcmesh%Ne)
360 real(RP),
intent(in) :: POT(elem%Np,lcmesh%NeZ,lcmesh%NeX,lcmesh%NeY)
361 real(RP),
intent(in),
optional :: bnd_SFC_PRES(lcmesh%lcmesh2D%refElem2D%Np,lcmesh%Ne2DA)
363 real(RP) :: Rtot (elem%Np,lcmesh%NeZ,lcmesh%NeX,lcmesh%NeY)
364 real(RP) :: CPtot_ov_CVtot(elem%Np,lcmesh%NeZ,lcmesh%NeX,lcmesh%NeY)
371 cptot_ov_cvtot(:,:,:,:) = cpdry / cvdry
375 call hydrostaic_build_rho_xyz_moist( &
377 dens_hyd, pres_hyd, &
378 pot, rtot, cptot_ov_cvtot, &
379 x, y, z, lcmesh, elem, &
383 end subroutine hydrostaic_build_rho_xyz_dry
400 subroutine hydrostaic_build_rho_xyz_moist( &
402 DENS_hyd, PRES_hyd, &
403 POT, Rtot, CPtot_ov_CVtot, &
404 x, y, z, lcmesh, elem, &
407 use scale_const,
only: &
415 real(RP),
intent(out) :: DDENS(elem%Np,lcmesh%NeA)
416 real(RP),
intent(in) :: DENS_hyd(elem%Np,lcmesh%NeA)
417 real(RP),
intent(in) :: PRES_hyd(elem%Np,lcmesh%NeA)
418 real(RP),
intent(in) :: x(elem%Np,lcmesh%Ne)
419 real(RP),
intent(in) :: y(elem%Np,lcmesh%Ne)
420 real(RP),
intent(in) :: z(elem%Np,lcmesh%Ne)
421 real(RP),
intent(in) :: POT(elem%Np,lcmesh%NeZ,lcmesh%NeX,lcmesh%NeY)
422 real(RP),
intent(in) :: Rtot(elem%Np,lcmesh%NeZ,lcmesh%NeX,lcmesh%NeY)
423 real(RP),
intent(in) :: CPtot_ov_CVtot(elem%Np,lcmesh%NeZ,lcmesh%NeX,lcmesh%NeY)
424 real(RP),
intent(in),
optional :: bnd_SFC_PRES(lcmesh%lcmesh2D%refElem2D%Np,lcmesh%Ne2DA)
427 integer :: ke_x, ke_y, ke_z
431 real(RP),
parameter :: EPS = 1.0e-12_rp
435 type(
gmres) :: gmres_hydro
436 real(RP),
allocatable :: wj(:)
437 real(RP),
allocatable :: pinv_v(:)
439 integer :: vmapM_z1D(elem%NfpTot,lcmesh%NeZ)
440 integer :: vmapP_z1D(elem%NfpTot,lcmesh%NeZ)
441 real(RP) :: VARS (elem%Np,lcmesh%NeZ)
442 real(RP) :: VARS0 (elem%Np,lcmesh%NeZ)
443 real(RP) :: VAR_DEL(elem%Np,lcmesh%NeZ)
444 real(RP) :: b(elem%Np,lcmesh%NeZ)
445 real(RP) :: Ax(elem%Np,lcmesh%NeZ)
446 real(RP) :: nz(elem%NfpTot,lcmesh%NeZ)
447 real(RP) :: DENS_hyd_z(elem%Np,lcmesh%NeZ)
448 real(RP) :: PRES_hyd_z(elem%Np,lcmesh%NeZ)
449 real(RP) :: PmatDlu(elem%Np,elem%Np,lcmesh%NeZ)
450 integer :: PmatDlu_ipiv(elem%Np,lcmesh%NeZ)
451 real(RP) :: PmatL(elem%Np,elem%Np,lcmesh%NeZ)
452 real(RP) :: PmatU(elem%Np,elem%Np,lcmesh%NeZ)
453 real(RP) :: GsqrtV_z(elem%Np,lcmesh%NeZ)
455 logical :: is_converged
457 real(RP) :: IntrpMat_VPOrdM1(elem%Np,elem%Np)
459 real(RP) :: bnd_SFC_PRES_tmp(lcmesh%lcmesh2D%refElem2D%Np,lcmesh%Ne2DA)
463 if (
present(bnd_sfc_pres) )
then
465 do ke2d=lcmesh%lcmesh2D%NeS, lcmesh%lcmesh2D%NeE
466 bnd_sfc_pres_tmp(:,ke2d) = bnd_sfc_pres(:,ke2d)
470 do ke2d=lcmesh%lcmesh2D%NeS, lcmesh%lcmesh2D%NeE
471 bnd_sfc_pres_tmp(:,ke2d) = pres_hyd(elem%Hslice(:,1),ke2d)
477 n = elem%Np * lcmesh%NeZ
478 m = min(n / elem%Nnode_h1D**2, 30)
481 call gmres_hydro%Init( n, m, eps, eps0 )
482 allocate( wj(n), pinv_v(n) )
484 call dz%Init( elem%Dx3, storage_format=
'ELL' )
485 call lift%Init( elem%Lift, storage_format=
'ELL' )
487 call lcmesh%GetVmapZ1D( vmapm_z1d, vmapp_z1d )
493 do ke_y=1, lcmesh%NeY
494 do ke_x=1, lcmesh%NeX
495 ke2d = ke_x + (ke_y-1)*lcmesh%NeX
496 do ke_z=1, lcmesh%NeZ
497 ke = ke2d + (ke_z-1)*lcmesh%NeX*lcmesh%NeY
498 vars(:,ke_z) = 0.0_rp
500 vars0(:,ke_z) = vars(:,ke_z)
501 nz(:,ke_z) = lcmesh%normal_fn(:,ke,3)
503 dens_hyd_z(:,ke_z) = dens_hyd(:,ke)
504 pres_hyd_z(:,ke_z) = pres_hyd(:,ke)
505 gsqrtv_z(:,ke_z) = lcmesh%Gsqrt(:,ke) / lcmesh%GsqrtH(elem%IndexH2Dto3D(:),ke2d)
510 do ke_z=1, lcmesh%NeZ
511 var_del(:,ke_z) = 0.0_rp
514 call eval_ax( ax(:,:), &
515 vars, vars0, pot(:,:,ke_x,ke_y), rtot(:,:,ke_x,ke_y), &
516 cptot_ov_cvtot(:,:,ke_x,ke_y), dens_hyd_z, pres_hyd_z, &
517 bnd_sfc_pres_tmp(:,ke2d), &
518 dz, lift, intrpmat_vpordm1, lcmesh, elem, &
519 nz, vmapm_z1d, vmapp_z1d, ke_x, ke_y )
521 do ke_z=1, lcmesh%NeZ
522 b(:,ke_z) = - ax(:,ke_z)
524 if (lcmesh%tileID==1)
then
525 if (itr_nlin > 1)
then
526 log_progress(*) ke_x, ke_y,
"itr_lin=", itr_lin
527 log_progress(*)
"-------------------------------------"
529 log_progress(*) ke_x, ke_y,
"itr_nlin:", itr_nlin, 0,
": VAR", vars(elem%Colmask(:,1),1)
530 log_progress(*) ke_x, ke_y,
"itr_nlin:", itr_nlin, 0,
": b", b(elem%Colmask(:,1),1)
531 if( io_l )
call flush(io_fid_log)
534 if ( maxval(abs(b(:,:))) < 1.0e-10_rp )
exit
536 call construct_pmatinv( pmatdlu, pmatdlu_ipiv, pmatl, pmatu, &
537 vars0, pot(:,:,ke_x,ke_y), rtot(:,:,ke_x,ke_y), &
538 cptot_ov_cvtot(:,:,ke_x,ke_y), dens_hyd_z, pres_hyd_z, &
539 dz, lift, intrpmat_vpordm1, gsqrtv_z, lcmesh, elem, &
540 nz, vmapm_z1d, vmapp_z1d, ke_x, ke_y )
542 do itr_lin=1, 2*int(n/m)
544 call gmres_hydro_core( gmres_hydro, var_del, wj, is_converged, &
546 pmatdlu, pmatdlu_ipiv, pmatl, pmatu, pinv_v, &
547 pot(:,:,ke_x,ke_y), rtot(:,:,ke_x,ke_y), &
548 cptot_ov_cvtot(:,:,ke_x,ke_y), dens_hyd_z, pres_hyd_z, &
549 dz, lift, intrpmat_vpordm1, lcmesh, elem, &
550 nz, vmapm_z1d, vmapp_z1d, ke_x, ke_y )
554 if (is_converged)
exit
556 do ke_z=1, lcmesh%NeZ
557 vars(:,ke_z) = vars(:,ke_z) + var_del(:,ke_z)
558 vars0(:,ke_z) = vars(:,ke_z)
562 do ke_z=1, lcmesh%NeZ
563 ke = ke_x + (ke_y-1)*lcmesh%NeX + (ke_z-1)*lcmesh%NeX*lcmesh%NeY
564 ddens(:,ke) = vars(:,ke_z)
570 call gmres_hydro%Final()
575 end subroutine hydrostaic_build_rho_xyz_moist
580 subroutine gmres_hydro_core( gmres_hydro, x, wj, is_converged, &
582 PmatDlu, PmatDlu_ipiv, PmatL, PmatU, pinv_v, & ! (in)
583 pot, rtot, cptot_ov_cvtot, dens_hyd, pres_hyd, &
584 dz, lift, intrpmat_vpordm1, lmesh, elem, &
585 nz, vmapm, vmapp, ke_x, ke_y )
591 integer,
intent(in) :: N
592 integer,
intent(in) :: m
594 class(
gmres),
intent(inout) :: gmres_hydro
595 real(RP),
intent(inout) :: x(N)
596 real(RP),
intent(inout) :: wj(N)
597 logical,
intent(out) :: is_converged
598 real(RP),
intent(in) :: x0(N)
599 real(RP),
intent(in) :: b(N)
600 real(RP),
intent(in) :: PmatDlu(elem%Np,elem%Np,lmesh%NeZ)
601 integer,
intent(in) :: PmatDlu_ipiv(elem%Np,lmesh%NeZ)
602 real(RP),
intent(in) :: PmatL(elem%Np,elem%Np,lmesh%NeZ)
603 real(RP),
intent(in) :: PmatU(elem%Np,elem%Np,lmesh%NeZ)
604 real(RP),
intent(inout) :: pinv_v(N)
606 real(RP),
intent(in) :: POT(elem%Np,lmesh%NeZ)
607 real(RP),
intent(in) :: Rtot(elem%Np,lmesh%NeZ)
608 real(RP),
intent(in) :: CPtot_ov_CVtot(elem%Np,lmesh%NeZ)
609 real(RP),
intent(in) :: DENS_hyd(elem%Np,lmesh%NeZ)
610 real(RP),
intent(in) :: PRES_hyd(elem%Np,lmesh%NeZ)
612 real(RP),
intent(in) :: IntrpMat_VPOrdM1(elem%Np,elem%Np)
613 real(RP),
intent(in) :: nz(elem%NfpTot,lmesh%NeZ)
614 integer,
intent(in) :: vmapM(elem%NfpTot,lmesh%NeZ)
615 integer,
intent(in) :: vmapP(elem%NfpTot,lmesh%NeZ)
616 integer,
intent(in) :: ke_x, ke_y
621 call eval_ax_lin( wj(:), &
622 x, x0, pot, rtot, cptot_ov_cvtot, &
623 dens_hyd, pres_hyd, &
624 dz, lift, intrpmat_vpordm1, lmesh, elem, &
625 nz, vmapm, vmapp, ke_x, ke_y )
627 call gmres_hydro%Iterate_pre( b, wj, is_converged )
628 if (is_converged)
return
631 call matmul_pinv_v( pinv_v, pmatdlu, pmatdlu_ipiv, pmatl, pmatu, gmres_hydro%v(:,j) )
633 call eval_ax_lin( wj(:), &
634 pinv_v, x0, pot, rtot, cptot_ov_cvtot, &
635 dens_hyd, pres_hyd, &
636 dz, lift, intrpmat_vpordm1, lmesh, elem, &
637 nz, vmapm, vmapp, ke_x, ke_y )
639 call gmres_hydro%Iterate_step_j( j, wj, is_converged )
641 log_info(
"GMRES check**:",*)
"j=", j,
"g:", gmres_hydro%g(j+1),
"r:", gmres_hydro%r(j,j),
"hj(j+1):", gmres_hydro%hj(j+1)
642 if ( is_converged )
exit
648 call gmres_hydro%Iterate_post( wj )
649 call matmul_pinv_v_plus_x0( x, pmatdlu, pmatdlu_ipiv, pmatl, pmatu, wj)
655 subroutine matmul_pinv_v( pinv_v_, pDlu_, PmatDlu_ipiv_, pL, pU, v)
657 real(RP),
intent(out) :: pinv_v_(elem%Np,lmesh%NeZ)
658 real(RP),
intent(in) :: pDlu_(elem%Np,elem%Np,lmesh%NeZ)
659 integer,
intent(in) :: PmatDlu_ipiv_(elem%Np,lmesh%NeZ)
660 real(RP),
intent(in) :: pL(elem%Np,elem%Np,lmesh%NeZ)
661 real(RP),
intent(in) :: pU(elem%Np,elem%Np,lmesh%NeZ)
662 real(RP),
intent(in) :: v(elem%Np,lmesh%NeZ)
665 real(RP) :: tmp(elem%Np)
673 ve = vs + elem%Np - 1
674 pinv_v_(:,1) = v(vs:ve,1)
675 call dgetrs(
'N', n, 1, pdlu_(:,:,1), n, pmatdlu_ipiv_(:,1), pinv_v_(:,1), n, info)
679 pinv_v_(:,k) = v(vs:ve,k) &
680 - matmul( pl(:,:,k), pinv_v_(:,k-1) )
682 call dgetrs(
'N', n, 1, pdlu_(:,:,k), n, pmatdlu_ipiv_(:,k), pinv_v_(:,k), n, info)
686 do k=lmesh%NeZ-1, 1, -1
688 tmp(vs:ve) = matmul( pu(:,:,k), pinv_v_(:,k+1) )
689 call dgetrs(
'N', n, 1, pdlu_(:,:,k), n, pmatdlu_ipiv_(:,k), tmp(:), n, info)
692 ve = vs + elem%Np - 1
693 pinv_v_(:,k) = pinv_v_(:,k) - tmp(vs:ve)
697 end subroutine matmul_pinv_v
700 subroutine matmul_pinv_v_plus_x0( x_, pDlu_, PmatDlu_ipiv_, pL, pU, v)
702 real(RP),
intent(inout) :: x_(elem%Np,lmesh%NeZ)
703 real(RP),
intent(in) :: pDlu_(elem%Np,elem%Np,lmesh%NeZ)
704 integer,
intent(in) :: PmatDlu_ipiv_(elem%Np,lmesh%NeZ)
705 real(RP),
intent(in) :: pL(elem%Np,elem%Np,lmesh%NeZ)
706 real(RP),
intent(in) :: pU(elem%Np,elem%Np,lmesh%NeZ)
707 real(RP),
intent(in) :: v(elem%Np,lmesh%NeZ)
710 real(RP) :: tmp(elem%Np,lmesh%NeZ)
714 call matmul_pinv_v( tmp, pdlu_, pmatdlu_ipiv_, pl, pu, v)
717 x_(:,k) = x_(:,k) + tmp(:,k)
721 end subroutine matmul_pinv_v_plus_x0
723 end subroutine gmres_hydro_core
726 subroutine eval_ax( Ax, &
727 DDENS, DENS0, POT, Rtot, CPtot_ov_CVtot, & ! (in)
728 dens_hyd, pres_hyd, bnd_sfc_pres, &
729 dz, lift, intrpmat_vpordm1, lmesh, elem, &
730 nz, vmapm, vmapp, ke_x, ke_y )
736 real(RP),
intent(out) :: Ax(elem%Np,lmesh%NeZ)
737 real(RP),
intent(in) :: DDENS (elem%Np,lmesh%NeZ)
738 real(RP),
intent(in) :: DENS0(elem%Np,lmesh%NeZ)
739 real(RP),
intent(in) :: POT(elem%Np,lmesh%NeZ)
740 real(RP),
intent(in) :: Rtot(elem%Np,lmesh%NeZ)
741 real(RP),
intent(in) :: CPtot_ov_CVtot(elem%Np,lmesh%NeZ)
742 real(RP),
intent(in) :: DENS_hyd(elem%Np,lmesh%NeZ)
743 real(RP),
intent(in) :: PRES_hyd(elem%Np,lmesh%NeZ)
744 real(RP),
intent(in) :: bnd_SFC_PRES(lmesh%lcmesh2D%refElem2D%Np)
746 real(RP),
intent(in) :: IntrpMat_VPOrdM1(elem%Np,elem%Np)
748 real(RP),
intent(in) :: nz(elem%NfpTot,lmesh%NeZ)
749 integer,
intent(in) :: vmapM(elem%NfpTot,lmesh%NeZ)
750 integer,
intent(in) :: vmapP(elem%NfpTot,lmesh%NeZ)
751 integer,
intent(in) :: ke_x, ke_y
753 real(RP) :: DPRES(elem%Np), DENS(elem%Np)
754 real(RP) :: Fz(elem%Np), LiftDelFlx(elem%Np)
755 real(RP) :: del_flux(elem%NfpTot,lmesh%NeZ)
764 real(RP) :: GsqrtV(elem%Np)
768 rdovp00 = rdry / pres00
769 rp0 = 1.0_rp / pres00
771 call cal_del_flux( del_flux, &
772 ddens, pot, rtot, cptot_ov_cvtot, &
773 dens_hyd, pres_hyd, bnd_sfc_pres, &
774 nz, vmapm, vmapp, lmesh, elem )
778 ke = ke_x + (ke_y-1)*lmesh%NeX + (ke_z-1)*lmesh%NeX*lmesh%NeY
779 ke2d = lmesh%EMap3Dto2D(ke)
781 gsqrtv(:) = lmesh%Gsqrt(:,ke) / lmesh%GsqrtH(elem%IndexH2Dto3D,ke2d)
783 dens(:) = dens_hyd(:,ke_z) + ddens(:,ke_z)
784 dpres(:) = pres00 * ( rtot(:,ke_z) * rp0 * dens(:) * pot(:,ke_z) )**cptot_ov_cvtot(:,ke_z)
787 call sparsemat_matmul(lift, lmesh%Fscale(:,ke)*del_flux(:,ke_z), liftdelflx)
791 ax(:,ke_z) = ( lmesh%Escale(:,ke,3,3) * fz(:) + liftdelflx(:) ) / gsqrtv(:) &
792 + grav * matmul(intrpmat_vpordm1, dens(:))
796 end subroutine eval_ax
799 subroutine cal_del_flux( del_flux, &
800 DDENS_, POT_, Rtot_, CPtot_ov_CVtot_, &
801 DENS_hyd, PRES_hyd, bnd_SFC_PRES, &
802 nz, vmapM, vmapP, lmesh, elem )
808 real(RP),
intent(out) :: del_flux(elem%NfpTot*lmesh%NeZ)
809 real(RP),
intent(in) :: DDENS_(elem%Np*lmesh%NeZ)
810 real(RP),
intent(in) :: POT_(elem%Np*lmesh%NeZ)
811 real(RP),
intent(in) :: Rtot_(elem%Np*lmesh%NeZ)
812 real(RP),
intent(in) :: CPtot_ov_CVtot_(elem%Np*lmesh%NeZ)
813 real(RP),
intent(in) :: DENS_hyd(elem%Np*lmesh%NeZ)
814 real(RP),
intent(in) :: PRES_hyd(elem%Np*lmesh%NeZ)
815 real(RP),
intent(in) :: bnd_SFC_PRES(lmesh%lcmesh2D%refElem2D%Np)
816 real(RP),
intent(in) :: nz(elem%NfpTot*lmesh%NeZ)
817 integer,
intent(in) :: vmapM(elem%NfpTot*lmesh%NeZ)
818 integer,
intent(in) :: vmapP(elem%NfpTot*lmesh%NeZ)
821 integer :: p, p2D, f, ke_z
823 real(RP) :: dpresP, dpresM
824 real(RP) :: RtotOvP00M, RtotOvP00P
830 rp0 = 1.0_rp / pres00
836 do i=1, elem%NfpTot*lmesh%NeZ
842 do f=1, elem%Nfaces_v
844 p = p2d + (f-1)*elem%Nfp_v + elem%Nfaces_h * elem%Nfp_h
845 i = p + (ke_z-1)*elem%NfpTot
846 im = vmapm(i); ip = vmapp(i)
848 rtotovp00m = rtot_(im) * rp0
849 rtotovp00p = rtot_(ip) * rp0
851 fac = 0.5_rp * ( 1.0_rp - sign(1.0_rp,nz(i)) )
852 dpresm = pres00 * ( rtotovp00m * (dens_hyd(im) + ddens_(im)) * pot_(im) )**cptot_ov_cvtot_(im)
853 dpresp = pres00 * ( rtotovp00p * (dens_hyd(ip) + ddens_(ip)) * pot_(ip) )**cptot_ov_cvtot_(ip)
855 if ( ke_z==1 .and. im==ip ) dpresp = bnd_sfc_pres(p2d)
857 del_flux(i) = fac * ( dpresp - dpresm ) * nz(i)
865 end subroutine cal_del_flux
868 subroutine eval_ax_lin( Ax, &
869 DDENS, DDENS0, POT, Rtot, CPtot_ov_CVtot, & ! (in)
870 dens_hyd, pres_hyd, &
871 dz, lift, intrpmat_vpordm1, lmesh, elem, &
872 nz, vmapm, vmapp, ke_x, ke_y )
878 real(RP),
intent(out) :: Ax(elem%Np,lmesh%NeZ)
879 real(RP),
intent(in) :: DDENS (elem%Np,lmesh%NeZ)
880 real(RP),
intent(in) :: DDENS0(elem%Np,lmesh%NeZ)
881 real(RP),
intent(in) :: POT(elem%Np,lmesh%NeZ)
882 real(RP),
intent(in) :: Rtot(elem%Np,lmesh%NeZ)
883 real(RP),
intent(in) :: CPtot_ov_CVtot(elem%Np,lmesh%NeZ)
884 real(RP),
intent(in) :: DENS_hyd(elem%Np,lmesh%NeZ)
885 real(RP),
intent(in) :: PRES_hyd(elem%Np,lmesh%NeZ)
887 real(RP),
intent(in) :: IntrpMat_VPOrdM1(elem%Np,elem%Np)
888 real(RP),
intent(in) :: nz(elem%NfpTot,lmesh%NeZ)
889 integer,
intent(in) :: vmapM(elem%NfpTot,lmesh%NeZ)
890 integer,
intent(in) :: vmapP(elem%NfpTot,lmesh%NeZ)
891 integer,
intent(in) :: ke_x, ke_y
893 real(RP) :: PRES(elem%Np), PRES0(elem%Np)
894 real(RP) :: DPRES(elem%Np)
895 real(RP) :: Fz(elem%Np), LiftDelFlx(elem%Np)
896 real(RP) :: del_flux(elem%NfpTot,lmesh%NeZ)
904 real(RP) :: GsqrtV(elem%Np)
908 rp0 = 1.0_rp / pres00
910 call cal_del_flux_lin( del_flux, &
911 ddens, ddens0, pot, rtot, cptot_ov_cvtot, &
912 dens_hyd, pres_hyd, &
913 nz, vmapm, vmapp, lmesh, elem )
917 ke = ke_x + (ke_y-1)*lmesh%NeX + (ke_z-1)*lmesh%NeX*lmesh%NeY
918 ke2d = lmesh%EMap3Dto2D(ke)
920 gsqrtv(:) = lmesh%Gsqrt(:,ke) / lmesh%GsqrtH(elem%IndexH2Dto3D,ke2d)
922 pres0(:) = pres00 * ( rtot(:,ke_z) * rp0 * (dens_hyd(:,ke_z) + ddens0(:,ke_z)) * pot(:,ke_z) )**cptot_ov_cvtot(:,ke_z)
923 dpres(:) = cptot_ov_cvtot(:,ke_z) * pres0(:) / (dens_hyd(:,ke_z) + ddens0(:,ke_z)) * ddens(:,ke_z)
926 call sparsemat_matmul(lift, lmesh%Fscale(:,ke)*del_flux(:,ke_z), liftdelflx)
928 ax(:,ke_z) = ( lmesh%Escale(:,ke,3,3) * fz(:) + liftdelflx(:) ) / gsqrtv(:) &
929 + grav * matmul(intrpmat_vpordm1, ddens(:,ke_z))
933 end subroutine eval_ax_lin
936 subroutine cal_del_flux_lin( del_flux, &
937 DDENS_, DDENS0_, POT_, Rtot_, CPtot_ov_CVtot_, &
938 DENS_hyd_, PRES_hyd_, &
939 nz, vmapM, vmapP, lmesh, elem )
945 real(RP),
intent(out) :: del_flux(elem%NfpTot*lmesh%NeZ)
946 real(RP),
intent(in) :: DDENS_(elem%Np*lmesh%NeZ)
947 real(RP),
intent(in) :: DDENS0_(elem%Np*lmesh%NeZ)
948 real(RP),
intent(in) :: Rtot_(elem%Np*lmesh%NeZ)
949 real(RP),
intent(in) :: CPtot_ov_CVtot_(elem%Np*lmesh%NeZ)
950 real(RP),
intent(in) :: DENS_hyd_(elem%Np*lmesh%NeZ)
951 real(RP),
intent(in) :: PRES_hyd_(elem%Np*lmesh%NeZ)
952 real(RP),
intent(in) :: POT_(elem%Np*lmesh%NeZ)
953 real(RP),
intent(in) :: nz(elem%NfpTot*lmesh%NeZ)
954 integer,
intent(in) :: vmapM(elem%NfpTot*lmesh%NeZ)
955 integer,
intent(in) :: vmapP(elem%NfpTot*lmesh%NeZ)
958 integer :: p, p2D, f, ke_z
960 real(RP) :: dpresP, dpresM
961 real(RP) :: pres0P, pres0M
964 real(RP) :: RtotOvP00M
965 real(RP) :: RtotOvP00P
971 rp0 = 1.0_rp / pres00
977 do i=1, elem%NfpTot*lmesh%NeZ
983 do f=1, elem%Nfaces_v
985 p = p2d + (f-1)*elem%Nfp_v + elem%Nfaces_h * elem%Nfp_h
986 i = p + (ke_z-1)*elem%NfpTot
988 im = vmapm(i); ip = vmapp(i)
990 rtotovp00m = rtot_(im) * rp0
991 rtotovp00p = rtot_(ip) * rp0
993 pres0m = pres00 * ( rtotovp00m * (dens_hyd_(im) + ddens0_(im)) * pot_(im) )**cptot_ov_cvtot_(im)
994 pres0p = pres00 * ( rtotovp00p * (dens_hyd_(ip) + ddens0_(ip)) * pot_(ip) )**cptot_ov_cvtot_(ip)
996 fac = 0.5_rp * ( 1.0_rp - sign(1.0_rp,nz(i)) )
997 dpresm = cptot_ov_cvtot_(im) * pres0m / (dens_hyd_(im) + ddens0_(im)) * ddens_(im)
998 dpresp = cptot_ov_cvtot_(ip) * pres0p / (dens_hyd_(ip) + ddens0_(ip)) * ddens_(ip)
1000 if ( ke_z == 1 .and. im == ip ) dpresp = 0.0_rp
1002 del_flux(i) = fac * ( dpresp - dpresm ) * nz(i)
1010 end subroutine cal_del_flux_lin
1013 subroutine construct_pmatinv( PmatDlu, PmatDlu_ipiv, PmatL, PmatU, & ! (out)
1014 ddens0, pot, rtot, cptot_ov_cvtot, dens_hyd, pres_hyd, &
1015 dz, lift, intrpmat_vpordm1, gsqrtv, lmesh, elem, &
1016 nz, vmapm, vmapp, ke_x, ke_y )
1023 real(RP),
intent(out) :: PmatDlu(elem%Np,elem%Np,lmesh%NeZ)
1024 integer,
intent(out) :: PmatDlu_ipiv(elem%Np,lmesh%NeZ)
1025 real(RP),
intent(out) :: PmatL(elem%Np,elem%Np,lmesh%NeZ)
1026 real(RP),
intent(out) :: PmatU(elem%Np,elem%Np,lmesh%NeZ)
1027 real(RP),
intent(in) :: DDENS0(elem%Np,lmesh%NeZ)
1028 real(RP),
intent(in) :: POT(elem%Np,lmesh%NeZ)
1029 real(RP),
intent(in) :: Rtot(elem%Np,lmesh%NeZ)
1030 real(RP),
intent(in) :: CPtot_ov_CVtot(elem%Np,lmesh%NeZ)
1031 real(RP),
intent(in) :: DENS_hyd(elem%Np,lmesh%NeZ)
1032 real(RP),
intent(in) :: PRES_hyd(elem%Np,lmesh%NeZ)
1033 class(
sparsemat),
intent(in) :: Dz, Lift
1034 real(RP),
intent(in) :: IntrpMat_VPOrdM1(elem%Np,elem%Np)
1035 real(RP),
intent(in) :: GsqrtV(elem%Np,lmesh%NeZ)
1036 real(RP),
intent(in) :: nz(elem%NfpTot,lmesh%NeZ)
1037 integer,
intent(in) :: vmapM(elem%NfpTot,lmesh%NeZ)
1038 integer,
intent(in) :: vmapP(elem%NfpTot,lmesh%NeZ)
1039 integer,
intent(in) :: ke_x, ke_y
1041 real(RP) :: DENS0(elem%Np,lmesh%NeZ)
1042 real(RP) :: PRES0(elem%Np,lmesh%NeZ)
1043 integer :: ke_z, ke_z2
1044 integer :: ke, p, fp, v
1045 real(RP) :: gamm, rgamm, rP0
1046 real(RP) :: dz_p(elem%Np)
1047 real(RP) :: PmatD(elem%Np,elem%Np)
1049 integer :: f1, f2, fp_s, fp_e
1050 integer :: FmV(elem%Nfp_v)
1051 integer :: FmV2 (elem%Nfp_v)
1052 real(RP) :: lift_op(elem%Np,elem%NfpTot)
1053 real(RP) :: lift_(elem%Np,elem%Np)
1054 real(RP) :: lift_2(elem%Np,elem%Np)
1055 real(RP) :: tmp(elem%Nfp_v)
1062 rp0 = 1.0_rp / pres00
1064 lift_op(:,:) = elem%Lift
1067 do ke_z=1, lmesh%NeZ
1068 dens0(:,ke_z) = dens_hyd(:,ke_z) + ddens0(:,ke_z)
1069 pres0(:,ke_z) = pres00 * ( rtot(:,ke_z) * rp0 * dens0(:,ke_z) * pot(:,ke_z) )**cptot_ov_cvtot(:,ke_z)
1075 do ke_z=1, lmesh%NeZ
1076 ke = ke_x + (ke_y-1)*lmesh%NeX + (ke_z-1)*lmesh%NeX*lmesh%NeY
1080 pmatl(:,:,ke_z) = 0.0_rp
1081 pmatu(:,:,ke_z) = 0.0_rp
1084 dz_p(:) = lmesh%Escale(p,ke,3,3) * elem%Dx3(p,:)
1085 pmatd(p,:) = dz_p(:) * cptot_ov_cvtot(:,ke_z) * pres0(:,ke_z) / ( dens0(:,ke_z) * gsqrtv(p,ke_z) ) &
1086 + grav * intrpmat_vpordm1(p,:)
1091 f2 = 2; ke_z2 = max(ke_z-1, 1)
1093 f2 = 1; ke_z2 = min(ke_z+1, lmesh%NeZ)
1095 if ( (ke_z == 1 .and. f1==1) .or. (ke_z == lmesh%NeZ .and. f1==elem%Nfaces_v) )
then
1099 fmv(:) = elem%Fmask_v(:,f1)
1100 fmv2(:) = elem%Fmask_v(:,f2)
1102 fp_s = elem%Nfp_h * elem%Nfaces_h + 1 + (f1-1)*elem%Nfp_v
1103 fp_e = fp_s + elem%Nfp_v - 1
1107 lift_2(:,:) = 0.0_rp
1111 fac = 0.5_rp * ( 1.0_rp - sign(1.0_rp,nz(fp,ke_z)) )
1112 tmp(:) = lift_op(fmv,fp) * lmesh%Fscale(fp,ke) * nz(fp,ke_z) * fac
1113 lift_(fmv,fmv(p)) = tmp(:) * cptot_ov_cvtot(fmv(p),ke_z ) * pres0(fmv(p),ke_z ) / dens0(fmv(p),ke_z )
1114 lift_2(fmv,fmv2(p)) = tmp(:) * cptot_ov_cvtot(fmv2(p),ke_z2) * pres0(fmv2(p),ke_z2) / dens0(fmv2(p),ke_z2)
1119 if ( ke_z == 1 .and. f1==1 )
then
1120 pmatd(:,:) = pmatd(:,:) - lift_(:,:)
1121 else if ( (ke_z == lmesh%NeZ .and. f1==elem%Nfaces_v) )
then
1123 pmatd(:,:) = pmatd(:,:) - lift_(:,:)
1125 pmatl(:,:,ke_z) = lift_2(:,:)
1127 pmatu(:,:,ke_z) = lift_2(:,:)
1132 call get_pmatd_lu( pmatdlu(:,:,ke_z), pmatd(:,:), pmatdlu_ipiv(:,ke_z), elem%Np )
1142 integer,
intent(in) :: N
1143 real(RP),
intent(out) :: pmatDlu_(N,N)
1144 real(RP),
intent(in) :: pmatD_(N,N)
1145 integer,
intent(out) :: pmatDlu_ipiv_(N)
1149 pmatdlu_(:,:) = pmatd_(:,:)
1155 subroutine get_pmatd_inv( pmatDinv_, pmatD_, pmatDlu_ipiv_, N)
1158 integer,
intent(in) :: N
1159 real(RP),
intent(out) :: pmatDinv_(N,N)
1160 real(RP),
intent(in) :: pmatD_(N,N)
1161 integer,
intent(out) :: pmatDlu_ipiv_(N)
1166 end subroutine get_pmatd_inv
1167 end subroutine construct_pmatinv
1169end module scale_atm_dyn_dgm_hydrostatic
module FElib / Fluid dyn solver / Atmosphere / Common
subroutine, public hydrostatic_calc_basicstate_constptlaps(dens_hyd, pres_hyd, ptlaps, pottemp0, pres_sfc, x, y, z, lcmesh3d, elem)
Calculate density and pressure in hydrostatic balance with a constant lapse rate of potential tempera...
subroutine, public hydrostatic_calc_basicstate_consttlaps(dens_hyd, pres_hyd, tlaps, temp0, pres_sfc, x, y, z, lcmesh3d, elem)
Calculate density and pressure in hydrostatic balance with a constant lapse rate of temperature.
subroutine, public hydrostatic_calc_basicstate_constbvfreq(dens_hyd, pres_hyd, bruntvaisalafreq, pottemp0, pres_sfc, x, y, z, lcmesh3d, elem)
Calculate density and pressure in hydrostatic balance with a constant Brunt–Väisälä frequency.
subroutine, public hydrostatic_calc_basicstate_constt(dens_hyd, pres_hyd, temp0, pres_sfc, x, y, z, lcmesh3d, elem)
Calculate density and pressure in hydrostatic balance with a constant temperature.
subroutine, public hydrostatic_calc_basicstate_constpt(dens_hyd, pres_hyd, pottemp0, pres_sfc, x, y, z, lcmesh3d, elem)
Calculate density and pressure in hydrostatic balance with a constant potential temperature.
module FElib / Element / Base
module FElib / Element / hexahedron
module FElib / Element / Operation with arbitary elements
module common / Linear algebra
real(rp) function, dimension(size(a, 1), size(a, 2)), public linalgebra_inv(a)
subroutine, public linalgebra_lu(a_lu, ipiv)
module FElib / Mesh / Local 3D
module FElib / Mesh / Local, Base
module common / sparsemat
subroutine get_pmatd_lu(pmatdlu_, pmatd_, pmatdlu_ipiv_, n)