FE-Project
Loading...
Searching...
No Matches
scale_cubedsphere_coord_cnv.F90
Go to the documentation of this file.
1!-------------------------------------------------------------------------------
2!> Module common / Coordinate conversion with cubed-sphere projection
3!!
4!! @par Description
5!! A module to provide coordinate conversions with an equiangular gnomonic cubed-sphere projection
6!!
7!!
8!! @par Reference
9!! - Nair et al. 2015:
10!! A Discontinuous Galerkin Transport Scheme on the Cubed Sphere.
11!! Monthly Weather Review, 133, 814–828.
12!! (Appendix A)
13!! - Yin et al. 2017:
14!! Parallel numerical simulation of the thermal convection in the Earth’s outer core on the cubed-sphere.
15!! Geophysical Journal International, 209, 1934–1954.
16!! (Appendix A)
17!!
18!! @author Yuta Kawai, Team SCALE
19!!
20#include "scaleFElib.h"
22 !-----------------------------------------------------------------------------
23 !
24 !++ used modules
25 !
26 use scale_const, only: &
27 pi => const_pi, &
28 eps => const_eps, &
29 rplanet => const_radius
30 use scale_precision
31 use scale_prc
32 use scale_io
33 use scale_prc
34
35#ifdef _OPENACC
36 use openacc, only: acc_async_sync
37#endif
38
39 !-----------------------------------------------------------------------------
40 implicit none
41 private
42
43 !-----------------------------------------------------------------------------
44 !
45 !++ Public type & procedure
46 !
54
56 module procedure :: cubedspherecoordcnv_cs2localorthvec_alpha_0
57 module procedure :: cubedspherecoordcnv_cs2localorthvec_alpha_1
58 end interface
60
62 module procedure :: cubedspherecoordcnv_localorth2csvec_alpha_0
63 module procedure :: cubedspherecoordcnv_localorth2csvec_alpha_1
64 end interface
66
67 !-----------------------------------------------------------------------------
68 !
69 !++ Public parameters & variables
70 !
71 !-----------------------------------------------------------------------------
72 !
73 !++ Private type & procedure
74 !
75 !-----------------------------------------------------------------------------
76 !
77 !++ Private parameters & variables
78 !
79 !-----------------------------------------------------------------------------
80
81
82contains
83 !> Calculate longitude and latitude coordinates from local coordinates using the central angles in an equiangular gnomonic cubed-sphere projection
84 !!
85!OCL SERIAL
87 panelID, alpha, beta, gam, Np, & ! (in)
88 lon, lat ) ! (out)
91 implicit none
92
93 integer, intent(in) :: panelid !< Panel ID of cubed-sphere coordinates
94 integer, intent(in) :: np !< Array size
95 real(rp), intent(in) :: alpha(np) !< Local coordinate using the central angles [rad]
96 real(rp), intent(in) :: beta (np) !< Local coordinate using the central angles [rad]
97 real(rp), intent(in) :: gam(np) !< A factor of r/a
98 real(rp), intent(out) :: lon(np) !< Longitude coordinate [rad]
99 real(rp), intent(out) :: lat(np) !< Latitude coordinate [rad]
100
101 real(rp) :: cartpos(np,3)
102 real(rp) :: geogpos(np,3)
103
104 integer :: p
105 !-----------------------------------------------------------------------------
106
107 select case( panelid )
108 case( 1, 2, 3, 4 )
109 !$omp parallel do
110 !$acc parallel loop present(alpha, beta, lon, lat)
111 do p=1, np
112 lon(p) = alpha(p) + 0.5_rp * pi * dble(panelid - 1)
113 lat(p) = atan( tan( beta(p) ) * cos( alpha(p) ) )
114
115 if ( lon(p) < 0.0_rp ) lon(p) = lon(p) + 2.0_rp * pi
116 end do
117 !$omp end parallel do
118 case(5, 6)
119 !$acc data create(CartPos, GeogPos) present(alpha, beta, gam, lon, lat)
120 call cubedspherecoordcnv_cs2cartpos( panelid, alpha, beta, gam, np, & ! (in)
121 cartpos(:,1), cartpos(:,2), cartpos(:,3) ) ! (out)
122
123 call geographiccoordcnv_orth_to_geo_pos( cartpos(:,:), np, & ! (in)
124 geogpos(:,:) ) ! (out)
125
126 !$omp parallel do
127 !$acc parallel loop
128 do p=1, np
129 lon(p) = geogpos(p,1)
130 lat(p) = geogpos(p,2)
131
132 if ( alpha(p) < 0.0_rp ) lon(p) = lon(p) + 2.0_rp * pi
133 end do
134 !$omp end parallel do
135 !$acc end data
136 case default
137 log_error("CubedSphereCoordCnv_CS2LonLatPos",'(a,i2,a)') "panelID ", panelid, " is invalid. Check!"
138 call prc_abort
139 end select
140
141 return
143
144 !> Convert the components of a vector in local coordinates with an equiangular gnomonic cubed-sphere projection to those in longitude and latitude coordinates
145 !!
146!OCL SERIAL
148 panelID, alpha, beta, gam, Np, & ! (in)
149 vecalpha, vecbeta, & ! (in)
150 veclon, veclat, & ! (out)
151 lat, gpu_async_id ) ! (in, optional)
152
153 use scale_const, only: &
154 eps => const_eps
155 implicit none
156
157 integer, intent(in) :: panelid !< Panel ID of cubed-sphere coordinates
158 integer, intent(in) :: np !< Array size
159 real(rp), intent(in) :: alpha(np) !< Local coordinate using the central angles [rad]
160 real(rp), intent(in) :: beta (np) !< Local coordinate using the central angles [rad]
161 real(rp), intent(in) :: gam(np) !< A factor of RPlanet / r
162 real(dp), intent(in) :: vecalpha(np) !< A component of vector in the alpha-coordinate
163 real(dp), intent(in) :: vecbeta (np) !< A component of vector in the beta-coordinate
164 real(rp), intent(out) :: veclon(np) !< A component of vector in the longitude-coordinate
165 real(rp), intent(out) :: veclat(np) !< A component of vector in the latitude-coordinate
166 real(rp), intent(in), optional :: lat(np) !< latitude [rad]
167 integer, intent(in), optional :: gpu_async_id !< GPU asynchronous ID
168
169 integer :: p
170 real(rp) :: x ,y, del2
171 real(rp) :: s
172
173 real(rp) :: radius
174 real(rp) :: cos_lat(np)
175
176 integer :: gpu_async_id_
177 !-----------------------------------------------------------------------------
178
179#ifdef _OPENACC
180 if (present(gpu_async_id)) then
181 gpu_async_id_ = gpu_async_id
182 else
183 gpu_async_id_ = acc_async_sync
184 end if
185#endif
186
187 !$acc data create(cos_Lat) present(alpha, beta, gam, VecLon, VecLat, VecAlpha, VecBeta)
188
189 if (present(lat)) then
190 !$omp parallel do
191 !$acc parallel loop
192 do p=1, np
193 cos_lat(p) = cos(lat(p))
194 end do
195 end if
196
197 select case( panelid )
198 case( 1, 2, 3, 4 )
199 if (.not. present(lat)) then
200 !$omp parallel do
201 !$acc parallel loop async(gpu_async_id_)
202 do p=1, np
203 cos_lat(p) = cos( atan( tan( beta(p) ) * cos( alpha(p) ) ) )
204 end do
205 end if
206
207 !$omp parallel do private( X, Y, del2, radius )
208 !$acc parallel loop async(gpu_async_id_)
209 do p=1, np
210 x = tan( alpha(p) )
211 y = tan( beta(p) )
212 del2 = 1.0_rp + x**2 + y**2
213 radius = rplanet * gam(p)
214
215 veclon(p) = vecalpha(p) * cos_lat(p) * radius
216 veclat(p) = ( - x * y * vecalpha(p) + ( 1.0_rp + y**2 ) * vecbeta(p) ) &
217 * radius * sqrt( 1.0_rp + x**2 ) / del2
218 end do
219 case ( 5 )
220 s = 1.0_rp
221 case ( 6 )
222 s = - 1.0_rp
223 case default
224 log_error("CubedSphereCoordCnv_CS2LonLatVec",'(a,i2,a)') "panelID ", panelid, " is invalid. Check!"
225 call prc_abort
226 end select
227
228 select case( panelid )
229 case( 5, 6 )
230 !$omp parallel do private( X, Y, del2, radius )
231 !$acc parallel loop async(gpu_async_id_)
232 do p=1, np
233 x = tan( alpha(p) )
234 y = tan( beta(p) )
235 del2 = 1.0_rp + x**2 + y**2
236 radius = s * rplanet * gam(p)
237
238 if (.not. present(lat)) then
239 cos_lat(p) = cos( atan( sign(1.0_rp, s) / max( sqrt( x**2 + y**2 ), eps ) ) )
240 end if
241
242 veclon(p) = (- y * ( 1.0_rp + x**2 ) * vecalpha(p) + x * ( 1.0_rp + y**2 ) * vecbeta(p) ) &
243 * radius / max( x**2 + y**2, eps ) * cos_lat(p)
244 veclat(p) = (- x * ( 1.0_rp + x**2 ) * vecalpha(p) - y * ( 1.0_rp + y**2 ) * vecbeta(p) ) &
245 * radius / ( del2 * ( max( sqrt( x**2 + y**2 ), eps ) ) )
246 end do
247 end select
248
249 !$acc end data
250
251 return
253
254 !> Calculate local coordinates using the central angles in an equiangular gnomonic cubed-sphere projection from longitude and latitude coordinates
255 !!
256!OCL SERIAL
258 panelID, lon, lat, Np, & ! (in)
259 alpha, beta ) ! (out)
260
261 implicit none
262 integer, intent(in) :: panelid !< Panel ID of cubed-sphere coordinates
263 integer, intent(in) :: np !< Array size
264 real(rp), intent(in) :: lon(np) !< Longitude coordinate [rad]
265 real(rp), intent(in) :: lat(np) !< Latitude coordinate [rad]
266 real(rp), intent(out) ::alpha(np) !< Local coordinate using the central angles [rad]
267 real(rp), intent(out) ::beta (np) !< Local coordinate using the central angles [rad]
268
269 integer :: p
270 real(rp) :: tan_lat
271 real(rp) :: lon_(np)
272 !-----------------------------------------------------------------------------
273
274 !$acc data create(lon_) present(lon, lat, alpha, beta)
275
276 select case(panelid)
277 case ( 1, 2, 3, 4 )
278 !$omp parallel
279 if ( panelid == 1 ) then
280 !$omp do
281 !$acc parallel loop
282 do p=1, np
283 if ( lon(p) >= 2.0_rp * pi - 0.25_rp * pi ) then
284 lon_(p) = lon(p) - 2.0_rp * pi
285 else
286 lon_(p) = lon(p)
287 end if
288 end do
289 else
290 !$omp do
291 !$acc parallel loop
292 do p=1, np
293 if ( lon(p) < 0.0_rp ) then
294 lon_(p) = lon(p) + 2.0_rp * pi
295 else
296 lon_(p) = lon(p)
297 end if
298 end do
299 end if
300 !$omp do
301 !$acc parallel loop
302 do p=1, np
303 alpha(p) = lon_(p) - 0.5_rp * pi * ( dble(panelid) - 1.0_rp )
304 beta(p) = atan( tan(lat(p)) / cos(alpha(p)) )
305 end do
306 !$omp end parallel
307 case ( 5 )
308 !$omp parallel private(tan_lat)
309 !$omp do
310 !$acc parallel loop
311 do p=1, np
312 tan_lat = tan(lat(p))
313 alpha(p) = + atan( sin(lon(p)) / tan_lat )
314 beta(p) = - atan( cos(lon(p)) / tan_lat )
315 end do
316 !$omp end parallel
317 case ( 6 )
318 !$omp parallel private(tan_lat)
319 !$omp do
320 !$acc parallel loop
321 do p=1, np
322 tan_lat = tan(lat(p))
323 alpha(p) = - atan( sin(lon(p)) / tan_lat )
324 beta(p) = - atan( cos(lon(p)) / tan_lat )
325 end do
326 !$omp end parallel
327 case default
328 log_error("CubedSphereCoordCnv_LonLat2CSPos",'(a,i2,a)') "panelID ", panelid, " is invalid. Check!"
329 call prc_abort
330 end select
331
332 !$acc end data
333 return
335
336 !> Convert the components of a vector in longitude and latitude coordinates to those in local coordinates with an equiangular gnomonic cubed-sphere projection
337 !!
338!OCL SERIAL
340 panelID, alpha, beta, gam, Np, & ! (in)
341 veclon, veclat, & ! (in)
342 vecalpha, vecbeta, & ! (out)
343 lat, gpu_async_id ) ! (in, optional)
344
345 implicit none
346
347 integer, intent(in) :: panelid !< Panel ID of cubed-sphere coordinates
348 integer, intent(in) :: np !< Array size
349 real(rp), intent(in) :: alpha(np) !< Local coordinate using the central angles [rad]
350 real(rp), intent(in) :: beta (np) !< Local coordinate using the central angles [rad]
351 real(rp), intent(in) :: gam(np) !< A factor of RPlanet / r
352 real(dp), intent(in) :: veclon(np) !< A component of vector in the longitude-coordinate
353 real(dp), intent(in) :: veclat(np) !< A component of vector in the latitude-coordinate
354 real(dp), intent(out) :: vecalpha(np) !< A component of vector in the alpha-coordinate
355 real(dp), intent(out) :: vecbeta (np) !< A component of vector in the beta-coordinate
356 real(rp), intent(in), optional :: lat(np) !< latitude [rad]
357 integer, intent(in), optional :: gpu_async_id !< GPU asynchronous ID for OpenACC operations
358
359 integer :: p
360 real(rp) :: x ,y, del2
361 real(rp) :: s
362
363 real(rp) :: radius
364 real(rp) :: cos_lat(np)
365 real(rp) :: veclon_ov_coslat
366
367 integer :: gpu_async_id_
368 !-----------------------------------------------------------------------------
369
370#ifdef _OPENACC
371 if (present(gpu_async_id)) then
372 gpu_async_id_ = gpu_async_id
373 else
374 gpu_async_id_ = acc_async_sync
375 end if
376#endif
377
378 !$acc data create(cos_Lat) present(alpha, beta, gam, VecLon, VecLat, VecAlpha, VecBeta)
379
380 if (present(lat)) then
381 !$omp parallel do
382 !$acc parallel loop async(gpu_async_id_)
383 do p=1, np
384 cos_lat(p) = cos(lat(p))
385 end do
386 end if
387
388 select case( panelid )
389 case( 1, 2, 3, 4 )
390 if (.not. present(lat)) then
391 !$omp parallel do
392 !$acc parallel loop async(gpu_async_id_)
393 do p=1, np
394 cos_lat(p) = cos( atan( tan( beta(p) ) * cos( alpha(p) ) ) )
395 end do
396 end if
397
398 !$omp parallel do private( X, Y, del2, radius, VecLon_ov_cosLat )
399 !$acc parallel loop async(gpu_async_id_)
400 do p=1, np
401 x = tan( alpha(p) )
402 y = tan( beta(p) )
403 del2 = 1.0_rp + x**2 + y**2
404 radius = rplanet * gam(p)
405 veclon_ov_coslat = veclon(p) / cos_lat(p)
406
407 vecalpha(p) = veclon_ov_coslat / radius
408 vecbeta(p) = ( x * y * veclon_ov_coslat + del2 / sqrt( 1.0_rp + x**2 ) * veclat(p) ) &
409 / ( radius * (1.0_rp + y**2) )
410 end do
411 case ( 5 )
412 s = 1.0_rp
413 case ( 6 )
414 s = -1.0_rp
415 case default
416 log_error("CubedSphereCoordCnv_LonLat2CSVec",'(a,i2,a)') "panelID ", panelid, " is invalid. Check!"
417 call prc_abort
418 end select
419
420 select case( panelid )
421 case( 5, 6 )
422 !$omp parallel do private( X, Y, del2, radius, VecLon_ov_cosLat )
423 !$acc parallel loop async(gpu_async_id_)
424 do p=1, np
425 x = tan( alpha(p) )
426 y = tan( beta(p) )
427 del2 = 1.0_rp + x**2 + y**2
428 radius = s * rplanet * gam(p)
429
430 if (.not. present(lat)) then
431 cos_lat(p) = cos( atan( s / sqrt(max(x**2 + y**2, eps)) ) )
432 end if
433 veclon_ov_coslat = veclon(p) / cos_lat(p)
434
435 vecalpha(p) = (- y * veclon_ov_coslat - del2 * x / sqrt( max(del2 - 1.0_rp,eps)) * veclat(p)) &
436 / ( radius * ( 1.0_rp + x**2 ) )
437 vecbeta(p) = ( x * veclon_ov_coslat - del2 * y / sqrt( max(del2 - 1.0_rp,eps)) * veclat(p)) &
438 / ( radius * ( 1.0_rp + y**2 ) )
439 end do
440 end select
441
442 !$acc end data
443
444 return
446
447 !> Calculate the Cartesian coordinates from local coordinates using the central angles in an equiangular gnomonic cubed-sphere projection
448 !!
449!OCL SERIAL
451 panelID, alpha, beta, gam, Np, & ! (in)
452 x, y, z ) ! (out)
453
454 implicit none
455 integer, intent(in) :: panelid !< Panel ID of cubed-sphere coordinates
456 integer, intent(in) :: np !< Array size
457 real(rp), intent(in) :: alpha(np) !< Local coordinate using the central angles [rad]
458 real(rp), intent(in) :: beta (np) !< Local coordinate using the central angles [rad]
459 real(rp), intent(in) :: gam(np) !< A factor of r/a
460 real(rp), intent(out) :: x(np) !< x-coordinate in the Cartesian coordinate
461 real(rp), intent(out) :: y(np) !< y-coordinate in the Cartesian coordinate
462 real(rp), intent(out) :: z(np) !< z-coordinate in the Cartesian coordinate
463
464 integer :: p
465 real(rp) :: x1, x2, fac
466
467 !-----------------------------------------------------------------------------
468
469 select case(panelid)
470 case(1)
471 !$omp parallel do private(x1, x2, fac)
472 !$acc parallel loop present(alpha, beta, gam, X, Y, Z)
473 do p=1, np
474 x1 = tan( alpha(p) )
475 x2 = tan( beta(p) )
476 fac = rplanet * gam(p) / sqrt( 1.0_rp + x1**2 + x2**2 )
477 x(p) = fac
478 y(p) = fac * x1
479 z(p) = fac * x2
480 end do
481 case(2)
482 !$omp parallel do private(x1, x2, fac)
483 !$acc parallel loop present(alpha, beta, gam, X, Y, Z)
484 do p=1, np
485 x1 = tan( alpha(p) )
486 x2 = tan( beta(p) )
487 fac = rplanet * gam(p) / sqrt( 1.0_rp + x1**2 + x2**2 )
488 x(p) = - fac * x1
489 y(p) = fac
490 z(p) = fac * x2
491 end do
492 case(3)
493 !$omp parallel do private(x1, x2, fac)
494 !$acc parallel loop present(alpha, beta, gam, X, Y, Z)
495 do p=1, np
496 x1 = tan( alpha(p) )
497 x2 = tan( beta(p) )
498 fac = rplanet * gam(p) / sqrt( 1.0_rp + x1**2 + x2**2 )
499 x(p) = - fac
500 y(p) = - fac * x1
501 z(p) = fac * x2
502 end do
503 case(4)
504 !$omp parallel do private(x1, x2, fac)
505 !$acc parallel loop present(alpha, beta, gam, X, Y, Z)
506 do p=1, np
507 x1 = tan( alpha(p) )
508 x2 = tan( beta(p) )
509 fac = rplanet * gam(p) / sqrt( 1.0_rp + x1**2 + x2**2 )
510 x(p) = fac * x1
511 y(p) = - fac
512 z(p) = fac * x2
513 end do
514 case(5)
515 !$omp parallel do private(x1, x2, fac)
516 !$acc parallel loop present(alpha, beta, gam, X, Y, Z)
517 do p=1, np
518 x1 = tan( alpha(p) )
519 x2 = tan( beta(p) )
520 fac = rplanet * gam(p) / sqrt( 1.0_rp + x1**2 + x2**2 )
521 x(p) = - fac * x2
522 y(p) = fac * x1
523 z(p) = fac
524 end do
525 case(6)
526 !$omp parallel do private(x1, x2, fac)
527 !$acc parallel loop present(alpha, beta, gam, X, Y, Z)
528 do p=1, np
529 x1 = tan( alpha(p) )
530 x2 = tan( beta(p) )
531 fac = rplanet * gam(p) / sqrt( 1.0_rp + x1**2 + x2**2 )
532 x(p) = fac * x2
533 y(p) = fac * x1
534 z(p) = - fac
535 end do
536 case default
537 log_error("CubedSphereCoordCnv_CS2CartPos",'(a,i2,a)') "panelID ", panelid, " is invalid. Check!"
538 call prc_abort
539 end select
540
541 return
542 end subroutine cubedspherecoordcnv_cs2cartpos
543
544 !> Convert the components of a vector in local coordinates with an equiangular gnomonic cubed-sphere projection to those in the Cartesian coordinates
545 !!
546!OCL SERIAL
548 panelID, alpha, beta, gam, Np, & ! (in)
549 vec_x, vec_y, vec_z, & ! (in)
550 vecalpha, vecbeta ) ! (out)
551
552 implicit none
553
554 integer, intent(in) :: panelid !< Panel ID of cubed-sphere coordinates
555 integer, intent(in) :: np !< Array size
556 real(rp), intent(in) :: alpha(np) !< Local coordinate using the central angles [rad]
557 real(rp), intent(in) :: beta (np) !< Local coordinate using the central angles [rad]
558 real(rp), intent(in) :: gam(np) !< A factor of RPlanet / r
559 real(dp), intent(in) :: vec_x(np) !< A component of vector in the x-coordinate with the Cartesian coordinate
560 real(dp), intent(in) :: vec_y(np) !< A component of vector in the y-coordinate with the Cartesian coordinate
561 real(dp), intent(in) :: vec_z(np) !< A component of vector in the z-coordinate with the Cartesian coordinate
562 real(rp), intent(out) :: vecalpha(np) !< A component of vector in the alpha-coordinate
563 real(rp), intent(out) :: vecbeta (np) !< A component of vector in the beta-coordinate
564
565 integer :: p
566 real(rp) :: x1, x2, fac
567 real(rp) :: r_sec2_alpha, r_sec2_beta
568 !-----------------------------------------------------------------------------
569
570 select case( panelid )
571 case(1)
572 !$omp parallel do private(x1, x2, r_sec2_alpha, r_sec2_beta, fac)
573 !$acc parallel loop present(alpha, beta, gam, Vec_x, Vec_y, Vec_z, VecAlpha, VecBeta)
574 do p=1, np
575 x1 = tan( alpha(p) )
576 x2 = tan( beta(p) )
577 r_sec2_alpha = cos(alpha(p))**2
578 r_sec2_beta = cos(beta(p))**2
579 fac = sqrt( 1.0_rp + x1**2 + x2**2 ) / ( rplanet * gam(p) )
580
581 vecalpha(p) = fac * r_sec2_alpha * ( - x1 * vec_x(p) + vec_y(p) )
582 vecbeta(p) = fac * r_sec2_beta * ( - x2 * vec_x(p) + vec_z(p) )
583 end do
584 case(2)
585 !$omp parallel do private(x1, x2, r_sec2_alpha, r_sec2_beta, fac)
586 !$acc parallel loop present(alpha, beta, gam, Vec_x, Vec_y, Vec_z, VecAlpha, VecBeta)
587 do p=1, np
588 x1 = tan( alpha(p) )
589 x2 = tan( beta(p) )
590 r_sec2_alpha = cos(alpha(p))**2
591 r_sec2_beta = cos(beta(p))**2
592 fac = sqrt( 1.0_rp + x1**2 + x2**2 ) / ( rplanet * gam(p) )
593
594 vecalpha(p) = - fac * r_sec2_alpha * ( vec_x(p) + x1 * vec_y(p) )
595 vecbeta(p) = fac * r_sec2_beta * ( - x2 * vec_y(p) + vec_z(p) )
596 end do
597 case(3)
598 !$omp parallel do private(x1, x2, r_sec2_alpha, r_sec2_beta, fac)
599 !$acc parallel loop present(alpha, beta, gam, Vec_x, Vec_y, Vec_z, VecAlpha, VecBeta)
600 do p=1, np
601 x1 = tan( alpha(p) )
602 x2 = tan( beta(p) )
603 r_sec2_alpha = cos(alpha(p))**2
604 r_sec2_beta = cos(beta(p))**2
605 fac = sqrt( 1.0_rp + x1**2 + x2**2 ) / ( rplanet * gam(p) )
606
607 vecalpha(p) = fac * r_sec2_alpha * ( x1 * vec_x(p) - vec_y(p) )
608 vecbeta(p) = fac * r_sec2_beta * ( x2 * vec_x(p) + vec_z(p) )
609 end do
610 case(4)
611 !$omp parallel do private(x1, x2, r_sec2_alpha, r_sec2_beta, fac)
612 !$acc parallel loop present(alpha, beta, gam, Vec_x, Vec_y, Vec_z, VecAlpha, VecBeta)
613 do p=1, np
614 x1 = tan( alpha(p) )
615 x2 = tan( beta(p) )
616 r_sec2_alpha = cos(alpha(p))**2
617 r_sec2_beta = cos(beta(p))**2
618 fac = sqrt( 1.0_rp + x1**2 + x2**2 ) / ( rplanet * gam(p) )
619
620 vecalpha(p) = fac * r_sec2_alpha * ( vec_x(p) + x1 * vec_y(p) )
621 vecbeta(p) = fac * r_sec2_beta * ( x2 * vec_y(p) + vec_z(p) )
622 end do
623 case ( 5 )
624 !$omp parallel do private(x1, x2, r_sec2_alpha, r_sec2_beta, fac)
625 !$acc parallel loop present(alpha, beta, gam, Vec_x, Vec_y, Vec_z, VecAlpha, VecBeta)
626 do p=1, np
627 x1 = tan( alpha(p) )
628 x2 = tan( beta(p) )
629 r_sec2_alpha = cos(alpha(p))**2
630 r_sec2_beta = cos(beta(p))**2
631 fac = sqrt( 1.0_rp + x1**2 + x2**2 ) / ( rplanet * gam(p) )
632
633 vecalpha(p) = fac * r_sec2_alpha * ( vec_y(p) - x1 * vec_z(p) )
634 vecbeta(p) = - fac * r_sec2_beta * ( vec_x(p) + x2 * vec_z(p) )
635 end do
636 case ( 6 )
637 !$omp parallel do private(x1, x2, r_sec2_alpha, r_sec2_beta, fac)
638 !$acc parallel loop present(alpha, beta, gam, Vec_x, Vec_y, Vec_z, VecAlpha, VecBeta)
639 do p=1, np
640 x1 = tan( alpha(p) )
641 x2 = tan( beta(p) )
642 r_sec2_alpha = cos(alpha(p))**2
643 r_sec2_beta = cos(beta(p))**2
644 fac = sqrt( 1.0_rp + x1**2 + x2**2 ) / ( rplanet * gam(p) )
645
646 vecalpha(p) = fac * r_sec2_alpha * ( vec_y(p) + x1 * vec_z(p) )
647 vecbeta(p) = fac * r_sec2_beta * ( vec_x(p) + x2 * vec_z(p) )
648 end do
649 case default
650 log_error("CubedSphereCoordCnv_Cart2CSVec",'(a,i2,a)') "panelID ", panelid, " is invalid. Check!"
651 call prc_abort
652 end select
653
654 return
655 end subroutine cubedspherecoordcnv_cart2csvec
656
657!OCL SERIAL
658 subroutine cubedspherecoordcnv_cs2localorthvec_alpha_0( &
659 alpha, beta, radius, Np, & ! (in)
660 vecorth1, vecorth2 ) ! (inout)
661
662 implicit none
663
664 integer, intent(in) :: Np
665 real(RP), intent(in) :: alpha(Np)
666 real(RP), intent(in) :: beta (Np)
667 real(RP), intent(in) :: radius(Np)
668 real(RP), intent(inout) :: VecOrth1(Np)
669 real(RP), intent(inout) :: VecOrth2(Np)
670
671 integer :: p
672 real(RP) :: x1, x2, del
673 real(RP) :: fac
674 real(RP) :: tmp
675 !-----------------------------------------------------------------------------
676
677 !$omp parallel do private(x1, x2, del, fac, tmp)
678 !$acc parallel loop present(alpha, beta, radius, VecOrth1, VecOrth2)
679 do p=1, np
680 x1 = tan( alpha(p) )
681 x2 = tan( beta(p) )
682 del = sqrt(1.0_rp + x1**2 + x2**2)
683 fac = radius(p) * sqrt(1.0_rp + x1**2) / del**2
684
685 tmp = vecorth1(p)
686 vecorth1(p) = fac * del * tmp
687 vecorth2(p) = fac * ( - x1 * x2 * tmp + (1.0_rp + x2**2) * vecorth2(p) )
688 end do
689
690 return
691 end subroutine cubedspherecoordcnv_cs2localorthvec_alpha_0
692
693!OCL SERIAL
694 subroutine cubedspherecoordcnv_cs2localorthvec_alpha_1( &
695 alpha, beta, radius, Np, & ! (in)
696 vecalpha, vecbeta, & ! (in)
697 vecorth1, vecorth2 ) ! (out)
698
699 implicit none
700
701 integer, intent(in) :: Np
702 real(RP), intent(in) :: alpha(Np)
703 real(RP), intent(in) :: beta (Np)
704 real(RP), intent(in) :: radius(Np)
705 real(RP), intent(in) :: VecAlpha(Np)
706 real(RP), intent(in) :: VecBeta (Np)
707 real(RP), intent(out) :: VecOrth1(Np)
708 real(RP), intent(out) :: VecOrth2(Np)
709
710 integer :: p
711 !-----------------------------------------------------------------------------
712
713 !$omp parallel do
714 !$acc parallel loop present(VecAlpha, VecBeta, VecOrth1, VecOrth2)
715 do p=1, np
716 vecorth1(p) = vecalpha(p)
717 vecorth2(p) = vecbeta(p)
718 end do
719 !$omp end parallel do
720
721 call cubedspherecoordcnv_cs2localorthvec_alpha_0( &
722 alpha, beta, radius, np, & ! (in)
723 vecorth1, vecorth2 ) ! (inout)
724
725 return
726 end subroutine cubedspherecoordcnv_cs2localorthvec_alpha_1
727
728!OCL SERIAL
729 subroutine cubedspherecoordcnv_localorth2csvec_alpha_0( &
730 alpha, beta, radius, Np, & ! (in)
731 vecalpha, vecbeta ) ! (inout)
732
733 implicit none
734
735 integer, intent(in) :: Np
736 real(RP), intent(in) :: alpha(Np)
737 real(RP), intent(in) :: beta (Np)
738 real(RP), intent(in) :: radius(Np)
739 real(RP), intent(inout) :: VecAlpha(Np)
740 real(RP), intent(inout) :: VecBeta (Np)
741
742 integer :: p
743 real(RP) :: x1, x2, del
744 real(RP) :: fac
745 real(RP) :: tmp
746 !-----------------------------------------------------------------------------
747
748 !$omp parallel do private(x1, x2, del, fac, tmp)
749 !$acc parallel loop present(alpha, beta, radius, VecAlpha, VecBeta)
750 do p=1, np
751 x1 = tan( alpha(p) )
752 x2 = tan( beta(p) )
753 del = sqrt(1.0_rp + x1**2 + x2**2)
754 fac = del / ( radius(p) * ( 1.0_rp + x2**2 ) * sqrt( 1.0_rp + x1**2 ) )
755
756 tmp = vecalpha(p)
757 vecalpha(p) = fac * ( 1.0_rp + x2**2 ) * tmp
758 vecbeta(p) = fac * ( x1 * x2 * tmp + del * vecbeta(p) )
759 end do
760
761 return
762 end subroutine cubedspherecoordcnv_localorth2csvec_alpha_0
763
764!OCL SERIAL
765 subroutine cubedspherecoordcnv_localorth2csvec_alpha_1( &
766 alpha, beta, radius, Np, & ! (in)
767 vecorth1, vecorth2, & ! (in)
768 vecalpha, vecbeta ) ! (out)
769 implicit none
770 integer, intent(in) :: Np
771 real(RP), intent(in) :: alpha(Np)
772 real(RP), intent(in) :: beta (Np)
773 real(RP), intent(in) :: radius(Np)
774 real(RP), intent(in) :: VecOrth1(Np)
775 real(RP), intent(in) :: VecOrth2(Np)
776 real(RP), intent(out) :: VecAlpha(Np)
777 real(RP), intent(out) :: VecBeta (Np)
778
779 integer :: p
780 !-----------------------------------------------------------------------------
781
782 !$omp parallel do
783 !$acc parallel loop present(VecOrth1, VecOrth2, VecAlpha, VecBeta)
784 do p=1, np
785 vecalpha(p) = vecorth1(p)
786 vecbeta(p) = vecorth2(p)
787 end do
788 !$omp end parallel do
789
790 call cubedspherecoordcnv_localorth2csvec_alpha_0( &
791 alpha, beta, radius, np, & ! (in)
792 vecalpha, vecbeta ) ! (inout)
793
794 return
795 end subroutine cubedspherecoordcnv_localorth2csvec_alpha_1
796
797 !> Calculate the metrics associated with an equiangular gnomonic cubed-sphere projection to those in longitude and latitude coordinates
798 !!
799!OCL SERIAL
801 alpha, beta, Np, radius, & ! (in)
802 g_ij, gij, gsqrt ) ! (out)
803
804 implicit none
805
806 integer, intent(in) :: np !< Array size
807 real(rp), intent(in) :: alpha(np) !< Local coordinate using the central angles [rad]
808 real(rp), intent(in) :: beta (np) !< Local coordinate using the central angles [rad]
809 real(rp), intent(in) :: radius !< Planetary radius
810 real(rp), intent(out) :: g_ij(np,2,2) !< Horizontal covariant metric tensor
811 real(rp), intent(out) :: gij (np,2,2) !< Horizontal contravariant metric tensor
812 real(rp), intent(out) :: gsqrt(np) !< Horizontal Jacobian
813
814 real(rp) :: x, y
815 real(rp) :: r2
816 real(rp) :: fac
817 real(rp) :: g_ij_(2,2)
818 real(rp) :: gij_ (2,2)
819
820 integer :: p
821 real(rp) :: oneplusx2, oneplusy2
822 !-----------------------------------------------------------------------------
823
824 !$omp parallel do private( &
825 !$omp X, Y, r2, OnePlusX2, OnePlusY2, fac, &
826 !$omp G_ij_, GIJ_ )
827 !$acc parallel loop private(G_ij_, GIJ_) present(alpha, beta, G_ij, GIJ, Gsqrt)
828 do p=1, np
829 x = tan(alpha(p))
830 y = tan(beta(p))
831 r2 = 1.0_rp + x**2 + y**2
832 oneplusx2 = 1.0_rp + x**2
833 oneplusy2 = 1.0_rp + y**2
834
835 fac = oneplusx2 * oneplusy2 * ( radius / r2 )**2
836 g_ij_(1,1) = fac * oneplusx2
837 g_ij_(1,2) = - fac * (x * y)
838 g_ij_(2,1) = - fac * (x * y)
839 g_ij_(2,2) = fac * oneplusy2
840 g_ij(p,:,:) = g_ij_(:,:)
841
842 gsqrt(p) = radius**2 * oneplusx2 * oneplusy2 / ( r2 * sqrt(r2) )
843
844 fac = 1.0_rp / gsqrt(p)**2
845 gij_(1,1) = fac * g_ij_(2,2)
846 gij_(1,2) = - fac * g_ij_(1,2)
847 gij_(2,1) = - fac * g_ij_(2,1)
848 gij_(2,2) = fac * g_ij_(1,1)
849 gij(p,:,:) = gij_(:,:)
850 end do
851
852 return
853 end subroutine cubedspherecoordcnv_getmetric
854
Module common / Coordinate conversion with cubed-sphere projection.
subroutine, public cubedspherecoordcnv_cs2lonlatpos(panelid, alpha, beta, gam, np, lon, lat)
Calculate longitude and latitude coordinates from local coordinates using the central angles in an eq...
subroutine, public cubedspherecoordcnv_getmetric(alpha, beta, np, radius, g_ij, gij, gsqrt)
Calculate the metrics associated with an equiangular gnomonic cubed-sphere projection to those in lon...
subroutine, public cubedspherecoordcnv_lonlat2csvec(panelid, alpha, beta, gam, np, veclon, veclat, vecalpha, vecbeta, lat, gpu_async_id)
Convert the components of a vector in longitude and latitude coordinates to those in local coordinate...
subroutine, public cubedspherecoordcnv_lonlat2cspos(panelid, lon, lat, np, alpha, beta)
Calculate local coordinates using the central angles in an equiangular gnomonic cubed-sphere projecti...
subroutine, public cubedspherecoordcnv_cart2csvec(panelid, alpha, beta, gam, np, vec_x, vec_y, vec_z, vecalpha, vecbeta)
Convert the components of a vector in local coordinates with an equiangular gnomonic cubed-sphere pro...
subroutine, public cubedspherecoordcnv_cs2lonlatvec(panelid, alpha, beta, gam, np, vecalpha, vecbeta, veclon, veclat, lat, gpu_async_id)
Convert the components of a vector in local coordinates with an equiangular gnomonic cubed-sphere pro...
subroutine, public cubedspherecoordcnv_cs2cartpos(panelid, alpha, beta, gam, np, x, y, z)
Calculate the Cartesian coordinates from local coordinates using the central angles in an equiangular...
Module common / Coordinate conversion with a geographic coordinate.
subroutine, public geographiccoordcnv_orth_to_geo_pos(orth_p, np, geo_p)