This subroutine defines and registers four variants of dynamics grids in terms of dynamics decomposition.
Their names are listed in dyn_grid_name
and their corresponding ids can be determined by calling dyn_grid_id
.
* "mpas_cell": Grid that is centered at MPAS "cell" points.
* "cam_cell": Grid that is also centered at MPAS "cell" points but uses standard CAM-SIMA coordinate and dimension names.
* "mpas_edge": Grid that is centered at MPAS "edge" points.
* "mpas_vertex": Grid that is centered at MPAS "vertex" points.
(KCW, 2024-03-28)
Type | Visibility | Attributes | Name | Initial | |||
---|---|---|---|---|---|---|---|
real(kind=kind_dyn_mpas), | private, | pointer | :: | areacell(:) | |||
real(kind=kind_r8), | private, | pointer | :: | cell_area(:) | |||
real(kind=kind_r8), | private, | pointer | :: | cell_weight(:) | |||
integer(kind=kind_imap), | private, | pointer | :: | global_grid_index(:) | |||
integer(kind=kind_imap), | private, | pointer | :: | global_grid_map(:,:) | |||
integer, | private | :: | i | ||||
integer, | private | :: | ierr | ||||
integer, | private, | pointer | :: | indextocellid(:) | |||
integer, | private, | pointer | :: | indextoedgeid(:) | |||
integer, | private, | pointer | :: | indextovertexid(:) | |||
type(horiz_coord_t), | private, | pointer | :: | lat_coord | |||
real(kind=kind_dyn_mpas), | private, | pointer | :: | latcell(:) | |||
real(kind=kind_dyn_mpas), | private, | pointer | :: | latedge(:) | |||
real(kind=kind_dyn_mpas), | private, | pointer | :: | latvertex(:) | |||
type(horiz_coord_t), | private, | pointer | :: | lon_coord | |||
real(kind=kind_dyn_mpas), | private, | pointer | :: | loncell(:) | |||
real(kind=kind_dyn_mpas), | private, | pointer | :: | lonedge(:) | |||
real(kind=kind_dyn_mpas), | private, | pointer | :: | lonvertex(:) | |||
character(len=*), | private, | parameter | :: | subname | = | 'dyn_grid::define_cam_grid' |
subroutine define_cam_grid() ! Module(s) from CAM-SIMA. use cam_abortutils, only: check_allocate use cam_grid_support, only: cam_grid_attribute_register, cam_grid_register, & horiz_coord_create, horiz_coord_t use cam_logfile, only: debugout_debug, debugout_verbose use cam_map_utils, only: kind_imap => imap use dyn_comp, only: dyn_debug_print, mpas_dynamical_core, & ncells_global, nedges_global, nvertices_global, & ncells_solve, nedges_solve, nvertices_solve, & sphere_radius use dynconst, only: constant_pi => pi, rad_to_deg use string_utils, only: stringify ! Module(s) from CESM Share. use shr_kind_mod, only: kind_r8 => shr_kind_r8 ! Module(s) from MPAS. use dyn_mpas_subdriver, only: kind_dyn_mpas => mpas_dynamical_core_real_kind character(*), parameter :: subname = 'dyn_grid::define_cam_grid' integer :: i integer :: ierr integer, pointer :: indextocellid(:) ! Global indexes of cell centers. integer, pointer :: indextoedgeid(:) ! Global indexes of edge nodes. integer, pointer :: indextovertexid(:) ! Global indexes of vertex nodes. real(kind_dyn_mpas), pointer :: areacell(:) ! Cell areas (m2). real(kind_dyn_mpas), pointer :: latcell(:) ! Cell center latitudes (rad). real(kind_dyn_mpas), pointer :: latedge(:) ! Edge node latitudes (rad). real(kind_dyn_mpas), pointer :: latvertex(:) ! Vertex node latitudes (rad). real(kind_dyn_mpas), pointer :: loncell(:) ! Cell center longitudes (rad). real(kind_dyn_mpas), pointer :: lonedge(:) ! Edge node longitudes (rad). real(kind_dyn_mpas), pointer :: lonvertex(:) ! Vertex node longitudes (rad). ! Global grid indexes. CAN be safely deallocated because its values are copied internally by ! `cam_grid_attribute_register` and `horiz_coord_create`. ! `kind_imap` is an integer kind of `PIO_OFFSET_KIND`. integer(kind_imap), pointer :: global_grid_index(:) ! Global grid maps. CANNOT be safely deallocated because `cam_grid_register` ! just uses pointers to point at it internally. ! `kind_imap` is an integer kind of `PIO_OFFSET_KIND`. integer(kind_imap), pointer :: global_grid_map(:, :) ! Cell areas (m2). CANNOT be safely deallocated because `cam_grid_attribute_register` ! just uses pointers to point at it internally. real(kind_r8), pointer :: cell_area(:) ! Cell weights normalized to unity. CANNOT be safely deallocated because `cam_grid_attribute_register` ! just uses pointers to point at it internally. real(kind_r8), pointer :: cell_weight(:) ! Latitude coordinates. CANNOT be safely deallocated because `cam_grid_register` ! just uses pointers to point at it internally. type(horiz_coord_t), pointer :: lat_coord ! Longitude coordinates. CANNOT be safely deallocated because `cam_grid_register` ! just uses pointers to point at it internally. type(horiz_coord_t), pointer :: lon_coord call dyn_debug_print(debugout_debug, subname // ' entered') nullify(indextocellid, indextoedgeid, indextovertexid) nullify(areacell) nullify(latcell, loncell) nullify(latedge, lonedge) nullify(latvertex, lonvertex) nullify(global_grid_index, global_grid_map) nullify(cell_area, cell_weight) nullify(lat_coord, lon_coord) ! Construct coordinate and grid objects for cell center grid (i.e., "mpas_cell"). ! Standard MPAS coordinate and dimension names are used. call mpas_dynamical_core % get_variable_pointer(areacell, 'mesh', 'areaCell') call mpas_dynamical_core % get_variable_pointer(indextocellid, 'mesh', 'indexToCellID') call mpas_dynamical_core % get_variable_pointer(latcell, 'mesh', 'latCell') call mpas_dynamical_core % get_variable_pointer(loncell, 'mesh', 'lonCell') allocate(global_grid_index(ncells_solve), stat=ierr) call check_allocate(ierr, subname, 'global_grid_index(ncells_solve)', 'dyn_grid', __LINE__) global_grid_index(:) = int(indextocellid(1:ncells_solve), kind_imap) lat_coord => horiz_coord_create('latCell', 'nCells', ncells_global, 'latitude', 'degrees_north', & 1, ncells_solve, real(latcell, kind_r8) * rad_to_deg, map=global_grid_index) lon_coord => horiz_coord_create('lonCell', 'nCells', ncells_global, 'longitude', 'degrees_east', & 1, ncells_solve, real(loncell, kind_r8) * rad_to_deg, map=global_grid_index) allocate(cell_area(ncells_solve), stat=ierr) call check_allocate(ierr, subname, 'cell_area(ncells_solve)', 'dyn_grid', __LINE__) allocate(cell_weight(ncells_solve), stat=ierr) call check_allocate(ierr, subname, 'cell_weight(ncells_solve)', 'dyn_grid', __LINE__) allocate(global_grid_map(3, ncells_solve), stat=ierr) call check_allocate(ierr, subname, 'global_grid_map(3, ncells_solve)', 'dyn_grid', __LINE__) do i = 1, ncells_solve cell_area(i) = real(areacell(i), kind_r8) cell_weight(i) = real(areacell(i), kind_r8) / (4.0_kind_r8 * constant_pi * real(sphere_radius, kind_r8) ** 2) global_grid_map(1, i) = int(i, kind_imap) global_grid_map(2, i) = int(1, kind_imap) global_grid_map(3, i) = global_grid_index(i) end do call dyn_debug_print(debugout_verbose, 'Registering dynamics grid "mpas_cell" with id ' // & stringify([dyn_grid_id('mpas_cell')])) call cam_grid_register('mpas_cell', dyn_grid_id('mpas_cell'), lat_coord, lon_coord, global_grid_map, & unstruct=.true., block_indexed=.false.) call cam_grid_attribute_register('mpas_cell', 'cell_area', 'MPAS cell area', 'nCells', cell_area, & map=global_grid_index) call cam_grid_attribute_register('mpas_cell', 'cell_weight', 'MPAS cell weight', 'nCells', cell_weight, & map=global_grid_index) nullify(areacell) nullify(cell_area, cell_weight) nullify(lat_coord, lon_coord) ! Construct coordinate and grid objects for cell center grid (i.e., "cam_cell"). ! Standard CAM-SIMA coordinate and dimension names are used. lat_coord => horiz_coord_create('lat', 'ncol', ncells_global, 'latitude', 'degrees_north', & 1, ncells_solve, real(latcell, kind_r8) * rad_to_deg, map=global_grid_index) lon_coord => horiz_coord_create('lon', 'ncol', ncells_global, 'longitude', 'degrees_east', & 1, ncells_solve, real(loncell, kind_r8) * rad_to_deg, map=global_grid_index) call dyn_debug_print(debugout_verbose, 'Registering dynamics grid "cam_cell" with id ' // & stringify([dyn_grid_id('cam_cell')])) call cam_grid_register('cam_cell', dyn_grid_id('cam_cell'), lat_coord, lon_coord, global_grid_map, & unstruct=.true., block_indexed=.false.) nullify(indextocellid) nullify(latcell, loncell) deallocate(global_grid_index) nullify(global_grid_index, global_grid_map) nullify(lat_coord, lon_coord) ! Construct coordinate and grid objects for edge node grid (i.e., "mpas_edge"). ! Standard MPAS coordinate and dimension names are used. call mpas_dynamical_core % get_variable_pointer(indextoedgeid, 'mesh', 'indexToEdgeID') call mpas_dynamical_core % get_variable_pointer(latedge, 'mesh', 'latEdge') call mpas_dynamical_core % get_variable_pointer(lonedge, 'mesh', 'lonEdge') allocate(global_grid_index(nedges_solve), stat=ierr) call check_allocate(ierr, subname, 'global_grid_index(nedges_solve)', 'dyn_grid', __LINE__) global_grid_index(:) = int(indextoedgeid(1:nedges_solve), kind_imap) lat_coord => horiz_coord_create('latEdge', 'nEdges', nedges_global, 'latitude', 'degrees_north', & 1, nedges_solve, real(latedge, kind_r8) * rad_to_deg, map=global_grid_index) lon_coord => horiz_coord_create('lonEdge', 'nEdges', nedges_global, 'longitude', 'degrees_east', & 1, nedges_solve, real(lonedge, kind_r8) * rad_to_deg, map=global_grid_index) allocate(global_grid_map(3, nedges_solve), stat=ierr) call check_allocate(ierr, subname, 'global_grid_map(3, nedges_solve)', 'dyn_grid', __LINE__) do i = 1, nedges_solve global_grid_map(1, i) = int(i, kind_imap) global_grid_map(2, i) = int(1, kind_imap) global_grid_map(3, i) = global_grid_index(i) end do call dyn_debug_print(debugout_verbose, 'Registering dynamics grid "mpas_edge" with id ' // & stringify([dyn_grid_id('mpas_edge')])) call cam_grid_register('mpas_edge', dyn_grid_id('mpas_edge'), lat_coord, lon_coord, global_grid_map, & unstruct=.true., block_indexed=.false.) nullify(indextoedgeid) nullify(latedge, lonedge) deallocate(global_grid_index) nullify(global_grid_index, global_grid_map) nullify(lat_coord, lon_coord) ! Construct coordinate and grid objects for vertex node grid (i.e., "mpas_vertex"). ! Standard MPAS coordinate and dimension names are used. call mpas_dynamical_core % get_variable_pointer(indextovertexid, 'mesh', 'indexToVertexID') call mpas_dynamical_core % get_variable_pointer(latvertex, 'mesh', 'latVertex') call mpas_dynamical_core % get_variable_pointer(lonvertex, 'mesh', 'lonVertex') allocate(global_grid_index(nvertices_solve), stat=ierr) call check_allocate(ierr, subname, 'global_grid_index(nvertices_solve)', 'dyn_grid', __LINE__) global_grid_index(:) = int(indextovertexid(1:nvertices_solve), kind_imap) lat_coord => horiz_coord_create('latVertex', 'nVertices', nvertices_global, 'latitude', 'degrees_north', & 1, nvertices_solve, real(latvertex, kind_r8) * rad_to_deg, map=global_grid_index) lon_coord => horiz_coord_create('lonVertex', 'nVertices', nvertices_global, 'longitude', 'degrees_east', & 1, nvertices_solve, real(lonvertex, kind_r8) * rad_to_deg, map=global_grid_index) allocate(global_grid_map(3, nvertices_solve), stat=ierr) call check_allocate(ierr, subname, 'global_grid_map(3, nvertices_solve)', 'dyn_grid', __LINE__) do i = 1, nvertices_solve global_grid_map(1, i) = int(i, kind_imap) global_grid_map(2, i) = int(1, kind_imap) global_grid_map(3, i) = global_grid_index(i) end do call dyn_debug_print(debugout_verbose, 'Registering dynamics grid "mpas_vertex" with id ' // & stringify([dyn_grid_id('mpas_vertex')])) call cam_grid_register('mpas_vertex', dyn_grid_id('mpas_vertex'), lat_coord, lon_coord, global_grid_map, & unstruct=.true., block_indexed=.false.) nullify(indextovertexid) nullify(latvertex, lonvertex) deallocate(global_grid_index) nullify(global_grid_index, global_grid_map) nullify(lat_coord, lon_coord) call dyn_debug_print(debugout_debug, subname // ' completed') end subroutine define_cam_grid