FE-Project
Loading...
Searching...
No Matches
scale_meshutil_vcoord.F90
Go to the documentation of this file.
1!-------------------------------------------------------------------------------
2!> module FElib / Mesh / utility for general vertical coordinate
3!!
4!! @par Description
5!! A module useful for general vertical coordinate
6!!
7!! @author Yuta Kawai, Team SCALE
8!<
9#include "scaleFElib.h"
11 !-----------------------------------------------------------------------------
12 !
13 !++ used modules
14 !
15 use scale_const, only: &
16 pi => const_pi, &
17 eps => const_eps
18 use scale_precision
19 use scale_prc
20 use scale_io
21 use scale_prc
22
25 use scale_element_base, only: &
27 use scale_sparsemat, only:&
29 !-----------------------------------------------------------------------------
30 implicit none
31 private
32
33 !-----------------------------------------------------------------------------
34 !
35 !++ Public type & procedures
36 !
39
40 !-----------------------------------------------------------------------------
41 !
42 !++ Public parameters & variables
43 !
44 character(*), public, parameter :: mesh_vcoord_terrain_following_name = "TERRAIN_FOLLOWING"
45 integer, public, parameter :: mesh_vcoord_terrain_following_id = 1
46
47 !-----------------------------------------------------------------------------
48 !
49 !++ Private type & procedures
50 !
51 !-----------------------------------------------------------------------------
52
53 !-----------------------------------------------------------------------------
54 !
55 !++ Private parameters & variables
56 !
57 !-----------------------------------------------------------------------------
58
59contains
60 !> Get a type ID of vertical coordinate
61!OCL SERIAL
62 function meshutil_get_vcoord_typeid( vcoord_type ) result( vcoord_id )
63 implicit none
64
65 character(len=*), intent(in) :: vcoord_type !< Name of vertical coordinate type
66 integer :: vcoord_id
67
68 select case( vcoord_type )
71 case default
72 log_error("MeshUtil_VCoord_TypeID",*) "vcoord_type is inappropriate. Check!", vcoord_type
73 call prc_abort
74 end select
75
76 return
78
79 !> Get metric terms of vertical coordinate transformation
80!OCL SERIAL
81 subroutine meshutil_vcoord_getmetric( G13, G23, zlev, GsqrtV, &
82 topo, zTop, vcoord_id, lcmesh, elem, lcmesh2D, elem2D, &
83 Dx2D, Dy2D, Lift2D )
84 implicit none
85
86 type(localmesh3d), intent(in) :: lcmesh
87 class(elementbase3d), intent(in) :: elem
88 type(localmesh2d), intent(in) :: lcmesh2d
89 class(elementbase2d), intent(in) :: elem2d
90 real(rp), intent(out) :: g13(elem%np,lcmesh%nea)
91 real(rp), intent(out) :: g23(elem%np,lcmesh%nea)
92 real(rp), intent(out) :: zlev(elem%np,lcmesh%nea)
93 real(rp), intent(inout) :: gsqrtv(elem%np,lcmesh%nea)
94 real(rp), intent(in) :: topo(elem2d%np,lcmesh2d%nea)
95 integer, intent(in) :: vcoord_id
96 real(rp), intent(in) :: ztop
97 type(sparsemat), intent(in) :: dx2d
98 type(sparsemat), intent(in) :: dy2d
99 type(sparsemat), intent(in) :: lift2d
100
101 integer :: ke, ke2d, p
102 real(rp) :: del_flux(elem2d%nfptot,lcmesh2d%ne,2)
103 real(rp) :: fx2d(elem2d%np), fy2d(elem2d%np), liftdelflux2d(elem2d%np,2)
104 real(rp) :: gradzs(elem2d%np,lcmesh2d%ne,2)
105 real(rp) :: coef3d
106
107 integer :: indexh2dto3d(elem%np)
108 !------------------------------------------------
109
110 if ( vcoord_id == mesh_vcoord_terrain_following_id ) then
111
112 ! * z = topo + (1 - topo / zTop ) * zeta
113 ! * zeta = zTop * (z - topo)/(zTop - topo)
114 ! * Gi3 = (dzeta(x1,x2,z)/dxi)_z = d (zeta,z) / d (xi,z) = - d(z,zeta)/ d(xi,zeta) * d(xi,zeta)/d(xi,z)
115 ! = - (dz/dxi)_zeta * dzeta/dz
116 ! = (GsqrtV)^-1 * [ - 1 + zeta / zTop ] * d topo /dxi (i=1, 2)
117
118
119 indexh2dto3d(:) = elem%IndexH2Dto3D(:)
120
121 !$acc data create( del_flux, GradZs ) copyin( IndexH2Dto3D )
122
123 call cal_del_flux( del_flux, &
124 topo, lcmesh2d%normal_fn(:,:,1), lcmesh2d%normal_fn(:,:,2), &
125 lcmesh2d%VMapM, lcmesh2d%VMapP, lcmesh2d, elem2d )
126
127 !$omp parallel private(Fx2D, Fy2D, LiftDelFlux2D, coef3D )
128 !$acc parallel loop gang private(ke2D, Fx2D, Fy2D, LiftDelFlux2D, coef3D ) &
129 !$acc present(topo, del_flux, zlev, GsqrtV, G13, G23, lcmesh,elem,lcmesh2D,elem2D)
130 !$omp do
131 do ke2d=1, lcmesh2d%Ne
132 call sparsemat_matmul( dx2d, topo(:,ke2d), fx2d )
133 call sparsemat_matmul( dy2d, topo(:,ke2d), fy2d )
134#ifdef _OPENACC
135 call sparsemat_matmul( lift2d, lcmesh2d%Fscale(:,ke2d), del_flux(:,ke2d,1), liftdelflux2d(:,1))
136 call sparsemat_matmul( lift2d, lcmesh2d%Fscale(:,ke2d), del_flux(:,ke2d,2), liftdelflux2d(:,2))
137#else
138 call sparsemat_matmul( lift2d, lcmesh2d%Fscale(:,ke2d) * del_flux(:,ke2d,1), liftdelflux2d(:,1))
139 call sparsemat_matmul( lift2d, lcmesh2d%Fscale(:,ke2d) * del_flux(:,ke2d,2), liftdelflux2d(:,2))
140#endif
141 !$acc loop vector
142 do p=1, elem2d%Np
143 gradzs(p,ke2d,1) = lcmesh2d%Escale(p,ke2d,1,1) * fx2d(p) + liftdelflux2d(p,1)
144 gradzs(p,ke2d,2) = lcmesh2d%Escale(p,ke2d,2,2) * fy2d(p) + liftdelflux2d(p,2)
145 end do
146 end do
147 !$omp end do
148
149 !$omp do
150 !$acc parallel loop gang private(ke2D,coef3D) present(lcmesh,elem)
151 do ke=1, lcmesh%Ne
152 ke2d = lcmesh%EMap3Dto2D(ke)
153 !$acc loop vector
154 do p=1, elem%Np
155 coef3d = 1.0_rp - lcmesh%pos_en(p,ke,3) / ztop
156 zlev(p,ke) = lcmesh%pos_en(p,ke,3) &
157 + coef3d * topo(indexh2dto3d(p),ke2d)
158
159 gsqrtv(p,ke) = 1.0_rp - topo(indexh2dto3d(p),ke2d) / ztop ! dz/dzeta
160
161 coef3d = - coef3d / gsqrtv(p,ke)
162 g13(p,ke) = coef3d * gradzs(indexh2dto3d(p),ke2d,1)
163 g23(p,ke) = coef3d * gradzs(indexh2dto3d(p),ke2d,2)
164 end do
165 end do
166 !$omp end do
167 !$acc end parallel
168 !$omp end parallel
169
170 !$acc end data
171 else
172 log_error("Mesh_VCoord_GetMetric",*) "vcoord_id is inappropriate. Check!", vcoord_id
173 call prc_abort
174 end if
175 return
176 end subroutine meshutil_vcoord_getmetric
177
178!- private subroutines ----------------------
179
180!OCL SERIAL
181 subroutine cal_del_flux( del_flux, &
182 topo, nx, ny, vmapM, vmapP, lmesh, elem )
183 implicit none
184 type(localmesh2d), intent(in) :: lmesh
185 class(elementbase2d), intent(in) :: elem
186 real(rp), intent(out) :: del_flux(elem%nfptot*lmesh%ne,2)
187 real(rp), intent(in) :: topo(elem%np*lmesh%nea)
188 real(rp), intent(in) :: nx(elem%nfptot*lmesh%ne)
189 real(rp), intent(in) :: ny(elem%nfptot*lmesh%ne)
190 integer, intent(in) :: vmapm(elem%nfptot*lmesh%ne)
191 integer, intent(in) :: vmapp(elem%nfptot*lmesh%ne)
192
193 integer :: i
194 integer :: ip, im
195 real(rp) :: dtopo
196 !-------------------------------------
197
198 !$omp parallel do private( i, iM, iP, dtopo )
199 !$acc parallel loop present(topo, nx, ny, vmapM, vmapP, del_flux, lmesh, elem)
200 do i=1, elem%NfpTot * lmesh%Ne
201 im = vmapm(i); ip = vmapp(i)
202
203 dtopo = 0.5_rp * ( topo(ip) - topo(im) )
204
205 del_flux(i,1) = dtopo * nx(i)
206 del_flux(i,2) = dtopo * ny(i)
207 end do
208 return
209 end subroutine cal_del_flux
210end module scale_meshutil_vcoord
module FElib / Element / Base
module FElib / Mesh / Local 2D
module FElib / Mesh / Local 3D
module FElib / Mesh / utility for general vertical coordinate
integer function, public meshutil_get_vcoord_typeid(vcoord_type)
Get a type ID of vertical coordinate.
character(*), parameter, public mesh_vcoord_terrain_following_name
integer, parameter, public mesh_vcoord_terrain_following_id
subroutine, public meshutil_vcoord_getmetric(g13, g23, zlev, gsqrtv, topo, ztop, vcoord_id, lcmesh, elem, lcmesh2d, elem2d, dx2d, dy2d, lift2d)
Get metric terms of vertical coordinate transformation.
Module common / sparsemat.
Derived type representing a 2D reference element.
Derived type representing a 3D reference element.
Derived type representing a local mesh for 2D domain.
Derived type to manage a local 3D computational domain.
Derived type to manage a sparse matrix.