@@ -1019,79 +1019,104 @@ end function get_equatorial_latitude
10191019 ! >
10201020 ! > @note For a cubed -sphere mesh, this will only return correct cell IDs if
10211021 ! > the offset cell remains on same the cubed-sphere "face" as the
1022- ! > start cell.
1022+ ! > start cell unless check_orientation is specified .
10231023 ! >
10241024 ! > @param[in] cell_number ID of the anchor element.
10251025 ! > @param[in] x_cells Offset in the E/W direction.
10261026 ! > @param[in] y_cells Offset in the N/S direction.
1027+ ! > @param[in] check_orientation Switch to check for orientation changes
1028+ ! ! such as when crossing panel boundaries
10271029 ! >
10281030 ! > @return cell_id ID of the cell at the given offset to the start cell.
10291031 ! >
10301032 function get_cell_id ( self , cell_number , &
1031- x_cells , y_cells ) result ( cell_id )
1033+ x_cells , y_cells , &
1034+ check_orientation ) result ( cell_id )
10321035
10331036 use reference_element_mod, only : W, S, E, N
10341037
10351038 implicit none
10361039
10371040 class(global_mesh_type), intent (in ) :: self
10381041
1039- integer (i_def), intent (in ) :: cell_number
1040- integer (i_def), intent (in ) :: x_cells, y_cells
1042+ integer (i_def), intent (in ) :: cell_number
1043+ integer (i_def), intent (in ) :: x_cells, y_cells
1044+ logical (l_def), optional , intent (in ) :: check_orientation
10411045
1042- integer (i_def) :: cell_id
1046+ integer (i_def) :: cell_id, old_cell_id
10431047
1044- integer (i_def) :: index_x, dist_x
1045- integer (i_def) :: index_y, dist_y
1046- integer (i_def) :: i
1048+ integer (i_def) :: x_index, y_index, x_dist, y_dist, i, j
1049+ integer (i_def) :: opposite(4 ), rotate(4 )
10471050
1048- cell_id = cell_number
1051+ logical (l_def) :: check
10491052
1050- ! Determine march along local x-axis
1051- if (x_cells > 0 ) then
1052- index_x = E
1053- dist_x = x_cells
1054- else if (x_cells < 0 ) then
1055- index_x = W
1056- dist_x = abs (x_cells)
1053+ opposite = (/ E, N, W, S / )
1054+ rotate = (/ S, E, N, W / )
1055+ if ( present ( check_orientation ) ) then
1056+ check = check_orientation
10571057 else
1058- index_x = W
1059- dist_x = 0
1058+ check = .false.
10601059 end if
10611060
1062- ! Determine march along local y-axis
1063- if (y_cells > 0 ) then
1064- index_y = N
1065- dist_y = y_cells
1066- else if (y_cells < 0 ) then
1067- index_y = S
1068- dist_y = abs (y_cells)
1061+ cell_id= cell_number
1062+
1063+ if (x_cells >= 0 )then
1064+ x_index = E
1065+ x_dist = x_cells
1066+ else
1067+ x_index = W
1068+ x_dist = abs (x_cells)
1069+ end if
1070+ if (y_cells >= 0 )then
1071+ y_index = N
1072+ y_dist = y_cells
10691073 else
1070- index_y = S
1071- dist_y = 0
1074+ y_index = S
1075+ y_dist = abs (y_cells)
10721076 end if
10731077
1074- ! ========================================
1075- ! March from anchor along local x/y axes.
1076- ! ========================================
1077- do i = 1 , dist_x
1078+ ! x_dist cells in the x-direction
1079+ do i = 1 , x_dist
1080+ old_cell_id = cell_id
1081+ cell_id = self % cell_next_2d(x_index,cell_id)
10781082 if (cell_id == self% void_cell) then
10791083 ! The current cell is not on the domain
10801084 write (log_scratch_space,' (A)' ) &
10811085 ' No adjacent cell, the current cell is not on mesh domain'
10821086 call log_event(log_scratch_space, LOG_LEVEL_ERROR)
10831087 end if
1084- cell_id = self% cell_next_2d(index_x, cell_id)
1088+ ! Check if we've changed direction
1089+ if ( check .and. self% cell_next_2d(opposite(x_index),cell_id) /= old_cell_id ) then
1090+ ! We have changed direction so we need to find the correct
1091+ ! index and reset
1092+ do j = 1 ,4
1093+ if ( self% cell_next_2d(opposite(j),cell_id) == old_cell_id ) x_index = j
1094+ end do
1095+ end if
10851096 end do
1086-
1087- do i= 1 , dist_y
1097+ ! y_dist cells in the y-direction
1098+ ! Since the direction may have changed we need to recompute
1099+ y_index = rotate(x_index)
1100+ if ( y_cells < 0 ) y_index = opposite(y_index)
1101+
1102+ ! y_index and y_dist
1103+ do i = 1 ,y_dist
1104+ old_cell_id = cell_id
1105+ cell_id = self% cell_next_2d(y_index,cell_id)
10881106 if (cell_id == self% void_cell) then
10891107 ! The current cell is not on the domain
10901108 write (log_scratch_space,' (A)' ) &
10911109 ' No adjacent cell, the current cell is not on mesh domain'
10921110 call log_event(log_scratch_space, LOG_LEVEL_ERROR)
10931111 end if
1094- cell_id = self% cell_next_2d(index_y, cell_id)
1112+ ! Check if we've changed direction
1113+ if ( check .and. self% cell_next_2d(opposite(y_index),cell_id) /= old_cell_id ) then
1114+ ! We have changed direction so we need to find the correct
1115+ ! index and reset
1116+ do j = 1 ,4
1117+ if ( self% cell_next_2d(opposite(j),cell_id) == old_cell_id ) y_index = j
1118+ end do
1119+ end if
10951120 end do
10961121
10971122 end function get_cell_id
0 commit comments