FE-Project
Loading...
Searching...
No Matches
mod_mkinit_util.F90
Go to the documentation of this file.
1!-------------------------------------------------------------------------------
10!-------------------------------------------------------------------------------
11#include "scalelib.h"
13 !-----------------------------------------------------------------------------
14 !
15 !++ used modules
16 !
17 use scale_precision
18 use scale_io
19 use scale_prof
20 use scale_prc
21
22 use scale_const, only: &
23 pi => const_pi
24
32
33
34 !-----------------------------------------------------------------------------
35 implicit none
36 private
37 !-----------------------------------------------------------------------------
38 !
39 !++ Public procedure
40 !
41 public :: mkinitutil_gen_gpmat
42 public :: mkinitutil_gen_vm1mat
47
48contains
49
50!OCL SERIAL
51 subroutine mkinitutil_gen_gpmat( GPMat, &
52 elem_intrp, elem )
53 implicit none
54
55 class(elementbase3d), intent(in) :: elem_intrp
56 class(elementbase3d), intent(in) :: elem
57 real(rp), intent(out) :: gpmat(elem%np,elem_intrp%np)
58
59 integer :: p1, p2, p3, p_
60 integer :: p_intrp
61
62 real(rp) :: invv_intrp(elem%np,elem_intrp%np)
63 !---------------------------------------------
64
65 invv_intrp(:,:) = 0.0_rp
66 do p3=1, elem%PolyOrder_v+1
67 do p2=1, elem%PolyOrder_h+1
68 do p1=1, elem%PolyOrder_h+1
69 p_ = p1 + (p2-1)*(elem%PolyOrder_h + 1) + (p3-1)*(elem%PolyOrder_h + 1)**2
70 p_intrp = p1 + (p2-1)*(elem_intrp%PolyOrder_h + 1) + (p3-1)*(elem_intrp%PolyOrder_h + 1)**2
71 invv_intrp(p_,:) = elem_intrp%invV(p_intrp,:)
72 end do
73 end do
74 end do
75 gpmat(:,:) = matmul(elem%V, invv_intrp)
76
77 return
78 end subroutine mkinitutil_gen_gpmat
79
80!OCL SERIAL
81 subroutine mkinitutil_gen_vm1mat( Vm1Mat, &
82 elem_intrp, elem )
83 implicit none
84
85 class(elementbase3d), intent(in) :: elem_intrp
86 class(elementbase3d), intent(in) :: elem
87 real(rp), intent(out) :: vm1mat(elem%np,elem_intrp%np)
88
89 integer :: p1, p2, p3, p_
90 integer :: p_intrp
91
92 real(rp) :: invv_intrpvm1(elem%np,elem_intrp%np)
93 !---------------------------------------------
94
95 invv_intrpvm1(:,:) = 0.0_rp
96 do p3=1, elem%PolyOrder_v
97 do p2=1, elem%PolyOrder_h+1
98 do p1=1, elem%PolyOrder_h+1
99 p_ = p1 + (p2-1)*(elem%PolyOrder_h + 1) + (p3-1)*(elem%PolyOrder_h + 1)**2
100 p_intrp = p1 + (p2-1)*(elem_intrp%PolyOrder_h + 1) + (p3-1)*(elem_intrp%PolyOrder_h + 1)**2
101 invv_intrpvm1(p_,:) = elem_intrp%invV(p_intrp,:)
102 end do
103 end do
104 end do
105 vm1mat(:,:) = matmul(elem%V, invv_intrpvm1)
106
107 return
108 end subroutine mkinitutil_gen_vm1mat
109
117!OCL SERIAL
119 q, &
120 qmax, rx, ry, rz, xc, yc, zc, &
121 x, y, z, lcmesh3D, elem, &
122 IntrpPolyOrder_h, IntrpPolyOrder_v, &
123 z_func_type, z_func_params, cosbell_exponent )
124
125 implicit none
126
127 class(localmesh3d), intent(in) :: lcmesh3d
128 class(elementbase3d), intent(in) :: elem
129 real(rp), intent(out) :: q(elem%np,lcmesh3d%nea)
130 real(rp), intent(in) :: qmax
131 real(rp), intent(in) :: rx, ry, rz
132 real(rp), intent(in) :: xc, yc, zc
133 real(rp), intent(in) :: x(elem%np,lcmesh3d%ne)
134 real(rp), intent(in) :: y(elem%np,lcmesh3d%ne)
135 real(rp), intent(in) :: z(elem%np,lcmesh3d%ne)
136 integer, intent(in) :: intrppolyorder_h
137 integer, intent(in) :: intrppolyorder_v
138 character(len=*), optional, intent(in) :: z_func_type
139 real(rp), optional, intent(in) :: z_func_params(:)
140 integer, intent(in), optional :: cosbell_exponent
141
142 integer :: ke
143
144 type(hexahedralelement) :: elem_intrp
145 real(rp), allocatable :: x_intrp(:,:), y_intrp(:,:), z_intrp(:,:)
146 real(rp), allocatable :: r_intrp(:)
147 real(rp), allocatable :: z_func(:,:)
148 real(rp) :: vx(elem%nv), vy(elem%nv), vz(elem%nv)
149
150 real(rp), allocatable :: intrpmat(:,:)
151 real(rp), allocatable :: q_intrp(:)
152
153 integer :: exponent
154 !-----------------------------------------------
155
156 if ( present(cosbell_exponent) ) then
157 exponent = cosbell_exponent
158 else
159 exponent = 1
160 end if
161
162 call elem_intrp%Init( intrppolyorder_h, intrppolyorder_v, .false. )
163
164 allocate( intrpmat(elem%Np,elem_intrp%Np) )
165 call mkinitutil_gen_gpmat( intrpmat, elem_intrp, elem )
166
167 allocate( x_intrp(elem_intrp%Np,lcmesh3d%Ne), y_intrp(elem_intrp%Np,lcmesh3d%Ne), z_intrp(elem_intrp%Np,lcmesh3d%Ne) )
168 allocate( z_func(elem_intrp%Np,lcmesh3d%Ne))
169 allocate( r_intrp(elem_intrp%Np) )
170 allocate( q_intrp(elem_intrp%Np) )
171
172 !$omp parallel private( &
173 !$omp q_intrp, vx, vy, vz, &
174 !$omp x_intrp, y_intrp, z_intrp, r_intrp )
175
176 !$omp do
177 do ke=lcmesh3d%NeS, lcmesh3d%NeE
178
179 vx(:) = lcmesh3d%pos_ev(lcmesh3d%EToV(ke,:),1)
180 vy(:) = lcmesh3d%pos_ev(lcmesh3d%EToV(ke,:),2)
181 vz(:) = lcmesh3d%pos_ev(lcmesh3d%EToV(ke,:),3)
182 x_intrp(:,ke) = vx(1) + 0.5_rp * ( elem_intrp%x1(:) + 1.0_rp ) * ( vx(2) - vx(1) )
183 y_intrp(:,ke) = vy(1) + 0.5_rp * ( elem_intrp%x2(:) + 1.0_rp ) * ( vy(4) - vy(1) )
184 z_intrp(:,ke) = vz(1) + 0.5_rp * ( elem_intrp%x3(:) + 1.0_rp ) * ( vz(5) - vz(1) )
185
186 z_func(:,ke) = 1.0_rp
187 end do
188 !$omp end do
189
190 ! Calculate the vertical function
191 if ( present(z_func_type) ) then
192 select case(z_func_type)
193 case ('sin')
194 !$omp do
195 do ke=lcmesh3d%NeS, lcmesh3d%NeE
196 z_func(:,ke) = sin( z_func_params(1) * pi * z_intrp(:,ke) / z_func_params(2) )
197 end do
198 !$omp end do
199 end select
200 end if
201
202 !$omp do
203 do ke=lcmesh3d%NeS, lcmesh3d%NeE
204 r_intrp(:) = sqrt( &
205 ( (x_intrp(:,ke) - xc) / rx )**2 &
206 + ( (y_intrp(:,ke) - yc) / ry )**2 &
207 + ( (z_intrp(:,ke) - zc) / rz )**2 )
208
209 where( r_intrp(:) <= 1.0_rp )
210 q_intrp(:) = qmax * ( 0.5_rp * (1.0_rp + cos( pi * r_intrp(:) ) ) )**exponent
211 elsewhere
212 q_intrp(:) = 0.0_rp
213 end where
214 q(:,ke) = matmul(intrpmat, q_intrp(:) * z_func(:,ke))
215 end do
216 !$omp end do
217 !$omp end parallel
218
219 call elem_intrp%Final()
220
221 return
222 end subroutine mkinitutil_calc_cosinebell
223
231!OCL SERIAL
233 q, &
234 qmax, rh, lonc, latc, rplanet, &
235 x, y, z, lcmesh3D, elem, &
236 IntrpPolyOrder_h, IntrpPolyOrder_v, &
237 z_func_type, z_func_params, cosbell_exponent )
238
239 use scale_cubedsphere_coord_cnv, only: &
241 implicit none
242
243 class(localmesh3d), intent(in) :: lcmesh3d
244 class(elementbase3d), intent(in) :: elem
245 real(rp), intent(out) :: q(elem%np,lcmesh3d%nea)
246 real(rp), intent(in) :: qmax
247 real(rp), intent(in) :: rh
248 real(rp), intent(in) :: lonc, latc
249 real(rp), intent(in) :: rplanet
250 real(rp), intent(in) :: x(elem%np,lcmesh3d%ne)
251 real(rp), intent(in) :: y(elem%np,lcmesh3d%ne)
252 real(rp), intent(in) :: z(elem%np,lcmesh3d%ne)
253 integer, intent(in) :: intrppolyorder_h
254 integer, intent(in) :: intrppolyorder_v
255 character(len=*), optional, intent(in) :: z_func_type
256 real(rp), optional, intent(in) :: z_func_params(:)
257 integer, intent(in), optional :: cosbell_exponent
258
259 integer :: ke
260
261 type(hexahedralelement) :: elem_intrp
262 real(rp), allocatable :: x_intrp(:,:), y_intrp(:,:), z_intrp(:,:)
263 real(rp), allocatable :: gam_intrp(:,:)
264 real(rp), allocatable :: lon_intrp(:,:), lat_intrp(:,:)
265 real(rp), allocatable :: z_func(:,:)
266 real(rp), allocatable :: r_intrp(:)
267 real(rp) :: vx(elem%nv), vy(elem%nv), vz(elem%nv)
268
269 real(rp), allocatable :: intrpmat(:,:)
270 real(rp), allocatable :: q_intrp(:)
271
272 integer :: exponent
273
274 !-----------------------------------------------
275
276 if ( present(cosbell_exponent) ) then
277 exponent = cosbell_exponent
278 else
279 exponent = 1
280 end if
281
282 call elem_intrp%Init( intrppolyorder_h, intrppolyorder_v, .false. )
283
284 allocate( intrpmat(elem%Np,elem_intrp%Np) )
285 call mkinitutil_gen_gpmat( intrpmat, elem_intrp, elem )
286
287 allocate( x_intrp(elem_intrp%Np,lcmesh3d%Ne), y_intrp(elem_intrp%Np,lcmesh3d%Ne), z_intrp(elem_intrp%Np,lcmesh3d%Ne) )
288 allocate( gam_intrp(elem_intrp%Np,lcmesh3d%Ne) )
289 allocate( lon_intrp(elem_intrp%Np,lcmesh3d%Ne), lat_intrp(elem_intrp%Np,lcmesh3d%Ne) )
290 allocate( z_func(elem_intrp%Np,lcmesh3d%Ne) )
291 allocate( r_intrp(elem_intrp%Np) )
292 allocate( q_intrp(elem_intrp%Np) )
293
294
295 !$omp parallel do private(vx, vy, vz)
296 do ke=lcmesh3d%NeS, lcmesh3d%NeE
297 vx(:) = lcmesh3d%pos_ev(lcmesh3d%EToV(ke,:),1)
298 vy(:) = lcmesh3d%pos_ev(lcmesh3d%EToV(ke,:),2)
299 vz(:) = lcmesh3d%pos_ev(lcmesh3d%EToV(ke,:),3)
300 x_intrp(:,ke) = vx(1) + 0.5_rp * ( elem_intrp%x1(:) + 1.0_rp ) * ( vx(2) - vx(1) )
301 y_intrp(:,ke) = vy(1) + 0.5_rp * ( elem_intrp%x2(:) + 1.0_rp ) * ( vy(4) - vy(1) )
302 z_intrp(:,ke) = vz(1) + 0.5_rp * ( elem_intrp%x3(:) + 1.0_rp ) * ( vz(5) - vz(1) )
303 gam_intrp(:,ke) = 1.0_rp
304
305 z_func(:,ke) = 1.0_rp
306 end do
307
308 call cubedspherecoordcnv_cs2lonlatpos( lcmesh3d%panelID, x_intrp, y_intrp, gam_intrp, & ! (in)
309 elem_intrp%Np * lcmesh3d%Ne, & ! (in)
310 lon_intrp(:,:), lat_intrp(:,:) ) ! (out)
311
312 ! Calculate the vertical function
313 if ( present(z_func_type) ) then
314 select case(z_func_type)
315 case ('sin')
316 !$omp parallel do
317 do ke=lcmesh3d%NeS, lcmesh3d%NeE
318 z_func(:,ke) = sin( z_func_params(1) * pi * z_intrp(:,ke) / z_func_params(2) )
319 end do
320 end select
321 end if
322
323 !$omp parallel do private( r_intrp, q_intrp )
324 do ke=lcmesh3d%NeS, lcmesh3d%NeE
325
326 ! Calculate the horizontal function
327 r_intrp(:) = rplanet / rh * acos( sin(latc) * sin(lat_intrp(:,ke)) + cos(latc) * cos(lat_intrp(:,ke)) * cos(lon_intrp(:,ke) - lonc) )
328 where( r_intrp(:) <= 1.0_rp )
329 q_intrp(:) = qmax * ( 0.5_rp * (1.0_rp + cos( pi * r_intrp(:) ) ) )**exponent
330 elsewhere
331 q_intrp(:) = 0.0_rp
332 end where
333
334 ! Perform Galerkin projection
335 q(:,ke) = matmul(intrpmat, q_intrp(:) * z_func(:,ke))
336 end do
337
338 call elem_intrp%Final()
339
340 return
342
343
347!OCL SERIAL
349 func, IntrpPolyOrder_h, IntrpPolyOrder_v, &
350 lcmesh3D, elem )
351
352 implicit none
353 class(localmesh3d), intent(in) :: lcmesh3d
354 class(elementbase3d), intent(in) :: elem
355 real(rp), intent(out) :: q(elem%np,lcmesh3d%nea)
356 integer, intent(in) :: intrppolyorder_h
357 integer, intent(in) :: intrppolyorder_v
358
359 interface
360 subroutine func( q_intrp, &
361 x, y, z, elem_intrp )
362 import elementbase3d
363 import rp
364 class(elementbase3d), intent(in) :: elem_intrp
365 real(rp), intent(out) :: q_intrp(elem_intrp%np)
366 real(rp), intent(in) :: x(elem_intrp%np)
367 real(rp), intent(in) :: y(elem_intrp%np)
368 real(rp), intent(in) :: z(elem_intrp%np)
369 end subroutine func
370 end interface
371
372 type(hexahedralelement) :: elem_intrp
373 real(rp), allocatable :: x_intrp(:,:), y_intrp(:,:), z_intrp(:,:)
374 real(rp) :: vx(elem%nv), vy(elem%nv), vz(elem%nv)
375
376 real(rp), allocatable :: intrpmat(:,:)
377 real(rp), allocatable :: q_intrp(:)
378
379 integer :: ke
380 !-----------------------------------------------
381
382 call elem_intrp%Init( intrppolyorder_h, intrppolyorder_v, .false. )
383
384 allocate( intrpmat(elem%Np,elem_intrp%Np) )
385 call mkinitutil_gen_gpmat( intrpmat, elem_intrp, elem )
386
387 allocate( x_intrp(elem_intrp%Np,lcmesh3d%Ne), y_intrp(elem_intrp%Np,lcmesh3d%Ne), z_intrp(elem_intrp%Np,lcmesh3d%Ne) )
388 allocate( q_intrp(elem_intrp%Np) )
389
390 !$omp parallel do private(vx, vy, vz)
391 do ke=lcmesh3d%NeS, lcmesh3d%NeE
392 vx(:) = lcmesh3d%pos_ev(lcmesh3d%EToV(ke,:),1)
393 vy(:) = lcmesh3d%pos_ev(lcmesh3d%EToV(ke,:),2)
394 vz(:) = lcmesh3d%pos_ev(lcmesh3d%EToV(ke,:),3)
395 x_intrp(:,ke) = vx(1) + 0.5_rp * ( elem_intrp%x1(:) + 1.0_rp ) * ( vx(2) - vx(1) )
396 y_intrp(:,ke) = vy(1) + 0.5_rp * ( elem_intrp%x2(:) + 1.0_rp ) * ( vy(4) - vy(1) )
397 z_intrp(:,ke) = vz(1) + 0.5_rp * ( elem_intrp%x3(:) + 1.0_rp ) * ( vz(5) - vz(1) )
398 end do
399
400 !$omp parallel do private( q_intrp )
401 do ke=lcmesh3d%NeS, lcmesh3d%NeE
402
403 call func( q_intrp, & ! (out)
404 x_intrp(:,ke), y_intrp(:,ke), z_intrp(:,ke), & ! (in)
405 elem_intrp ) ! (in)
406
407 ! Perform Galerkin projection
408 q(:,ke) = matmul( intrpmat, q_intrp )
409 end do
410
411 call elem_intrp%Final()
412
413 return
415
419!OCL SERIAL
421 func, IntrpPolyOrder_h, IntrpPolyOrder_v, &
422 lcmesh3D, elem, rplanet )
423
424 use scale_cubedsphere_coord_cnv, only: &
426
427 implicit none
428 class(localmesh3d), intent(in) :: lcmesh3d
429 class(elementbase3d), intent(in) :: elem
430 real(rp), intent(out) :: q(elem%np,lcmesh3d%nea)
431 integer, intent(in) :: intrppolyorder_h
432 integer, intent(in) :: intrppolyorder_v
433 real(rp), intent(in) :: rplanet
434
435 interface
436 subroutine func( q_intrp, &
437 lon, lat, z, elem_intrp, rplanet_ )
438 import elementbase3d
439 import rp
440 class(elementbase3d), intent(in) :: elem_intrp
441 real(rp), intent(out) :: q_intrp(elem_intrp%np)
442 real(rp), intent(in) :: lon(elem_intrp%np)
443 real(rp), intent(in) :: lat(elem_intrp%np)
444 real(rp), intent(in) :: z(elem_intrp%np)
445 real(rp), intent(in) :: rplanet_
446 end subroutine func
447 end interface
448
449 type(hexahedralelement) :: elem_intrp
450 real(rp), allocatable :: x_intrp(:,:), y_intrp(:,:), z_intrp(:,:)
451 real(rp), allocatable :: gam_intrp(:,:)
452 real(rp), allocatable :: lon_intrp(:,:), lat_intrp(:,:)
453 real(rp) :: vx(elem%nv), vy(elem%nv), vz(elem%nv)
454
455 real(rp), allocatable :: intrpmat(:,:)
456 real(rp), allocatable :: q_intrp(:)
457
458 integer :: ke
459 !-----------------------------------------------
460
461 call elem_intrp%Init( intrppolyorder_h, intrppolyorder_v, .false. )
462
463 allocate( intrpmat(elem%Np,elem_intrp%Np) )
464 call mkinitutil_gen_gpmat( intrpmat, elem_intrp, elem )
465
466 allocate( x_intrp(elem_intrp%Np,lcmesh3d%Ne), y_intrp(elem_intrp%Np,lcmesh3d%Ne), z_intrp(elem_intrp%Np,lcmesh3d%Ne) )
467 allocate( gam_intrp(elem_intrp%Np,lcmesh3d%Ne) )
468 allocate( lon_intrp(elem_intrp%Np,lcmesh3d%Ne), lat_intrp(elem_intrp%Np,lcmesh3d%Ne) )
469 allocate( q_intrp(elem_intrp%Np) )
470
471 !$omp parallel do private(vx, vy, vz)
472 do ke=lcmesh3d%NeS, lcmesh3d%NeE
473 vx(:) = lcmesh3d%pos_ev(lcmesh3d%EToV(ke,:),1)
474 vy(:) = lcmesh3d%pos_ev(lcmesh3d%EToV(ke,:),2)
475 vz(:) = lcmesh3d%pos_ev(lcmesh3d%EToV(ke,:),3)
476 x_intrp(:,ke) = vx(1) + 0.5_rp * ( elem_intrp%x1(:) + 1.0_rp ) * ( vx(2) - vx(1) )
477 y_intrp(:,ke) = vy(1) + 0.5_rp * ( elem_intrp%x2(:) + 1.0_rp ) * ( vy(4) - vy(1) )
478 z_intrp(:,ke) = vz(1) + 0.5_rp * ( elem_intrp%x3(:) + 1.0_rp ) * ( vz(5) - vz(1) )
479
480 gam_intrp(:,ke) = 1.0_rp
481 end do
482
483 call cubedspherecoordcnv_cs2lonlatpos( lcmesh3d%panelID, x_intrp, y_intrp, gam_intrp, & ! (in)
484 elem_intrp%Np * lcmesh3d%Ne, & ! (in)
485 lon_intrp(:,:), lat_intrp(:,:) ) ! (out)
486
487 !$omp parallel do private( q_intrp )
488 do ke=lcmesh3d%NeS, lcmesh3d%NeE
489
490 call func( q_intrp, & ! (out)
491 lon_intrp(:,ke), lat_intrp(:,ke), z_intrp(:,ke), & ! (in)
492 elem_intrp, rplanet ) ! (in)
493
494 ! Perform Galerkin projection
495 q(:,ke) = matmul( intrpmat, q_intrp )
496 end do
497
498 call elem_intrp%Final()
499
500 return
502
503end module mod_mkinit_util
module Utility for mkinit
subroutine, public mkinitutil_gen_gpmat(gpmat, elem_intrp, elem)
subroutine, public mkinitutil_gen_vm1mat(vm1mat, elem_intrp, elem)
subroutine, public mkinitutil_galerkinprojection_global(q, func, intrppolyorder_h, intrppolyorder_v, lcmesh3d, elem, rplanet)
Apply the Galerkin projection to the user-defined function (for global model)
subroutine, public mkinitutil_calc_cosinebell(q, qmax, rx, ry, rz, xc, yc, zc, x, y, z, lcmesh3d, elem, intrppolyorder_h, intrppolyorder_v, z_func_type, z_func_params, cosbell_exponent)
Calculate the distribution function of a cosine bell in regional domain.
subroutine, public mkinitutil_calc_cosinebell_global(q, qmax, rh, lonc, latc, rplanet, x, y, z, lcmesh3d, elem, intrppolyorder_h, intrppolyorder_v, z_func_type, z_func_params, cosbell_exponent)
Calculate the distribution function of a cosine bell in global domain.
subroutine, public mkinitutil_galerkinprojection(q, func, intrppolyorder_h, intrppolyorder_v, lcmesh3d, elem)
Apply the Galerkin projection to the user-defined function.
module common / Coordinate conversion with a cubed-sphere
subroutine, public cubedspherecoordcnv_cs2lonlatpos(panelid, alpha, beta, gam, np, lon, lat)
module FElib / Element / Base
module FElib / Element / hexahedron
module FElib / Element / Quadrilateral
module FElib / Mesh / Local 2D
module FElib / Mesh / Local 3D
module FElib / Mesh / Cubic 3D domain