1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4 ! This module handles transformations between model grid coordinates and
5 ! latitude-longitude coordinates. The actual transformations are done through
6 ! the map_utils module.
8 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
15 use misc_definitions_module
18 integer, parameter :: MAX_SOURCE_LEVELS = 20
21 integer :: current_nest_number
22 integer :: SOURCE_PROJ = 0
23 ! The following arrays hold values for all available domains
24 ! NOTE: The entries in the arrays for "domain 0" are used for projection
25 ! information of user-specified source data
26 type (proj_info), dimension(-MAX_SOURCE_LEVELS:MAX_DOMAINS) :: proj_stack
28 ! The projection and domain that we have computed constants for
29 integer :: computed_proj = INVALID
30 integer :: computed_domain = INVALID
34 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
35 ! Name: push_source_projection
38 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
39 subroutine push_source_projection(iprojection, user_stand_lon, user_truelat1, user_truelat2, &
40 user_dxkm, user_dykm, user_dlat, user_dlon, user_known_x, &
41 user_known_y, user_known_lat, user_known_lon, &
42 user_pole_lat, user_pole_lon, &
43 user_centerlat, user_centerlon, &
44 user_centeri, user_centerj, &
50 integer, intent(in) :: iprojection
51 real, intent(in) :: user_stand_lon, user_truelat1, user_truelat2, user_dxkm, user_dykm, &
52 user_dlat, user_dlon, &
53 user_known_x, user_known_y, user_known_lat, user_known_lon
54 real, intent(in), optional :: earth_radius
55 real, intent(in), optional :: user_centerlon, user_centerlat, user_pole_lat, user_pole_lon
56 real, intent(in), optional :: user_centerj, user_centeri
59 SOURCE_PROJ = SOURCE_PROJ-1
60 if (SOURCE_PROJ < -MAX_SOURCE_LEVELS) then
61 call mprintf(.true.,ERROR,'In push_user_projection(), too many levels of user projections.')
64 call map_init(proj_stack(SOURCE_PROJ))
66 if (iprojection == PROJ_LATLON) then
67 call map_set(iprojection, proj_stack(SOURCE_PROJ), &
68 lat1=user_known_lat, &
69 lon1=user_known_lon, &
70 knowni=user_known_x, &
71 knownj=user_known_y, &
72 nxmax=nint(360.0 / user_dlon), &
77 else if (iprojection == PROJ_MERC) then
78 call map_set(iprojection, proj_stack(SOURCE_PROJ), &
79 truelat1=user_truelat1, &
80 lat1=user_known_lat, &
81 lon1=user_known_lon, &
82 knowni=user_known_x, &
83 knownj=user_known_y, &
87 else if (iprojection == PROJ_CYL) then
88 call mprintf(.true.,ERROR,'Should not have PROJ_CYL as projection for ' &
89 //'source data in push_source_projection()')
91 else if (iprojection == PROJ_CASSINI) then
93 call map_set(iprojection, proj_stack(SOURCE_PROJ), &
96 stdlon=user_stand_lon, &
97 lat1=user_centerlat, &
98 lon1=user_centerlon, &
100 lon0=user_pole_lon, &
101 knowni=user_centeri, &
102 knownj=user_centerj, &
103 r_earth=earth_radius)
105 else if (iprojection == PROJ_LC) then
106 call map_set(iprojection, proj_stack(SOURCE_PROJ), &
107 truelat1=user_truelat1, &
108 truelat2=user_truelat2, &
109 stdlon=user_stand_lon, &
110 lat1=user_known_lat, &
111 lon1=user_known_lon, &
112 knowni=user_known_x, &
113 knownj=user_known_y, &
115 r_earth=earth_radius)
117 else if (iprojection == PROJ_ALBERS_NAD83) then
118 call map_set(iprojection, proj_stack(SOURCE_PROJ), &
119 truelat1=user_truelat1, &
120 truelat2=user_truelat2, &
121 stdlon=user_stand_lon, &
122 lat1=user_known_lat, &
123 lon1=user_known_lon, &
124 knowni=user_known_x, &
125 knownj=user_known_y, &
127 r_earth=earth_radius)
129 else if (iprojection == PROJ_PS) then
130 call map_set(iprojection, proj_stack(SOURCE_PROJ), &
131 truelat1=user_truelat1, &
132 stdlon=user_stand_lon, &
133 lat1=user_known_lat, &
134 lon1=user_known_lon, &
135 knowni=user_known_x, &
136 knownj=user_known_y, &
138 r_earth=earth_radius)
140 else if (iprojection == PROJ_PS_WGS84) then
141 call map_set(iprojection, proj_stack(SOURCE_PROJ), &
142 truelat1=user_truelat1, &
143 stdlon=user_stand_lon, &
144 lat1=user_known_lat, &
145 lon1=user_known_lon, &
146 knowni=user_known_x, &
147 knownj=user_known_y, &
149 r_earth=earth_radius)
151 else if (iprojection == PROJ_GAUSS) then
152 call map_set(iprojection, proj_stack(SOURCE_PROJ), &
153 lat1=user_known_lat, &
154 lon1=user_known_lon, &
155 nxmax=nint(360.0 / user_dlon), &
156 nlat=nint(user_dlat), &
158 r_earth=earth_radius)
160 else if (iprojection == PROJ_ROTLL) then
161 ! BUG: Implement this projection.
165 end subroutine push_source_projection
168 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
169 ! Name: pop_source_projection
172 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
173 subroutine pop_source_projection()
177 SOURCE_PROJ = SOURCE_PROJ+1
179 call mprintf((SOURCE_PROJ > 0), ERROR, &
180 'In pop_user_projection(), projection stack has overflowed.')
182 end subroutine pop_source_projection
186 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
187 ! Name: set_domain_projection
190 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
191 subroutine set_domain_projection(iprojection, user_stand_lon, user_truelat1, user_truelat2, &
192 user_dxkm, user_dykm, user_dlat, user_dlon, &
193 user_xdim, user_ydim, user_known_x, &
194 user_known_y, user_known_lat, user_known_lon, &
195 user_pole_lat, user_pole_lon, earth_radius)
200 integer, intent(in) :: iprojection
201 integer, intent(in) :: user_xdim, user_ydim
202 real, intent(in) :: user_stand_lon, user_truelat1, user_truelat2, &
203 user_dxkm, user_dykm, user_dlat, user_dlon, &
204 user_known_x, user_known_y, user_known_lat, user_known_lon, &
205 user_pole_lat, user_pole_lon
206 real, intent(in), optional :: earth_radius
208 current_nest_number = 1
210 call map_init(proj_stack(current_nest_number))
212 if (iprojection == PROJ_LATLON) then
213 call map_set(iprojection, proj_stack(current_nest_number), &
214 lat1=user_known_lat, &
215 lon1=user_known_lon, &
218 r_earth=earth_radius)
220 else if (iprojection == PROJ_MERC) then
221 call map_set(iprojection, proj_stack(current_nest_number), &
222 truelat1=user_truelat1, &
223 lat1=user_known_lat, &
224 lon1=user_known_lon, &
225 knowni=user_known_x, &
226 knownj=user_known_y, &
228 r_earth=earth_radius)
230 else if (iprojection == PROJ_CYL) then
231 call map_set(iprojection, proj_stack(current_nest_number), &
234 stdlon=user_stand_lon, &
235 r_earth=earth_radius)
237 else if (iprojection == PROJ_CASSINI) then
238 call map_set(iprojection, proj_stack(current_nest_number), &
243 stdlon=user_stand_lon, &
244 lat1=user_known_lat, &
245 lon1=user_known_lon, &
246 lat0=user_pole_lat, &
247 lon0=user_pole_lon, &
248 knowni=user_known_x, &
249 knownj=user_known_y, &
250 r_earth=earth_radius)
252 else if (iprojection == PROJ_LC) then
253 call map_set(iprojection, proj_stack(current_nest_number), &
254 truelat1=user_truelat1, &
255 truelat2=user_truelat2, &
256 stdlon=user_stand_lon, &
257 lat1=user_known_lat, &
258 lon1=user_known_lon, &
259 knowni=user_known_x, &
260 knownj=user_known_y, &
262 r_earth=earth_radius)
264 else if (iprojection == PROJ_ALBERS_NAD83) then
265 call map_set(iprojection, proj_stack(current_nest_number), &
266 truelat1=user_truelat1, &
267 truelat2=user_truelat2, &
268 stdlon=user_stand_lon, &
269 lat1=user_known_lat, &
270 lon1=user_known_lon, &
271 knowni=user_known_x, &
272 knownj=user_known_y, &
274 r_earth=earth_radius)
276 else if (iprojection == PROJ_PS) then
277 call map_set(iprojection, proj_stack(current_nest_number), &
278 truelat1=user_truelat1, &
279 stdlon=user_stand_lon, &
280 lat1=user_known_lat, &
281 lon1=user_known_lon, &
282 knowni=user_known_x, &
283 knownj=user_known_y, &
285 r_earth=earth_radius)
287 else if (iprojection == PROJ_PS_WGS84) then
288 call map_set(iprojection, proj_stack(current_nest_number), &
289 truelat1=user_truelat1, &
290 stdlon=user_stand_lon, &
291 lat1=user_known_lat, &
292 lon1=user_known_lon, &
293 knowni=user_known_x, &
294 knownj=user_known_y, &
297 else if (iprojection == PROJ_GAUSS) then
298 call map_set(iprojection, proj_stack(current_nest_number), &
299 lat1=user_known_lat, &
300 lon1=user_known_lon, &
301 nlat=nint(user_dlat), &
303 r_earth=earth_radius)
305 else if (iprojection == PROJ_ROTLL) then
306 call map_set(iprojection, proj_stack(current_nest_number), &
311 lat1=user_known_lat, &
312 lon1=user_known_lon, &
316 r_earth=earth_radius)
320 end subroutine set_domain_projection
325 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
326 ! Name: compute_nest_locations
328 ! Purpose: This routine computes the variables necessary in determining the
329 ! location of all nests without reference to the parent or coarse domains.
330 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
331 subroutine compute_nest_locations()
337 real :: temp_known_x, temp_known_y, temp_known_lat, temp_known_lon, &
338 temp_dxkm, temp_dykm, temp_dlat, temp_dlon
340 ! Set location of coarse/mother domain
341 call map_init(proj_stack(1))
343 if (iproj_type == PROJ_LATLON) then
344 call map_set(iproj_type, proj_stack(1), &
350 else if (iproj_type == PROJ_MERC) then
351 call map_set(iproj_type, proj_stack(1), &
359 else if (iproj_type == PROJ_CYL) then
360 call map_set(iproj_type, proj_stack(1), &
365 else if (iproj_type == PROJ_CASSINI) then
366 call map_set(iproj_type, proj_stack(1), &
379 else if (iproj_type == PROJ_LC) then
380 call map_set(iproj_type, proj_stack(1), &
390 else if (iproj_type == PROJ_ALBERS_NAD83) then
391 call map_set(iproj_type, proj_stack(1), &
401 else if (iproj_type == PROJ_PS) then
402 call map_set(iproj_type, proj_stack(1), &
411 else if (iproj_type == PROJ_PS_WGS84) then
412 call map_set(iproj_type, proj_stack(1), &
421 else if (iproj_type == PROJ_GAUSS) then
422 call map_set(iproj_type, proj_stack(current_nest_number), &
428 else if (iproj_type == PROJ_ROTLL) then
429 call map_set(iproj_type, proj_stack(1), &
442 ! Now we can compute lat/lon <-> x/y for coarse domain
443 call select_domain(1)
445 ! Call a recursive procedure to find the lat/lon of the centerpoint for
449 temp_known_x = real(ixdim(i))/2.
450 temp_known_y = real(jydim(i))/2.
452 call find_known_latlon(i, temp_known_x, temp_known_y, &
453 temp_known_lat, temp_known_lon, &
454 temp_dxkm, temp_dykm, temp_dlat, temp_dlon)
456 if (iproj_type == PROJ_LATLON) then
457 call map_set(iproj_type, proj_stack(i), &
458 lat1=temp_known_lat, &
459 lon1=temp_known_lon, &
463 else if (iproj_type == PROJ_MERC) then
464 call map_set(iproj_type, proj_stack(i), &
466 lat1=temp_known_lat, &
467 lon1=temp_known_lon, &
468 knowni=temp_known_x, &
469 knownj=temp_known_y, &
472 else if (iproj_type == PROJ_CYL) then
473 call mprintf(.true.,ERROR,'Don''t know how to do nesting with PROJ_CYL ' &
474 //'in compute_nest_locations()')
476 else if (iproj_type == PROJ_CASSINI) then
477 call map_set(iproj_type, proj_stack(i), &
483 knowni=temp_known_x, &
484 knownj=temp_known_y, &
487 lat1=temp_known_lat, &
490 else if (iproj_type == PROJ_LC) then
491 call map_set(iproj_type, proj_stack(i), &
495 lat1=temp_known_lat, &
496 lon1=temp_known_lon, &
497 knowni=temp_known_x, &
498 knownj=temp_known_y, &
501 else if (iproj_type == PROJ_ALBERS_NAD83) then
502 call map_set(iproj_type, proj_stack(i), &
506 lat1=temp_known_lat, &
507 lon1=temp_known_lon, &
508 knowni=temp_known_x, &
509 knownj=temp_known_y, &
512 else if (iproj_type == PROJ_PS) then
513 call map_set(iproj_type, proj_stack(i), &
516 lat1=temp_known_lat, &
517 lon1=temp_known_lon, &
518 knowni=temp_known_x, &
519 knownj=temp_known_y, &
522 else if (iproj_type == PROJ_PS_WGS84) then
523 call map_set(iproj_type, proj_stack(i), &
526 lat1=temp_known_lat, &
527 lon1=temp_known_lon, &
528 knowni=temp_known_x, &
529 knownj=temp_known_y, &
532 else if (iproj_type == PROJ_GAUSS) then
533 call map_set(iproj_type, proj_stack(current_nest_number), &
534 lat1=temp_known_lat, &
535 lon1=temp_known_lon, &
536 nlat=nint(temp_dykm), &
539 else if (iproj_type == PROJ_ROTLL) then
540 ! BUG: Implement this projection.
546 end subroutine compute_nest_locations
549 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
550 ! Name: find_known_latlon
552 ! Purpose: This recursive routine computes the latitude and longitude for a
553 ! specified x/y location in the given nest number, and also computes the
556 ! NOTE: This routine assumes that xytoll will work correctly for the
558 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
559 recursive subroutine find_known_latlon(n, rx, ry, rlat, rlon, dx, dy, dlat, dlon)
564 integer, intent(in) :: n
565 real, intent(in) :: rx, ry
566 real, intent(out) :: rlat, rlon, dx, dy, dlat, dlon
569 real :: x_in_parent, y_in_parent
571 if (n == 1) then ! Stopping case for the recursion
577 call ij_to_latlon(proj_stack(current_nest_number), rx, ry, rlat, rlon)
581 else ! Recursive case
583 x_in_parent = (rx - ((parent_grid_ratio(n)+1.)/2.)) &
584 / parent_grid_ratio(n) + parent_ll_x(n)
585 y_in_parent = (ry - ((parent_grid_ratio(n)+1.)/2.)) &
586 / parent_grid_ratio(n) + parent_ll_y(n)
588 call find_known_latlon(parent_id(n), x_in_parent, y_in_parent, rlat, rlon, dx, dy, dlat, dlon)
590 dx = dx / parent_grid_ratio(n)
591 dy = dy / parent_grid_ratio(n)
592 dlat = dlat / parent_grid_ratio(n)
593 dlon = dlon / parent_grid_ratio(n)
596 end subroutine find_known_latlon
599 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
600 ! Name: compute_nest_level_info
602 ! Purpose: This routine computes the parameters describing a nesting level for
604 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
605 subroutine compute_nest_level_info()
610 integer :: i, nest_level, temp
611 type (list) :: level_list
613 call list_init(level_list)
615 ! Set location of coarse/mother domain
616 call map_init(proj_stack(1))
618 call map_set(PROJ_ROTLL, proj_stack(1), &
629 parent_ur_x(1) = real(ixdim(1))
630 parent_ur_y(1) = real(jydim(1))
634 nest_level = get_nest_level(i)
636 if (.not. list_search(level_list, ikey=nest_level, ivalue=temp)) then
638 call list_insert(level_list, ikey=nest_level, ivalue=nest_level)
640 ixdim(nest_level) = ixdim(1)*(3**(nest_level-1))-(3**(nest_level-1)-1)
641 jydim(nest_level) = jydim(1)*(3**(nest_level-1))-(3**(nest_level-1)-1)
643 parent_ur_x(nest_level) = ixdim(nest_level)
644 parent_ur_y(nest_level) = jydim(nest_level)
646 call map_set(PROJ_ROTLL, proj_stack(nest_level), &
647 ixdim = ixdim(nest_level), &
648 jydim = jydim(nest_level), &
653 latinc=(dykm/real((3**(nest_level-1)))), &
654 loninc=(dxkm/real((3**(nest_level-1)))), &
660 call list_destroy(level_list)
662 end subroutine compute_nest_level_info
665 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
666 ! Name: get_domain_resolution
669 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
670 subroutine get_domain_resolution(dom_dx, dom_dy)
675 real, intent(out) :: dom_dx, dom_dy
677 ! The proj_info structure only stores dx, so set both dom_dx and dom_dy to dx
678 dom_dx = proj_stack(current_nest_number)%dx
679 dom_dy = proj_stack(current_nest_number)%dx
681 end subroutine get_domain_resolution
684 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
685 ! Name: get_nest_level
687 ! Purpose: This function returns, given a grid ID number, the nesting level of
688 ! that domain; the coarse domain is taken to have nesting level 1.
689 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
690 function get_nest_level(i)
695 integer, intent(in) :: i
701 integer :: get_nest_level
703 ! If argument is the coarse domain, return
709 if (i > MAX_DOMAINS) then
710 call mprintf(.true., ERROR, &
711 'get_nest_level() called with invalid grid ID of %i.',i1=i)
714 ! If not the coarse domain, then nesting level is at least 2
715 ! Yes, this looks silly. But we do not have a grid_id array, so
716 ! we must check on parent_id
720 do while (parent_id(j) /= 1)
722 get_nest_level = get_nest_level + 1
725 if (get_nest_level > MAX_DOMAINS) then
726 call mprintf(.true., ERROR, &
727 'Spooky nesting setup encountered in get_nest_level().')
731 end function get_nest_level
735 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
736 ! Name: select_domain
738 ! Purpose: This routine is used to select which nest x/y <-> lat/lon
739 ! conversions will be with respect to. For example, selecting domain 2 will
740 ! cause the llxy routine to compute x/y locations with respect to domain 2
742 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
743 subroutine select_domain(domain_num)
748 integer, intent(in) :: domain_num
751 if (domain_num > n_domains) then
752 call mprintf(.true.,ERROR,'In select_domain(), selected domain is greater than n_domains.')
756 if (domain_num > 1) then
757 call mprintf(.true.,ERROR,'In select_domain(), selected domain is greater than 1.')
761 current_nest_number = domain_num
763 end subroutine select_domain
766 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
767 ! Name: iget_selected_domain
769 ! Purpose: This function returns the number of the currently selected nest.
770 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
771 function iget_selected_domain()
776 integer :: iget_selected_domain
778 iget_selected_domain = current_nest_number
780 end function iget_selected_domain
783 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
787 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
788 subroutine lltoxy(xlat, xlon, x, y, stagger, comp_ll)
793 integer, intent(in) :: stagger
794 real, intent(in) :: xlat, xlon
795 real, intent(out) :: x, y
796 logical, optional, intent(in) :: comp_ll
799 logical :: save_comp_ll
801 ! Account for grid staggering
802 if (stagger == HH) then
803 proj_stack(current_nest_number)%stagger = HH
804 else if (stagger == VV) then
805 proj_stack(current_nest_number)%stagger = VV
808 if (present(comp_ll)) then
809 save_comp_ll = proj_stack(current_nest_number)%comp_ll
810 proj_stack(current_nest_number)%comp_ll = comp_ll
813 call latlon_to_ij(proj_stack(current_nest_number), xlat, xlon, x, y)
815 if (present(comp_ll)) then
816 proj_stack(current_nest_number)%comp_ll = save_comp_ll
819 ! Account for grid staggering
820 if (stagger == U) then
822 else if (stagger == V) then
824 else if (stagger == CORNER) then
829 end subroutine lltoxy
832 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
836 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
837 subroutine xytoll(x, y, xlat, xlon, stagger, comp_ll)
842 integer, intent(in) :: stagger
843 real, intent(in) :: x, y
844 real, intent(out) :: xlat, xlon
845 logical, optional, intent(in) :: comp_ll
849 logical :: save_comp_ll
851 ! Account for grid staggering; we cannot modify x and y, so modify local
853 if (stagger == U) then
856 else if (stagger == V) then
859 else if (stagger == HH) then
860 proj_stack(current_nest_number)%stagger = HH
863 else if (stagger == VV) then
864 proj_stack(current_nest_number)%stagger = VV
867 else if (stagger == CORNER) then
868 proj_stack(current_nest_number)%stagger = CORNER
876 if (present(comp_ll)) then
877 save_comp_ll = proj_stack(current_nest_number)%comp_ll
878 proj_stack(current_nest_number)%comp_ll = comp_ll
881 call ij_to_latlon(proj_stack(current_nest_number), rx, ry, xlat, xlon)
883 if (present(comp_ll)) then
884 proj_stack(current_nest_number)%comp_ll = save_comp_ll
887 end subroutine xytoll
889 end module llxy_module