10#include "scaleFElib.h"
21 use scale_const,
only: &
25 cpdry => const_cpdry, &
26 cvdry => const_cvdry, &
55 module procedure hydrostatic_build_rho_xyz_dry
56 module procedure hydrostatic_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
110 do ke=lcmesh3d%NeS, lcmesh3d%NeE
113 pres_hyd(p,ke) = pres_sfc * exp( - z(p,ke) / h0 )
114 dens_hyd(p,ke) = pres_hyd(p,ke) / ( rdry * temp0 )
134 DENS_hyd, PRES_hyd, &
135 PotTemp0, PRES_sfc, x, y, z, lcmesh3D, elem )
141 real(rp),
intent(out) :: dens_hyd(elem%np,lcmesh3d%nea)
142 real(rp),
intent(out) :: pres_hyd(elem%np,lcmesh3d%nea)
143 real(rp),
intent(in) :: x(elem%np,lcmesh3d%ne)
144 real(rp),
intent(in) :: y(elem%np,lcmesh3d%ne)
145 real(rp),
intent(in) :: z(elem%np,lcmesh3d%ne)
146 real(rp),
intent(in) :: pottemp0
147 real(rp),
intent(in) :: pres_sfc
152 real(rp) :: exner_sfc
159 exner_sfc = (pres_sfc / pres00)**rovcp
163 do ke=lcmesh3d%NeS, lcmesh3d%NeE
167 exner = exner_sfc - grav / (cpdry * pottemp0) * z(p,ke)
168 pres_hyd(p,ke) = pres00 * exner**cpovr
169 dens_hyd(p,ke) = pres_hyd(p,ke) / ( rdry * exner * pottemp0 )
190 DENS_hyd, PRES_hyd, &
191 BruntVaisalaFreq, PotTemp0, PRES_sfc, x, y, z, lcmesh3D, elem )
197 real(rp),
intent(out) :: dens_hyd(elem%np,lcmesh3d%nea)
198 real(rp),
intent(out) :: pres_hyd(elem%np,lcmesh3d%nea)
199 real(rp),
intent(in) :: x(elem%np,lcmesh3d%ne)
200 real(rp),
intent(in) :: y(elem%np,lcmesh3d%ne)
201 real(rp),
intent(in) :: z(elem%np,lcmesh3d%ne)
202 real(rp),
intent(in) :: bruntvaisalafreq
203 real(rp),
intent(in) :: pottemp0
204 real(rp),
intent(in) :: pres_sfc
210 real(rp) :: exner_sfc
217 exner_sfc = (pres_sfc / pres00)**rovcp
221 do ke=lcmesh3d%NeS, lcmesh3d%NeE
225 pt = pottemp0 * exp( bruntvaisalafreq**2 / grav * z(p,ke) )
226 exner = exner_sfc + grav**2 / ( cpdry * bruntvaisalafreq**2 ) * ( 1.0_rp / pt - 1.0_rp / pottemp0 )
228 pres_hyd(p,ke) = pres00 * exner**cpovr
229 dens_hyd(p,ke) = pres_hyd(p,ke) / ( rdry * exner * pt )
250 DENS_hyd, PRES_hyd, &
251 TLAPS, Temp0, PRES_sfc, x, y, z, lcmesh3D, elem )
257 real(rp),
intent(out) :: dens_hyd(elem%np,lcmesh3d%nea)
258 real(rp),
intent(out) :: pres_hyd(elem%np,lcmesh3d%nea)
259 real(rp),
intent(in) :: x(elem%np,lcmesh3d%ne)
260 real(rp),
intent(in) :: y(elem%np,lcmesh3d%ne)
261 real(rp),
intent(in) :: z(elem%np,lcmesh3d%ne)
262 real(rp),
intent(in) :: tlaps
263 real(rp),
intent(in) :: temp0
264 real(rp),
intent(in) :: pres_sfc
272 fac = grav / ( rdry * tlaps )
276 do ke=lcmesh3d%NeS, lcmesh3d%NeE
278 temp = temp0 * ( 1.0_rp - tlaps / temp0 * z(p,ke) )
279 pres_hyd(p,ke) = pres_sfc * ( temp / temp0 )**fac
280 dens_hyd(p,ke) = pres_hyd(p,ke) / ( rdry * temp )
301 DENS_hyd, PRES_hyd, &
302 PTLAPS, PotTemp0, PRES_sfc, x, y, z, lcmesh3D, elem )
308 real(rp),
intent(out) :: dens_hyd(elem%np,lcmesh3d%nea)
309 real(rp),
intent(out) :: pres_hyd(elem%np,lcmesh3d%nea)
310 real(rp),
intent(in) :: x(elem%np,lcmesh3d%ne)
311 real(rp),
intent(in) :: y(elem%np,lcmesh3d%ne)
312 real(rp),
intent(in) :: z(elem%np,lcmesh3d%ne)
313 real(rp),
intent(in) :: ptlaps
314 real(rp),
intent(in) :: pottemp0
315 real(rp),
intent(in) :: pres_sfc
321 real(rp) :: exner_sfc
328 exner_sfc = (pres_sfc / pres00)**rovcp
330 if ( ptlaps == 0.0_rp )
then
332 dens_hyd, pres_hyd, &
333 pottemp0, pres_sfc, x, y, z, lcmesh3d, elem )
337 do ke=lcmesh3d%NeS, lcmesh3d%NeE
341 pt = pottemp0 + ptlaps * z(p,ke)
342 exner = exner_sfc - grav / ( cpdry * ptlaps ) * log( 1.0_rp + ptlaps / pottemp0 * z(p,ke) )
344 pres_hyd(p,ke) = pres00 * exner**cpovr
345 dens_hyd(p,ke) = pres_hyd(p,ke) / ( rdry * exner * pt )
366 subroutine hydrostatic_build_rho_xyz_dry( &
368 DENS_hyd, PRES_hyd, &
370 x, y, z, lcmesh, elem, &
377 real(RP),
intent(out) :: DDENS(elem%Np,lcmesh%NeA)
378 real(RP),
intent(in) :: DENS_hyd(elem%Np,lcmesh%NeA)
379 real(RP),
intent(in) :: PRES_hyd(elem%Np,lcmesh%NeA)
380 real(RP),
intent(in) :: x(elem%Np,lcmesh%Ne)
381 real(RP),
intent(in) :: y(elem%Np,lcmesh%Ne)
382 real(RP),
intent(in) :: z(elem%Np,lcmesh%Ne)
383 real(RP),
intent(in) :: POT(elem%Np,lcmesh%NeZ,lcmesh%NeX,lcmesh%NeY)
384 real(RP),
intent(in),
optional :: bnd_SFC_PRES(lcmesh%lcmesh2D%refElem2D%Np,lcmesh%Ne2DA)
386 real(RP) :: Rtot (elem%Np,lcmesh%NeZ,lcmesh%NeX,lcmesh%NeY)
387 real(RP) :: CPtot_ov_CVtot(elem%Np,lcmesh%NeZ,lcmesh%NeX,lcmesh%NeY)
394 cptot_ov_cvtot(:,:,:,:) = cpdry / cvdry
398 call hydrostatic_build_rho_xyz_moist( &
400 dens_hyd, pres_hyd, &
401 pot, rtot, cptot_ov_cvtot, &
402 x, y, z, lcmesh, elem, &
406 end subroutine hydrostatic_build_rho_xyz_dry
423 subroutine hydrostatic_build_rho_xyz_moist( &
425 DENS_hyd, PRES_hyd, &
426 POT, Rtot, CPtot_ov_CVtot, &
427 x, y, z, lcmesh, elem, &
430 use scale_const,
only: &
438 real(RP),
intent(out) :: DDENS(elem%Np,lcmesh%NeA)
439 real(RP),
intent(in) :: DENS_hyd(elem%Np,lcmesh%NeA)
440 real(RP),
intent(in) :: PRES_hyd(elem%Np,lcmesh%NeA)
441 real(RP),
intent(in) :: x(elem%Np,lcmesh%Ne)
442 real(RP),
intent(in) :: y(elem%Np,lcmesh%Ne)
443 real(RP),
intent(in) :: z(elem%Np,lcmesh%Ne)
444 real(RP),
intent(in) :: POT(elem%Np,lcmesh%NeZ,lcmesh%NeX,lcmesh%NeY)
445 real(RP),
intent(in) :: Rtot(elem%Np,lcmesh%NeZ,lcmesh%NeX,lcmesh%NeY)
446 real(RP),
intent(in) :: CPtot_ov_CVtot(elem%Np,lcmesh%NeZ,lcmesh%NeX,lcmesh%NeY)
447 real(RP),
intent(in),
optional :: bnd_SFC_PRES(lcmesh%lcmesh2D%refElem2D%Np,lcmesh%Ne2DA)
450 integer :: ke_x, ke_y, ke_z
454 real(RP),
parameter :: EPS = 1.0e-12_rp
458 type(
gmres) :: gmres_hydro
459 real(RP),
allocatable :: wj(:)
460 real(RP),
allocatable :: pinv_v(:)
462 integer :: vmapM_z1D(elem%NfpTot,lcmesh%NeZ)
463 integer :: vmapP_z1D(elem%NfpTot,lcmesh%NeZ)
464 real(RP) :: VARS (elem%Np,lcmesh%NeZ)
465 real(RP) :: VARS0 (elem%Np,lcmesh%NeZ)
466 real(RP) :: VAR_DEL(elem%Np,lcmesh%NeZ)
467 real(RP) :: b(elem%Np,lcmesh%NeZ)
468 real(RP) :: Ax(elem%Np,lcmesh%NeZ)
469 real(RP) :: nz(elem%NfpTot,lcmesh%NeZ)
470 real(RP) :: DENS_hyd_z(elem%Np,lcmesh%NeZ)
471 real(RP) :: PRES_hyd_z(elem%Np,lcmesh%NeZ)
472 real(RP) :: PmatDlu(elem%Np,elem%Np,lcmesh%NeZ)
473 integer :: PmatDlu_ipiv(elem%Np,lcmesh%NeZ)
474 real(RP) :: PmatL(elem%Np,elem%Np,lcmesh%NeZ)
475 real(RP) :: PmatU(elem%Np,elem%Np,lcmesh%NeZ)
476 real(RP) :: GsqrtV_z(elem%Np,lcmesh%NeZ)
478 logical :: is_converged
480 real(RP) :: IntrpMat_VPOrdM1(elem%Np,elem%Np)
482 real(RP) :: bnd_SFC_PRES_tmp(lcmesh%lcmesh2D%refElem2D%Np,lcmesh%Ne2DA)
486 if (
present(bnd_sfc_pres) )
then
488 do ke2d=lcmesh%lcmesh2D%NeS, lcmesh%lcmesh2D%NeE
489 bnd_sfc_pres_tmp(:,ke2d) = bnd_sfc_pres(:,ke2d)
493 do ke2d=lcmesh%lcmesh2D%NeS, lcmesh%lcmesh2D%NeE
494 bnd_sfc_pres_tmp(:,ke2d) = pres_hyd(elem%Hslice(:,1),ke2d)
500 n = elem%Np * lcmesh%NeZ
501 m = min(n / elem%Nnode_h1D**2, 30)
504 call gmres_hydro%Init( n, m, eps, eps0 )
505 allocate( wj(n), pinv_v(n) )
507 call dz%Init( elem%Dx3, storage_format=
'ELL' )
508 call lift%Init( elem%Lift, storage_format=
'ELL' )
510 call lcmesh%GetVmapZ1D( vmapm_z1d, vmapp_z1d )
516 do ke_y=1, lcmesh%NeY
517 do ke_x=1, lcmesh%NeX
518 ke2d = ke_x + (ke_y-1)*lcmesh%NeX
519 do ke_z=1, lcmesh%NeZ
520 ke = ke2d + (ke_z-1)*lcmesh%NeX*lcmesh%NeY
521 vars(:,ke_z) = 0.0_rp
523 vars0(:,ke_z) = vars(:,ke_z)
524 nz(:,ke_z) = lcmesh%normal_fn(:,ke,3)
526 dens_hyd_z(:,ke_z) = dens_hyd(:,ke)
527 pres_hyd_z(:,ke_z) = pres_hyd(:,ke)
528 gsqrtv_z(:,ke_z) = lcmesh%Gsqrt(:,ke) / lcmesh%GsqrtH(elem%IndexH2Dto3D(:),ke2d)
533 do ke_z=1, lcmesh%NeZ
534 var_del(:,ke_z) = 0.0_rp
537 call eval_ax( ax(:,:), &
538 vars, vars0, pot(:,:,ke_x,ke_y), rtot(:,:,ke_x,ke_y), &
539 cptot_ov_cvtot(:,:,ke_x,ke_y), dens_hyd_z, pres_hyd_z, &
540 bnd_sfc_pres_tmp(:,ke2d), &
541 dz, lift, intrpmat_vpordm1, lcmesh, elem, &
542 nz, vmapm_z1d, vmapp_z1d, ke_x, ke_y )
544 do ke_z=1, lcmesh%NeZ
545 b(:,ke_z) = - ax(:,ke_z)
547 if (lcmesh%tileID==1)
then
548 if (itr_nlin > 1)
then
549 log_progress(*) ke_x, ke_y,
"itr_lin=", itr_lin
550 log_progress(*)
"-------------------------------------"
552 log_progress(*) ke_x, ke_y,
"itr_nlin:", itr_nlin, 0,
": VAR", vars(elem%Colmask(:,1),1)
553 log_progress(*) ke_x, ke_y,
"itr_nlin:", itr_nlin, 0,
": b", b(elem%Colmask(:,1),1)
554 if( io_l )
call flush(io_fid_log)
557 if ( maxval(abs(b(:,:))) < 1.0e-10_rp )
exit
559 call construct_pmatinv( pmatdlu, pmatdlu_ipiv, pmatl, pmatu, &
560 vars0, pot(:,:,ke_x,ke_y), rtot(:,:,ke_x,ke_y), &
561 cptot_ov_cvtot(:,:,ke_x,ke_y), dens_hyd_z, pres_hyd_z, &
562 dz, lift, intrpmat_vpordm1, gsqrtv_z, lcmesh, elem, &
563 nz, vmapm_z1d, vmapp_z1d, ke_x, ke_y )
565 do itr_lin=1, 2*int(n/m)
567 call gmres_hydro_core( gmres_hydro, var_del, wj, is_converged, &
569 pmatdlu, pmatdlu_ipiv, pmatl, pmatu, pinv_v, &
570 pot(:,:,ke_x,ke_y), rtot(:,:,ke_x,ke_y), &
571 cptot_ov_cvtot(:,:,ke_x,ke_y), dens_hyd_z, pres_hyd_z, &
572 dz, lift, intrpmat_vpordm1, lcmesh, elem, &
573 nz, vmapm_z1d, vmapp_z1d, ke_x, ke_y )
577 if (is_converged)
exit
579 do ke_z=1, lcmesh%NeZ
580 vars(:,ke_z) = vars(:,ke_z) + var_del(:,ke_z)
581 vars0(:,ke_z) = vars(:,ke_z)
585 do ke_z=1, lcmesh%NeZ
586 ke = ke_x + (ke_y-1)*lcmesh%NeX + (ke_z-1)*lcmesh%NeX*lcmesh%NeY
587 ddens(:,ke) = vars(:,ke_z)
593 call gmres_hydro%Final()
598 end subroutine hydrostatic_build_rho_xyz_moist
603 subroutine gmres_hydro_core( gmres_hydro, x, wj, is_converged, &
605 PmatDlu, PmatDlu_ipiv, PmatL, PmatU, pinv_v, & ! (in)
606 pot, rtot, cptot_ov_cvtot, dens_hyd, pres_hyd, &
607 dz, lift, intrpmat_vpordm1, lmesh, elem, &
608 nz, vmapm, vmapp, ke_x, ke_y )
614 integer,
intent(in) :: N
615 integer,
intent(in) :: m
617 class(
gmres),
intent(inout) :: gmres_hydro
618 real(RP),
intent(inout) :: x(N)
619 real(RP),
intent(inout) :: wj(N)
620 logical,
intent(out) :: is_converged
621 real(RP),
intent(in) :: x0(N)
622 real(RP),
intent(in) :: b(N)
623 real(RP),
intent(in) :: PmatDlu(elem%Np,elem%Np,lmesh%NeZ)
624 integer,
intent(in) :: PmatDlu_ipiv(elem%Np,lmesh%NeZ)
625 real(RP),
intent(in) :: PmatL(elem%Np,elem%Np,lmesh%NeZ)
626 real(RP),
intent(in) :: PmatU(elem%Np,elem%Np,lmesh%NeZ)
627 real(RP),
intent(inout) :: pinv_v(N)
629 real(RP),
intent(in) :: POT(elem%Np,lmesh%NeZ)
630 real(RP),
intent(in) :: Rtot(elem%Np,lmesh%NeZ)
631 real(RP),
intent(in) :: CPtot_ov_CVtot(elem%Np,lmesh%NeZ)
632 real(RP),
intent(in) :: DENS_hyd(elem%Np,lmesh%NeZ)
633 real(RP),
intent(in) :: PRES_hyd(elem%Np,lmesh%NeZ)
635 real(RP),
intent(in) :: IntrpMat_VPOrdM1(elem%Np,elem%Np)
636 real(RP),
intent(in) :: nz(elem%NfpTot,lmesh%NeZ)
637 integer,
intent(in) :: vmapM(elem%NfpTot,lmesh%NeZ)
638 integer,
intent(in) :: vmapP(elem%NfpTot,lmesh%NeZ)
639 integer,
intent(in) :: ke_x, ke_y
644 call eval_ax_lin( wj(:), &
645 x, x0, pot, rtot, cptot_ov_cvtot, &
646 dens_hyd, pres_hyd, &
647 dz, lift, intrpmat_vpordm1, lmesh, elem, &
648 nz, vmapm, vmapp, ke_x, ke_y )
650 call gmres_hydro%Iterate_pre( b, wj, is_converged )
651 if (is_converged)
return
654 call matmul_pinv_v( pinv_v, pmatdlu, pmatdlu_ipiv, pmatl, pmatu, gmres_hydro%v(:,j) )
656 call eval_ax_lin( wj(:), &
657 pinv_v, x0, pot, rtot, cptot_ov_cvtot, &
658 dens_hyd, pres_hyd, &
659 dz, lift, intrpmat_vpordm1, lmesh, elem, &
660 nz, vmapm, vmapp, ke_x, ke_y )
662 call gmres_hydro%Iterate_step_j( j, wj, is_converged )
664 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)
665 if ( is_converged )
exit
671 call gmres_hydro%Iterate_post( wj )
672 call matmul_pinv_v_plus_x0( x, pmatdlu, pmatdlu_ipiv, pmatl, pmatu, wj)
678 subroutine matmul_pinv_v( pinv_v_, pDlu_, PmatDlu_ipiv_, pL, pU, v)
680 real(RP),
intent(out) :: pinv_v_(elem%Np,lmesh%NeZ)
681 real(RP),
intent(in) :: pDlu_(elem%Np,elem%Np,lmesh%NeZ)
682 integer,
intent(in) :: PmatDlu_ipiv_(elem%Np,lmesh%NeZ)
683 real(RP),
intent(in) :: pL(elem%Np,elem%Np,lmesh%NeZ)
684 real(RP),
intent(in) :: pU(elem%Np,elem%Np,lmesh%NeZ)
685 real(RP),
intent(in) :: v(elem%Np,lmesh%NeZ)
688 real(RP) :: tmp(elem%Np)
696 ve = vs + elem%Np - 1
697 pinv_v_(:,1) = v(vs:ve,1)
698 call dgetrs(
'N', n, 1, pdlu_(:,:,1), n, pmatdlu_ipiv_(:,1), pinv_v_(:,1), n, info)
702 pinv_v_(:,k) = v(vs:ve,k) &
703 - matmul( pl(:,:,k), pinv_v_(:,k-1) )
705 call dgetrs(
'N', n, 1, pdlu_(:,:,k), n, pmatdlu_ipiv_(:,k), pinv_v_(:,k), n, info)
709 do k=lmesh%NeZ-1, 1, -1
711 tmp(vs:ve) = matmul( pu(:,:,k), pinv_v_(:,k+1) )
712 call dgetrs(
'N', n, 1, pdlu_(:,:,k), n, pmatdlu_ipiv_(:,k), tmp(:), n, info)
715 ve = vs + elem%Np - 1
716 pinv_v_(:,k) = pinv_v_(:,k) - tmp(vs:ve)
720 end subroutine matmul_pinv_v
723 subroutine matmul_pinv_v_plus_x0( x_, pDlu_, PmatDlu_ipiv_, pL, pU, v)
725 real(RP),
intent(inout) :: x_(elem%Np,lmesh%NeZ)
726 real(RP),
intent(in) :: pDlu_(elem%Np,elem%Np,lmesh%NeZ)
727 integer,
intent(in) :: PmatDlu_ipiv_(elem%Np,lmesh%NeZ)
728 real(RP),
intent(in) :: pL(elem%Np,elem%Np,lmesh%NeZ)
729 real(RP),
intent(in) :: pU(elem%Np,elem%Np,lmesh%NeZ)
730 real(RP),
intent(in) :: v(elem%Np,lmesh%NeZ)
733 real(RP) :: tmp(elem%Np,lmesh%NeZ)
737 call matmul_pinv_v( tmp, pdlu_, pmatdlu_ipiv_, pl, pu, v)
740 x_(:,k) = x_(:,k) + tmp(:,k)
744 end subroutine matmul_pinv_v_plus_x0
746 end subroutine gmres_hydro_core
749 subroutine eval_ax( Ax, &
750 DDENS, DENS0, POT, Rtot, CPtot_ov_CVtot, & ! (in)
751 dens_hyd, pres_hyd, bnd_sfc_pres, &
752 dz, lift, intrpmat_vpordm1, lmesh, elem, &
753 nz, vmapm, vmapp, ke_x, ke_y )
759 real(RP),
intent(out) :: Ax(elem%Np,lmesh%NeZ)
760 real(RP),
intent(in) :: DDENS (elem%Np,lmesh%NeZ)
761 real(RP),
intent(in) :: DENS0(elem%Np,lmesh%NeZ)
762 real(RP),
intent(in) :: POT(elem%Np,lmesh%NeZ)
763 real(RP),
intent(in) :: Rtot(elem%Np,lmesh%NeZ)
764 real(RP),
intent(in) :: CPtot_ov_CVtot(elem%Np,lmesh%NeZ)
765 real(RP),
intent(in) :: DENS_hyd(elem%Np,lmesh%NeZ)
766 real(RP),
intent(in) :: PRES_hyd(elem%Np,lmesh%NeZ)
767 real(RP),
intent(in) :: bnd_SFC_PRES(lmesh%lcmesh2D%refElem2D%Np)
769 real(RP),
intent(in) :: IntrpMat_VPOrdM1(elem%Np,elem%Np)
771 real(RP),
intent(in) :: nz(elem%NfpTot,lmesh%NeZ)
772 integer,
intent(in) :: vmapM(elem%NfpTot,lmesh%NeZ)
773 integer,
intent(in) :: vmapP(elem%NfpTot,lmesh%NeZ)
774 integer,
intent(in) :: ke_x, ke_y
776 real(RP) :: DPRES(elem%Np), DENS(elem%Np)
777 real(RP) :: Fz(elem%Np), LiftDelFlx(elem%Np)
778 real(RP) :: del_flux(elem%NfpTot,lmesh%NeZ)
787 real(RP) :: GsqrtV(elem%Np)
791 rdovp00 = rdry / pres00
792 rp0 = 1.0_rp / pres00
794 call cal_del_flux( del_flux, &
795 ddens, pot, rtot, cptot_ov_cvtot, &
796 dens_hyd, pres_hyd, bnd_sfc_pres, &
797 nz, vmapm, vmapp, lmesh, elem )
801 ke = ke_x + (ke_y-1)*lmesh%NeX + (ke_z-1)*lmesh%NeX*lmesh%NeY
802 ke2d = lmesh%EMap3Dto2D(ke)
804 gsqrtv(:) = lmesh%Gsqrt(:,ke) / lmesh%GsqrtH(elem%IndexH2Dto3D,ke2d)
806 dens(:) = dens_hyd(:,ke_z) + ddens(:,ke_z)
807 dpres(:) = pres00 * ( rtot(:,ke_z) * rp0 * dens(:) * pot(:,ke_z) )**cptot_ov_cvtot(:,ke_z)
810 call sparsemat_matmul(lift, lmesh%Fscale(:,ke)*del_flux(:,ke_z), liftdelflx)
814 ax(:,ke_z) = ( lmesh%Escale(:,ke,3,3) * fz(:) + liftdelflx(:) ) / gsqrtv(:) &
815 + grav * matmul(intrpmat_vpordm1, dens(:))
819 end subroutine eval_ax
822 subroutine cal_del_flux( del_flux, &
823 DDENS_, POT_, Rtot_, CPtot_ov_CVtot_, &
824 DENS_hyd, PRES_hyd, bnd_SFC_PRES, &
825 nz, vmapM, vmapP, lmesh, elem )
831 real(RP),
intent(out) :: del_flux(elem%NfpTot*lmesh%NeZ)
832 real(RP),
intent(in) :: DDENS_(elem%Np*lmesh%NeZ)
833 real(RP),
intent(in) :: POT_(elem%Np*lmesh%NeZ)
834 real(RP),
intent(in) :: Rtot_(elem%Np*lmesh%NeZ)
835 real(RP),
intent(in) :: CPtot_ov_CVtot_(elem%Np*lmesh%NeZ)
836 real(RP),
intent(in) :: DENS_hyd(elem%Np*lmesh%NeZ)
837 real(RP),
intent(in) :: PRES_hyd(elem%Np*lmesh%NeZ)
838 real(RP),
intent(in) :: bnd_SFC_PRES(lmesh%lcmesh2D%refElem2D%Np)
839 real(RP),
intent(in) :: nz(elem%NfpTot*lmesh%NeZ)
840 integer,
intent(in) :: vmapM(elem%NfpTot*lmesh%NeZ)
841 integer,
intent(in) :: vmapP(elem%NfpTot*lmesh%NeZ)
844 integer :: p, p2D, f, ke_z
846 real(RP) :: dpresP, dpresM
847 real(RP) :: RtotOvP00M, RtotOvP00P
853 rp0 = 1.0_rp / pres00
859 do i=1, elem%NfpTot*lmesh%NeZ
865 do f=1, elem%Nfaces_v
867 p = p2d + (f-1)*elem%Nfp_v + elem%Nfaces_h * elem%Nfp_h
868 i = p + (ke_z-1)*elem%NfpTot
869 im = vmapm(i); ip = vmapp(i)
871 rtotovp00m = rtot_(im) * rp0
872 rtotovp00p = rtot_(ip) * rp0
874 fac = 0.5_rp * ( 1.0_rp - sign(1.0_rp,nz(i)) )
875 dpresm = pres00 * ( rtotovp00m * (dens_hyd(im) + ddens_(im)) * pot_(im) )**cptot_ov_cvtot_(im)
876 dpresp = pres00 * ( rtotovp00p * (dens_hyd(ip) + ddens_(ip)) * pot_(ip) )**cptot_ov_cvtot_(ip)
878 if ( ke_z==1 .and. im==ip ) dpresp = bnd_sfc_pres(p2d)
880 del_flux(i) = fac * ( dpresp - dpresm ) * nz(i)
888 end subroutine cal_del_flux
891 subroutine eval_ax_lin( Ax, &
892 DDENS, DDENS0, POT, Rtot, CPtot_ov_CVtot, & ! (in)
893 dens_hyd, pres_hyd, &
894 dz, lift, intrpmat_vpordm1, lmesh, elem, &
895 nz, vmapm, vmapp, ke_x, ke_y )
901 real(RP),
intent(out) :: Ax(elem%Np,lmesh%NeZ)
902 real(RP),
intent(in) :: DDENS (elem%Np,lmesh%NeZ)
903 real(RP),
intent(in) :: DDENS0(elem%Np,lmesh%NeZ)
904 real(RP),
intent(in) :: POT(elem%Np,lmesh%NeZ)
905 real(RP),
intent(in) :: Rtot(elem%Np,lmesh%NeZ)
906 real(RP),
intent(in) :: CPtot_ov_CVtot(elem%Np,lmesh%NeZ)
907 real(RP),
intent(in) :: DENS_hyd(elem%Np,lmesh%NeZ)
908 real(RP),
intent(in) :: PRES_hyd(elem%Np,lmesh%NeZ)
910 real(RP),
intent(in) :: IntrpMat_VPOrdM1(elem%Np,elem%Np)
911 real(RP),
intent(in) :: nz(elem%NfpTot,lmesh%NeZ)
912 integer,
intent(in) :: vmapM(elem%NfpTot,lmesh%NeZ)
913 integer,
intent(in) :: vmapP(elem%NfpTot,lmesh%NeZ)
914 integer,
intent(in) :: ke_x, ke_y
916 real(RP) :: PRES(elem%Np), PRES0(elem%Np)
917 real(RP) :: DPRES(elem%Np)
918 real(RP) :: Fz(elem%Np), LiftDelFlx(elem%Np)
919 real(RP) :: del_flux(elem%NfpTot,lmesh%NeZ)
927 real(RP) :: GsqrtV(elem%Np)
931 rp0 = 1.0_rp / pres00
933 call cal_del_flux_lin( del_flux, &
934 ddens, ddens0, pot, rtot, cptot_ov_cvtot, &
935 dens_hyd, pres_hyd, &
936 nz, vmapm, vmapp, lmesh, elem )
940 ke = ke_x + (ke_y-1)*lmesh%NeX + (ke_z-1)*lmesh%NeX*lmesh%NeY
941 ke2d = lmesh%EMap3Dto2D(ke)
943 gsqrtv(:) = lmesh%Gsqrt(:,ke) / lmesh%GsqrtH(elem%IndexH2Dto3D,ke2d)
945 pres0(:) = pres00 * ( rtot(:,ke_z) * rp0 * (dens_hyd(:,ke_z) + ddens0(:,ke_z)) * pot(:,ke_z) )**cptot_ov_cvtot(:,ke_z)
946 dpres(:) = cptot_ov_cvtot(:,ke_z) * pres0(:) / (dens_hyd(:,ke_z) + ddens0(:,ke_z)) * ddens(:,ke_z)
949 call sparsemat_matmul(lift, lmesh%Fscale(:,ke)*del_flux(:,ke_z), liftdelflx)
951 ax(:,ke_z) = ( lmesh%Escale(:,ke,3,3) * fz(:) + liftdelflx(:) ) / gsqrtv(:) &
952 + grav * matmul(intrpmat_vpordm1, ddens(:,ke_z))
956 end subroutine eval_ax_lin
959 subroutine cal_del_flux_lin( del_flux, &
960 DDENS_, DDENS0_, POT_, Rtot_, CPtot_ov_CVtot_, &
961 DENS_hyd_, PRES_hyd_, &
962 nz, vmapM, vmapP, lmesh, elem )
968 real(RP),
intent(out) :: del_flux(elem%NfpTot*lmesh%NeZ)
969 real(RP),
intent(in) :: DDENS_(elem%Np*lmesh%NeZ)
970 real(RP),
intent(in) :: DDENS0_(elem%Np*lmesh%NeZ)
971 real(RP),
intent(in) :: Rtot_(elem%Np*lmesh%NeZ)
972 real(RP),
intent(in) :: CPtot_ov_CVtot_(elem%Np*lmesh%NeZ)
973 real(RP),
intent(in) :: DENS_hyd_(elem%Np*lmesh%NeZ)
974 real(RP),
intent(in) :: PRES_hyd_(elem%Np*lmesh%NeZ)
975 real(RP),
intent(in) :: POT_(elem%Np*lmesh%NeZ)
976 real(RP),
intent(in) :: nz(elem%NfpTot*lmesh%NeZ)
977 integer,
intent(in) :: vmapM(elem%NfpTot*lmesh%NeZ)
978 integer,
intent(in) :: vmapP(elem%NfpTot*lmesh%NeZ)
981 integer :: p, p2D, f, ke_z
983 real(RP) :: dpresP, dpresM
984 real(RP) :: pres0P, pres0M
987 real(RP) :: RtotOvP00M
988 real(RP) :: RtotOvP00P
994 rp0 = 1.0_rp / pres00
1000 do i=1, elem%NfpTot*lmesh%NeZ
1001 del_flux(i) = 0.0_rp
1005 do ke_z=1, lmesh%NeZ
1006 do f=1, elem%Nfaces_v
1007 do p2d=1, elem%Nfp_v
1008 p = p2d + (f-1)*elem%Nfp_v + elem%Nfaces_h * elem%Nfp_h
1009 i = p + (ke_z-1)*elem%NfpTot
1011 im = vmapm(i); ip = vmapp(i)
1013 rtotovp00m = rtot_(im) * rp0
1014 rtotovp00p = rtot_(ip) * rp0
1016 pres0m = pres00 * ( rtotovp00m * (dens_hyd_(im) + ddens0_(im)) * pot_(im) )**cptot_ov_cvtot_(im)
1017 pres0p = pres00 * ( rtotovp00p * (dens_hyd_(ip) + ddens0_(ip)) * pot_(ip) )**cptot_ov_cvtot_(ip)
1019 fac = 0.5_rp * ( 1.0_rp - sign(1.0_rp,nz(i)) )
1020 dpresm = cptot_ov_cvtot_(im) * pres0m / (dens_hyd_(im) + ddens0_(im)) * ddens_(im)
1021 dpresp = cptot_ov_cvtot_(ip) * pres0p / (dens_hyd_(ip) + ddens0_(ip)) * ddens_(ip)
1023 if ( ke_z == 1 .and. im == ip ) dpresp = 0.0_rp
1025 del_flux(i) = fac * ( dpresp - dpresm ) * nz(i)
1033 end subroutine cal_del_flux_lin
1036 subroutine construct_pmatinv( PmatDlu, PmatDlu_ipiv, PmatL, PmatU, & ! (out)
1037 ddens0, pot, rtot, cptot_ov_cvtot, dens_hyd, pres_hyd, &
1038 dz, lift, intrpmat_vpordm1, gsqrtv, lmesh, elem, &
1039 nz, vmapm, vmapp, ke_x, ke_y )
1046 real(RP),
intent(out) :: PmatDlu(elem%Np,elem%Np,lmesh%NeZ)
1047 integer,
intent(out) :: PmatDlu_ipiv(elem%Np,lmesh%NeZ)
1048 real(RP),
intent(out) :: PmatL(elem%Np,elem%Np,lmesh%NeZ)
1049 real(RP),
intent(out) :: PmatU(elem%Np,elem%Np,lmesh%NeZ)
1050 real(RP),
intent(in) :: DDENS0(elem%Np,lmesh%NeZ)
1051 real(RP),
intent(in) :: POT(elem%Np,lmesh%NeZ)
1052 real(RP),
intent(in) :: Rtot(elem%Np,lmesh%NeZ)
1053 real(RP),
intent(in) :: CPtot_ov_CVtot(elem%Np,lmesh%NeZ)
1054 real(RP),
intent(in) :: DENS_hyd(elem%Np,lmesh%NeZ)
1055 real(RP),
intent(in) :: PRES_hyd(elem%Np,lmesh%NeZ)
1056 class(
sparsemat),
intent(in) :: Dz, Lift
1057 real(RP),
intent(in) :: IntrpMat_VPOrdM1(elem%Np,elem%Np)
1058 real(RP),
intent(in) :: GsqrtV(elem%Np,lmesh%NeZ)
1059 real(RP),
intent(in) :: nz(elem%NfpTot,lmesh%NeZ)
1060 integer,
intent(in) :: vmapM(elem%NfpTot,lmesh%NeZ)
1061 integer,
intent(in) :: vmapP(elem%NfpTot,lmesh%NeZ)
1062 integer,
intent(in) :: ke_x, ke_y
1064 real(RP) :: DENS0(elem%Np,lmesh%NeZ)
1065 real(RP) :: PRES0(elem%Np,lmesh%NeZ)
1066 integer :: ke_z, ke_z2
1067 integer :: ke, p, fp, v
1068 real(RP) :: gamm, rgamm, rP0
1069 real(RP) :: dz_p(elem%Np)
1070 real(RP) :: PmatD(elem%Np,elem%Np)
1072 integer :: f1, f2, fp_s, fp_e
1073 integer :: FmV(elem%Nfp_v)
1074 integer :: FmV2 (elem%Nfp_v)
1075 real(RP) :: lift_op(elem%Np,elem%NfpTot)
1076 real(RP) :: lift_(elem%Np,elem%Np)
1077 real(RP) :: lift_2(elem%Np,elem%Np)
1078 real(RP) :: tmp(elem%Nfp_v)
1085 rp0 = 1.0_rp / pres00
1087 lift_op(:,:) = elem%Lift
1090 do ke_z=1, lmesh%NeZ
1091 dens0(:,ke_z) = dens_hyd(:,ke_z) + ddens0(:,ke_z)
1092 pres0(:,ke_z) = pres00 * ( rtot(:,ke_z) * rp0 * dens0(:,ke_z) * pot(:,ke_z) )**cptot_ov_cvtot(:,ke_z)
1098 do ke_z=1, lmesh%NeZ
1099 ke = ke_x + (ke_y-1)*lmesh%NeX + (ke_z-1)*lmesh%NeX*lmesh%NeY
1103 pmatl(:,:,ke_z) = 0.0_rp
1104 pmatu(:,:,ke_z) = 0.0_rp
1107 dz_p(:) = lmesh%Escale(p,ke,3,3) * elem%Dx3(p,:)
1108 pmatd(p,:) = dz_p(:) * cptot_ov_cvtot(:,ke_z) * pres0(:,ke_z) / ( dens0(:,ke_z) * gsqrtv(p,ke_z) ) &
1109 + grav * intrpmat_vpordm1(p,:)
1114 f2 = 2; ke_z2 = max(ke_z-1, 1)
1116 f2 = 1; ke_z2 = min(ke_z+1, lmesh%NeZ)
1118 if ( (ke_z == 1 .and. f1==1) .or. (ke_z == lmesh%NeZ .and. f1==elem%Nfaces_v) )
then
1122 fmv(:) = elem%Fmask_v(:,f1)
1123 fmv2(:) = elem%Fmask_v(:,f2)
1125 fp_s = elem%Nfp_h * elem%Nfaces_h + 1 + (f1-1)*elem%Nfp_v
1126 fp_e = fp_s + elem%Nfp_v - 1
1130 lift_2(:,:) = 0.0_rp
1134 fac = 0.5_rp * ( 1.0_rp - sign(1.0_rp,nz(fp,ke_z)) )
1135 tmp(:) = lift_op(fmv,fp) * lmesh%Fscale(fp,ke) * nz(fp,ke_z) * fac
1136 lift_(fmv,fmv(p)) = tmp(:) * cptot_ov_cvtot(fmv(p),ke_z ) * pres0(fmv(p),ke_z ) / dens0(fmv(p),ke_z )
1137 lift_2(fmv,fmv2(p)) = tmp(:) * cptot_ov_cvtot(fmv2(p),ke_z2) * pres0(fmv2(p),ke_z2) / dens0(fmv2(p),ke_z2)
1142 if ( ke_z == 1 .and. f1==1 )
then
1143 pmatd(:,:) = pmatd(:,:) - lift_(:,:)
1144 else if ( (ke_z == lmesh%NeZ .and. f1==elem%Nfaces_v) )
then
1146 pmatd(:,:) = pmatd(:,:) - lift_(:,:)
1148 pmatl(:,:,ke_z) = lift_2(:,:)
1150 pmatu(:,:,ke_z) = lift_2(:,:)
1155 call get_pmatd_lu( pmatdlu(:,:,ke_z), pmatd(:,:), pmatdlu_ipiv(:,ke_z), elem%Np )
1165 integer,
intent(in) :: N
1166 real(RP),
intent(out) :: pmatDlu_(N,N)
1167 real(RP),
intent(in) :: pmatD_(N,N)
1168 integer,
intent(out) :: pmatDlu_ipiv_(N)
1172 pmatdlu_(:,:) = pmatd_(:,:)
1178 subroutine get_pmatd_inv( pmatDinv_, pmatD_, pmatDlu_ipiv_, N)
1181 integer,
intent(in) :: N
1182 real(RP),
intent(out) :: pmatDinv_(N,N)
1183 real(RP),
intent(in) :: pmatD_(N,N)
1184 integer,
intent(out) :: pmatDlu_ipiv_(N)
1189 end subroutine get_pmatd_inv
1190 end subroutine construct_pmatinv
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)
Calculate a inversion of matrix A.
subroutine, public linalgebra_lu(a_lu, ipiv)
Perform LU factorization.
module FElib / Mesh / Local 3D
module FElib / Mesh / Local, Base
Module common / sparsemat.
subroutine get_pmatd_lu(pmatdlu_, pmatd_, pmatdlu_ipiv_, n)
Derived type representing a 3D reference element.
Derived type representing an arbitrary finite element.
Derived type representing a hexahedral element.
Derived type to provide a iterative solver for system of linear equations using GMRES.
Derived type to manage a local 3D computational domain.
Derived type to manage a local computational domain (base type)
Derived type to manage a sparse matrix.