Line data Source code
1 : module phys_grid
2 :
3 : !------------------------------------------------------------------------------
4 : !
5 : ! The phys_grid module represents the CAM physics decomposition.
6 : !
7 : ! phys_grid_init receives the physics column info (area, weight, centers)
8 : ! from the dycore.
9 : ! The routine then creates the physics decomposition which
10 : ! is the arrangement of columns across the atmosphere model's
11 : ! MPI tasks as well as the arrangement into groups to
12 : ! facilitate efficient threading.
13 : ! The routine then creates a grid object to allow for data
14 : ! to be read into and written from this decomposition.
15 : ! The phys_grid module also provides interfaces for retrieving information
16 : ! about the decomposition
17 : !
18 : ! Note: This current implementation does not perform load balancing,
19 : ! physics columns ae always on the same task as the corresponding
20 : ! column received from the dycore.
21 : !
22 : !------------------------------------------------------------------------------
23 : use shr_kind_mod, only: r8 => shr_kind_r8
24 : use ppgrid, only: begchunk, endchunk, pver, pverp, pcols
25 : use physics_column_type, only: physics_column_t
26 : use perf_mod, only: t_adj_detailf, t_startf, t_stopf
27 :
28 : implicit none
29 : private
30 : save
31 :
32 : !!XXgoldyXX: v This needs to be removed to complete the weak scaling transition.
33 : public :: SCATTER_FIELD_TO_CHUNK
34 : !!XXgoldyXX: ^ This needs to be removed to complete the weak scaling transition.
35 :
36 : ! Physics grid management
37 : public :: phys_grid_init ! initialize the physics grid
38 : public :: phys_grid_readnl ! Read the phys_grid_nl namelist
39 : public :: phys_grid_initialized
40 : ! Local task interfaces
41 : public :: get_nlcols_p ! Number of local columns
42 : public :: get_area_p ! area of a physics column in radians squared
43 : public :: get_wght_p ! weight of a physics column in radians squared
44 : public :: get_rlat_p ! latitude of a physics column in radians
45 : public :: get_rlon_p ! longitude of a physics column in radians
46 : public :: get_rlat_all_p ! latitudes of physics cols in chunk (radians)
47 : public :: get_rlon_all_p ! longitudes of physics cols in chunk (radians)
48 : public :: get_lat_p ! latitude of a physics column in degrees
49 : public :: get_lon_p ! longitude of a physics column in degrees
50 : public :: get_lat_all_p ! latitudes of physics cols in chunk (degrees)
51 : public :: get_lon_all_p ! longitudes of physics cols in chunk (degrees)
52 : public :: get_area_all_p ! areas of physics cols in chunk
53 : public :: get_wght_all_p ! weights of physics cols in chunk
54 : public :: get_ncols_p ! number of columns in a chunk
55 : public :: get_gcol_p ! global column index of a physics column
56 : public :: get_gcol_all_p ! global col index of all phys cols in a chunk
57 : public :: get_dyn_col_p ! dynamics local blk number and blk offset(s)
58 : public :: get_chunk_info_p ! chunk index and col # of a physics column
59 : public :: get_grid_dims ! return grid dimensions
60 : ! Physics-dynamics coupling
61 : public :: phys_decomp_to_dyn ! Transfer physics data to dynamics decomp
62 : public :: dyn_decomp_to_phys ! Transfer dynamics data to physics decomp
63 :
64 : ! The identifier for the physics grid
65 : integer, parameter, public :: phys_decomp = 100
66 : integer, parameter, public :: phys_decomp_scm = 200
67 :
68 : !! PUBLIC TYPES
69 :
70 : ! Physics chunking (thread blocking) data
71 : ! Note that chunks cover local data
72 : type, public :: chunk
73 : integer, private :: ncols = 1 ! # of grid columns in this chunk
74 : integer, private :: chunk_index = -1 ! Local index of this chunk
75 : integer, private, allocatable :: phys_cols(:) ! phys column indices
76 : end type chunk
77 :
78 : !! PRIVATE DATA
79 :
80 : ! dynamics field grid information
81 : ! hdim1_d and hdim2_d are dimensions of rectangular horizontal grid
82 : ! data structure, If 1D data structure, then hdim2_d == 1.
83 : integer :: hdim1_d, hdim2_d
84 :
85 : ! Physics decomposition information
86 : type(physics_column_t), allocatable :: phys_columns(:)
87 :
88 : type(chunk), private, pointer :: chunks(:) => NULL() ! (begchunk:endchunk)
89 :
90 : logical :: phys_grid_set = .false.
91 :
92 : logical :: calc_memory_increase = .false.
93 :
94 : interface get_dyn_col_p
95 : module procedure :: get_dyn_col_p_chunk
96 : module procedure :: get_dyn_col_p_index
97 : end interface get_dyn_col_p
98 :
99 : ! Private interfaces
100 : private :: chunk_info_to_index_p
101 :
102 : !!XXgoldyXX: v temporary interface to allow old code to compile
103 : interface get_lat_all_p
104 : module procedure :: get_lat_all_p_r8 ! The new version
105 : module procedure :: get_lat_all_p_int ! calls endun
106 : end interface get_lat_all_p
107 :
108 : interface get_lon_all_p
109 : module procedure :: get_lon_all_p_r8 ! The new version
110 : module procedure :: get_lon_all_p_int ! calls endun
111 : end interface get_lon_all_p
112 : !!XXgoldyXX: ^ temporary interface to allow old code to compile
113 :
114 : integer, protected, public :: num_global_phys_cols = 0
115 : integer, protected, public :: columns_on_task = 0
116 : integer, protected, public :: index_top_layer = 0
117 : integer, protected, public :: index_bottom_layer = 0
118 : integer, protected, public :: index_top_interface = 1
119 : integer, protected, public :: index_bottom_interface = 0
120 : integer, public :: phys_columns_on_task = 0
121 :
122 : !==============================================================================
123 : CONTAINS
124 : !==============================================================================
125 :
126 1536 : subroutine phys_grid_readnl(nlfile)
127 : use cam_abortutils, only: endrun
128 : use namelist_utils, only: find_group_name
129 : use cam_logfile, only: iulog
130 : use spmd_utils, only: mpicom, mstrid=>masterprocid, masterproc
131 : use spmd_utils, only: mpi_integer
132 :
133 : character(len=*), intent(in) :: nlfile
134 :
135 : ! Local variables
136 : integer :: unitn, ierr
137 : character(len=*), parameter :: sub = 'phys_grid_readnl'
138 :
139 : integer :: phys_alltoall = -HUGE(1)
140 : integer :: phys_loadbalance = -HUGE(1)
141 : integer :: phys_twin_algorithm = -HUGE(1)
142 : integer :: phys_chnk_per_thd = -HUGE(1)
143 :
144 : namelist /phys_grid_nl/ phys_alltoall, phys_loadbalance, &
145 : phys_twin_algorithm, phys_chnk_per_thd
146 : !------------------------------------------------------------------------
147 :
148 : ! Read namelist
149 1536 : if (masterproc) then
150 2 : open(newunit=unitn, file=trim(nlfile), status='old')
151 2 : call find_group_name(unitn, 'phys_grid_nl', status=ierr)
152 2 : if (ierr == 0) then
153 0 : read(unitn, phys_grid_nl, iostat=ierr)
154 0 : if (ierr /= 0) then
155 0 : call endrun(sub//': FATAL: reading namelist')
156 : end if
157 : end if
158 2 : close(unitn)
159 : end if
160 :
161 1536 : call mpi_bcast(phys_alltoall, 1, mpi_integer, mstrid, mpicom, ierr)
162 1536 : call mpi_bcast(phys_loadbalance, 1, mpi_integer, mstrid, mpicom, ierr)
163 1536 : call mpi_bcast(phys_twin_algorithm, 1, mpi_integer, mstrid, mpicom, ierr)
164 1536 : call mpi_bcast(phys_chnk_per_thd, 1, mpi_integer, mstrid, mpicom, ierr)
165 :
166 1536 : if (masterproc) then
167 2 : write(iulog,*) 'PHYS_GRID options:'
168 2 : write(iulog,*) ' Using PCOLS =', pcols
169 2 : write(iulog,*) ' phys_loadbalance = (not used)'
170 2 : write(iulog,*) ' phys_twin_algorithm = (not used)'
171 2 : write(iulog,*) ' phys_alltoall = (not used)'
172 2 : write(iulog,*) ' chunks_per_thread = (not used)'
173 : end if
174 :
175 1536 : end subroutine phys_grid_readnl
176 :
177 : !========================================================================
178 :
179 1536 : subroutine phys_grid_init()
180 : use mpi, only: MPI_INTEGER, MPI_REAL8, MPI_MIN, MPI_MAX
181 : use shr_mem_mod, only: shr_mem_getusage
182 : use cam_abortutils, only: endrun
183 : use cam_logfile, only: iulog
184 : use spmd_utils, only: npes, mpicom, masterprocid, masterproc, iam
185 : use dyn_grid, only: get_dyn_grid_info, physgrid_copy_attributes_d
186 : use cam_grid_support, only: cam_grid_register, cam_grid_attribute_register
187 : use cam_grid_support, only: iMap, hclen => max_hcoordname_len
188 : use cam_grid_support, only: horiz_coord_t, horiz_coord_create
189 : use cam_grid_support, only: cam_grid_attribute_copy, cam_grid_attr_exists
190 : use shr_const_mod, only: PI => SHR_CONST_PI
191 : use scamMod, only: scmlon,scmlat,single_column,closeioplatidx,closeioplonidx
192 :
193 : ! Local variables
194 : integer :: index
195 : integer :: col_index, phys_col
196 : integer :: ichnk, icol, ncol, gcol
197 : integer :: num_chunks
198 1536 : type(physics_column_t), allocatable :: dyn_columns(:) ! Dyn decomp
199 : ! Maps and values for physics grid
200 1536 : real(r8), pointer :: lonvals(:)
201 1536 : real(r8), pointer :: latvals(:)
202 : real(r8) :: lonmin, latmin
203 1536 : integer(iMap), pointer :: grid_map(:,:)
204 1536 : integer(iMap), pointer :: grid_map_scm(:,:)
205 1536 : integer(iMap), allocatable :: coord_map(:)
206 : type(horiz_coord_t), pointer :: lat_coord
207 : type(horiz_coord_t), pointer :: lon_coord
208 1536 : real(r8), pointer :: area_d(:)
209 1536 : real(r8), pointer :: areawt_d(:)
210 : real(r8) :: mem_hw_beg, mem_hw_end
211 : real(r8) :: mem_beg, mem_end
212 : logical :: unstructured
213 : real(r8) :: temp ! For MPI
214 : integer :: ierr ! For MPI
215 1536 : character(len=hclen), pointer :: copy_attributes(:)
216 : character(len=hclen) :: copy_gridname
217 : character(len=*), parameter :: subname = 'phys_grid_init: '
218 : real(r8), parameter :: rarea_sphere = 1.0_r8 / (4.0_r8*PI)
219 1536 : real (r8), allocatable :: dynlats(:),dynlons(:),pos_dynlons(:)
220 : real (r8) :: pos_scmlon,minpoint,testpoint
221 : integer :: scm_col_index, i, num_lev
222 :
223 1536 : nullify(lonvals)
224 1536 : nullify(latvals)
225 1536 : nullify(grid_map)
226 0 : if (single_column) nullify(grid_map_scm)
227 1536 : nullify(lat_coord)
228 1536 : nullify(lon_coord)
229 1536 : nullify(area_d)
230 1536 : nullify(areawt_d)
231 1536 : nullify(copy_attributes)
232 :
233 1536 : if (calc_memory_increase) then
234 0 : call shr_mem_getusage(mem_hw_beg, mem_beg)
235 : end if
236 :
237 1536 : call t_adj_detailf(-2)
238 1536 : call t_startf("phys_grid_init")
239 :
240 : ! Gather info from the dycore
241 : call get_dyn_grid_info(hdim1_d, hdim2_d, num_lev, index_top_layer, &
242 1536 : index_bottom_layer, unstructured, dyn_columns)
243 :
244 : ! Set up the physics decomposition
245 1536 : columns_on_task = size(dyn_columns)
246 :
247 1536 : if (single_column) then
248 0 : allocate(dynlats(columns_on_task),dynlons(columns_on_task),pos_dynlons(columns_on_task))
249 0 : dynlats(:) = dyn_columns(:)%lat_deg
250 0 : dynlons(:) = dyn_columns(:)%lon_deg
251 :
252 0 : pos_dynlons(:)= mod(dynlons(:) + 360._r8,360._r8)
253 0 : pos_scmlon = mod(scmlon + 360._r8,360._r8)
254 :
255 0 : if (unstructured) then
256 : minpoint=1000.0_r8
257 0 : do i=1,columns_on_task
258 0 : testpoint=abs(pos_dynlons(i)-pos_scmlon)+abs(dynlats(i)-scmlat)
259 0 : if (testpoint < minpoint) then
260 0 : minpoint=testpoint
261 0 : scm_col_index=i
262 : endif
263 : enddo
264 : end if
265 0 : hdim1_d = 1
266 0 : hdim2_d = 1
267 0 : phys_columns_on_task = 1
268 0 : deallocate(dynlats,dynlons,pos_dynlons)
269 : else
270 1536 : phys_columns_on_task = columns_on_task
271 : end if
272 : ! hdim1_d * hdim2_d is the total number of columns
273 1536 : num_global_phys_cols = hdim1_d * hdim2_d
274 : !!XXgoldyXX: Can we enforce interface numbering separate from dycore?
275 : !!XXgoldyXX: This will work for both CAM and WRF/MPAS physics
276 : !!XXgoldyXX: This only has a 50% chance of working on a single level model
277 1536 : if (index_top_layer < index_bottom_layer) then
278 1536 : index_top_interface = index_top_layer
279 1536 : index_bottom_interface = index_bottom_layer + 1
280 : else
281 0 : index_bottom_interface = index_bottom_layer
282 0 : index_top_interface = index_top_layer + 1
283 : end if
284 :
285 1536 : if (allocated(phys_columns)) then
286 0 : deallocate(phys_columns)
287 : end if
288 104880 : allocate(phys_columns(phys_columns_on_task))
289 1536 : if (phys_columns_on_task > 0) then
290 1536 : col_index = phys_columns_on_task
291 1536 : num_chunks = col_index / pcols
292 1536 : if ((num_chunks * pcols) < col_index) then
293 1536 : num_chunks = num_chunks + 1
294 : end if
295 1536 : begchunk = 1
296 1536 : endchunk = begchunk + num_chunks - 1
297 : else
298 : ! We do not support tasks with no physics columns
299 0 : call endrun(subname//'No columns on task, use fewer tasks')
300 : end if
301 10800 : allocate(chunks(begchunk:endchunk))
302 1536 : col_index = 0
303 : ! Simple chunk assignment
304 7728 : do index = begchunk, endchunk
305 6192 : chunks(index)%ncols = MIN(pcols, (phys_columns_on_task - col_index))
306 6192 : chunks(index)%chunk_index = index
307 18576 : allocate(chunks(index)%phys_cols(chunks(index)%ncols))
308 104928 : do phys_col = 1, chunks(index)%ncols
309 97200 : col_index = col_index + 1
310 : ! Copy information supplied by the dycore
311 97200 : if (single_column) then
312 0 : phys_columns(col_index) = dyn_columns(scm_col_index)
313 : ! !scm physics only has 1 global column
314 0 : phys_columns(col_index)%global_col_num = 1
315 0 : phys_columns(col_index)%coord_indices(:)=scm_col_index
316 : else
317 97200 : phys_columns(col_index) = dyn_columns(col_index)
318 : end if
319 : ! Fill in physics decomp info
320 97200 : phys_columns(col_index)%phys_task = iam
321 97200 : phys_columns(col_index)%local_phys_chunk = index
322 97200 : phys_columns(col_index)%phys_chunk_index = phys_col
323 103392 : chunks(index)%phys_cols(phys_col) = col_index
324 : end do
325 : end do
326 :
327 98736 : deallocate(dyn_columns)
328 :
329 : ! Add physics-package grid to set of CAM grids
330 : ! physgrid always uses 'lat' and 'lon' as coordinate names; If dynamics
331 : ! grid is different, it will use different coordinate names
332 :
333 : ! First, create a map for the physics grid
334 : ! It's structure will depend on whether or not the physics grid is
335 : ! unstructured
336 1536 : if (unstructured) then
337 4608 : allocate(grid_map(3, pcols * (endchunk - begchunk + 1)))
338 1536 : if (single_column) allocate(grid_map_scm(3, pcols * (endchunk - begchunk + 1)))
339 : else
340 0 : allocate(grid_map(4, pcols * (endchunk - begchunk + 1)))
341 0 : if (single_column) allocate(grid_map_scm(4, pcols * (endchunk - begchunk + 1)))
342 : end if
343 397824 : grid_map = 0_iMap
344 1536 : if (single_column) grid_map_scm = 0_iMap
345 4608 : allocate(latvals(size(grid_map, 2)))
346 3072 : allocate(lonvals(size(grid_map, 2)))
347 :
348 1536 : lonmin = 1000.0_r8 ! Out of longitude range
349 1536 : latmin = 1000.0_r8 ! Out of latitude range
350 1536 : index = 0
351 7728 : do ichnk = begchunk, endchunk
352 6192 : ncol = chunks(ichnk)%ncols ! Too soon to call get_ncols_p
353 106800 : do icol = 1, pcols
354 99072 : index = index + 1
355 99072 : if (icol <= ncol) then
356 97200 : col_index = chunks(ichnk)%phys_cols(icol)
357 97200 : latvals(index) = phys_columns(col_index)%lat_deg
358 97200 : if (latvals(index) < latmin) then
359 9410 : latmin = latvals(index)
360 : end if
361 97200 : lonvals(index) = phys_columns(col_index)%lon_deg
362 97200 : if (lonvals(index) < lonmin) then
363 6592 : lonmin = lonvals(index)
364 : end if
365 : else
366 1872 : col_index = -1
367 1872 : latvals(index) = 1000.0_r8
368 1872 : lonvals(index) = 1000.0_r8
369 : end if
370 99072 : grid_map(1, index) = int(icol, iMap)
371 99072 : grid_map(2, index) = int(ichnk, iMap)
372 99072 : if (single_column) then
373 0 : grid_map_scm(1, index) = int(icol, iMap)
374 0 : grid_map_scm(2, index) = int(ichnk, iMap)
375 : end if
376 105264 : if (icol <= ncol) then
377 97200 : if (unstructured) then
378 97200 : gcol = phys_columns(col_index)%global_col_num
379 97200 : if (gcol > 0) then
380 97200 : grid_map(3, index) = int(gcol, iMap)
381 97200 : if (single_column) grid_map_scm(3, index) = closeioplonidx
382 : end if ! else entry remains 0
383 : else
384 : ! lon
385 0 : gcol = phys_columns(col_index)%coord_indices(1)
386 0 : if (gcol > 0) then
387 0 : grid_map(3, index) = int(gcol, iMap)
388 0 : if (single_column) grid_map_scm(3, index) = closeioplonidx
389 : end if ! else entry remains 0
390 : ! lat
391 0 : gcol = phys_columns(col_index)%coord_indices(2)
392 0 : if (gcol > 0) then
393 0 : grid_map(4, index) = gcol
394 0 : if (single_column) grid_map_scm(4, index) = closeioplatidx
395 : end if ! else entry remains 0
396 : end if
397 : end if ! Else entry remains 0
398 : end do
399 : end do
400 :
401 : ! Note that if the dycore is using the same points as the physics grid,
402 : ! it will have already set up 'lat' and 'lon' axes for
403 : ! the physics grid
404 : ! However, these will be in the dynamics decomposition
405 :
406 1536 : if (unstructured) then
407 : lon_coord => horiz_coord_create('lon', 'ncol', num_global_phys_cols, &
408 : 'longitude', 'degrees_east', 1, size(lonvals), lonvals, &
409 1536 : map=grid_map(3,:))
410 : lat_coord => horiz_coord_create('lat', 'ncol', num_global_phys_cols, &
411 : 'latitude', 'degrees_north', 1, size(latvals), latvals, &
412 1536 : map=grid_map(3,:))
413 : else
414 0 : allocate(coord_map(size(grid_map, 2)))
415 : ! We need a global minimum longitude and latitude
416 0 : if (npes > 1) then
417 0 : temp = lonmin
418 : call MPI_allreduce(temp, lonmin, 1, MPI_INTEGER, MPI_MIN, &
419 0 : mpicom, ierr)
420 0 : temp = latmin
421 : call MPI_allreduce(temp, latmin, 1, MPI_INTEGER, MPI_MIN, &
422 0 : mpicom, ierr)
423 : ! Create lon coord map which only writes from one of each unique lon
424 0 : where(latvals == latmin)
425 0 : coord_map(:) = grid_map(3, :)
426 : elsewhere
427 : coord_map(:) = 0_iMap
428 : end where
429 : lon_coord => horiz_coord_create('lon', 'lon', hdim1_d, &
430 : 'longitude', 'degrees_east', 1, size(lonvals), lonvals, &
431 0 : map=coord_map)
432 :
433 : ! Create lat coord map which only writes from one of each unique lat
434 0 : where(lonvals == lonmin)
435 0 : coord_map(:) = grid_map(4, :)
436 : elsewhere
437 : coord_map(:) = 0_iMap
438 : end where
439 : lat_coord => horiz_coord_create('lat', 'lat', hdim2_d, &
440 : 'latitude', 'degrees_north', 1, size(latvals), latvals, &
441 0 : map=coord_map)
442 0 : deallocate(coord_map)
443 : end if
444 : end if
445 : call cam_grid_register('physgrid', phys_decomp, lat_coord, lon_coord, &
446 1536 : grid_map, unstruct=unstructured, block_indexed=.true.)
447 1536 : if (single_column) call cam_grid_register('physgrid_scm', phys_decomp_scm, lat_coord, lon_coord, &
448 0 : grid_map_scm, unstruct=unstructured, block_indexed=.true.)
449 : ! Copy required attributes from the dynamics array
450 1536 : nullify(copy_attributes)
451 1536 : call physgrid_copy_attributes_d(copy_gridname, copy_attributes)
452 4608 : do index = 1, size(copy_attributes)
453 : call cam_grid_attribute_copy(copy_gridname, 'physgrid', &
454 4608 : copy_attributes(index))
455 : end do
456 :
457 1536 : if (.not. cam_grid_attr_exists('physgrid', 'area')) then
458 : ! Physgrid always needs an area attribute.
459 1536 : if (unstructured) then
460 : ! If we did not inherit one from the dycore (i.e., physics and
461 : ! dynamics are on different grids), create that attribute here
462 : ! (Note, a separate physics grid is only supported for
463 : ! unstructured grids).
464 4608 : allocate(area_d(size(grid_map, 2)))
465 98736 : do col_index = 1, phys_columns_on_task
466 98736 : area_d(col_index) = phys_columns(col_index)%area
467 : end do
468 : call cam_grid_attribute_register('physgrid', 'area', &
469 1536 : 'physics column areas', 'ncol', area_d, map=grid_map(3,:))
470 1536 : nullify(area_d) ! Belongs to attribute now
471 :
472 4608 : allocate(areawt_d(size(grid_map, 2)))
473 98736 : do col_index = 1, phys_columns_on_task
474 98736 : areawt_d(col_index) = phys_columns(col_index)%weight*rarea_sphere
475 : end do
476 : call cam_grid_attribute_register('physgrid', 'areawt', &
477 1536 : 'physics column area weight', 'ncol', areawt_d, map=grid_map(3,:))
478 1536 : nullify(areawt_d) ! Belongs to attribute now
479 : else
480 0 : call endrun(subname//"No 'area' attribute from dycore")
481 : end if
482 : end if
483 : ! Cleanup pointers (they belong to the grid now)
484 : ! Cleanup, we are responsible for copy attributes
485 1536 : if (associated(copy_attributes)) then
486 1536 : deallocate(copy_attributes)
487 : nullify(copy_attributes)
488 : end if
489 1536 : nullify(grid_map)
490 1536 : if (single_column) nullify(grid_map_scm)
491 1536 : deallocate(latvals)
492 : nullify(latvals)
493 1536 : deallocate(lonvals)
494 : nullify(lonvals)
495 :
496 : ! Set flag indicating physics grid is now set
497 1536 : phys_grid_set = .true.
498 :
499 1536 : call t_stopf("phys_grid_init")
500 1536 : call t_adj_detailf(+2)
501 :
502 1536 : if (calc_memory_increase) then
503 0 : call shr_mem_getusage(mem_hw_end, mem_end)
504 0 : temp = mem_end - mem_beg
505 : call MPI_reduce(temp, mem_end, 1, MPI_REAL8, MPI_MAX, masterprocid, &
506 0 : mpicom, ierr)
507 0 : if (masterproc) then
508 0 : write(iulog, *) 'phys_grid_init: Increase in memory usage = ', &
509 0 : mem_end, ' (MB)'
510 : end if
511 0 : temp = mem_hw_end - mem_hw_beg
512 : call MPI_reduce(temp, mem_hw_end, 1, MPI_REAL8, MPI_MAX, &
513 0 : masterprocid, mpicom, ierr)
514 0 : if (masterproc) then
515 0 : write(iulog, *) subname, 'Increase in memory highwater = ', &
516 0 : mem_end, ' (MB)'
517 : end if
518 : end if
519 :
520 3072 : end subroutine phys_grid_init
521 :
522 : !========================================================================
523 :
524 70324200 : integer function chunk_info_to_index_p(lcid, col, subname_in)
525 1536 : use cam_logfile, only: iulog
526 : use cam_abortutils, only: endrun
527 : ! Return the physics column index indicated by
528 : ! <lcid> (chunk) and <col> (column).
529 :
530 : ! Dummy arguments
531 : integer, intent(in) :: lcid ! local chunk id
532 : integer, intent(in) :: col ! Column index
533 : character(len=*), optional, intent(in) :: subname_in
534 : ! Local variables
535 : character(len=128) :: errmsg
536 : character(len=*), parameter :: subname = 'chunk_info_to_index_p: '
537 :
538 70324200 : if (.not. phys_grid_initialized()) then
539 0 : if (present(subname_in)) then
540 0 : call endrun(trim(subname_in)//'physics grid not initialized')
541 : else
542 0 : call endrun(subname//'physics grid not initialized')
543 : end if
544 70324200 : else if ((lcid < begchunk) .or. (lcid > endchunk)) then
545 0 : if (present(subname_in)) then
546 0 : write(errmsg, '(a,3(a,i0))') trim(subname_in), 'lcid (', lcid, &
547 0 : ') out of range (', begchunk, ' to ', endchunk
548 : else
549 0 : write(errmsg, '(a,3(a,i0))') subname, 'lcid (', lcid, &
550 0 : ') out of range (', begchunk, ' to ', endchunk
551 : end if
552 0 : write(iulog, *) trim(errmsg)
553 0 : call endrun(trim(errmsg))
554 70324200 : else if ((col < 1) .or. (col > get_ncols_p(lcid))) then
555 0 : if (present(subname_in)) then
556 0 : write(errmsg, '(a,2(a,i0))') trim(subname_in), 'col (', col, &
557 0 : ') out of range (1 to ', get_ncols_p(lcid)
558 : else
559 0 : write(errmsg, '(a,2(a,i0))') subname, 'col (', col, &
560 0 : ') out of range (1 to ', get_ncols_p(lcid)
561 : end if
562 0 : write(iulog, *) trim(errmsg)
563 0 : call endrun(trim(errmsg))
564 : end if
565 70324200 : chunk_info_to_index_p = chunks(lcid)%phys_cols(col)
566 70324200 : end function chunk_info_to_index_p
567 :
568 : !========================================================================
569 :
570 358128792 : logical function phys_grid_initialized()
571 : ! Return .true. if the physics grid is initialized, otherwise .false.
572 358128792 : phys_grid_initialized = phys_grid_set
573 358128792 : end function phys_grid_initialized
574 :
575 : !========================================================================
576 :
577 2233344 : integer function get_nlcols_p()
578 2233344 : get_nlcols_p = phys_columns_on_task
579 2233344 : end function get_nlcols_p
580 :
581 : !========================================================================
582 :
583 0 : real(r8) function get_rlat_p(lcid, col)
584 : !-----------------------------------------------------------------------
585 : !
586 : ! get_rlat_p: latitude of a physics column in radians
587 : !
588 : !-----------------------------------------------------------------------
589 :
590 : ! Dummy argument
591 : integer, intent(in) :: lcid
592 : integer, intent(in) :: col
593 : ! Local variables
594 : integer :: index
595 : character(len=*), parameter :: subname = 'get_rlat_p'
596 :
597 0 : index = chunk_info_to_index_p(lcid, col, subname_in=subname)
598 0 : get_rlat_p = phys_columns(index)%lat_rad
599 :
600 0 : end function get_rlat_p
601 :
602 : !========================================================================
603 :
604 0 : real(r8) function get_rlon_p(lcid, col)
605 : !-----------------------------------------------------------------------
606 : !
607 : ! get_rlon_p: longitude of a physics column in radians
608 : !
609 : !-----------------------------------------------------------------------
610 :
611 : ! Dummy argument
612 : integer, intent(in) :: lcid
613 : integer, intent(in) :: col
614 : ! Local variables
615 : integer :: index
616 : character(len=*), parameter :: subname = 'get_rlon_p'
617 :
618 0 : index = chunk_info_to_index_p(lcid, col, subname_in=subname)
619 0 : get_rlon_p = phys_columns(index)%lon_rad
620 :
621 0 : end function get_rlon_p
622 :
623 : !========================================================================
624 :
625 10904112 : subroutine get_rlat_all_p(lcid, rlatdim, rlats)
626 : use cam_abortutils, only: endrun
627 : !-----------------------------------------------------------------------
628 : !
629 : ! get_rlat_all_p: Return all latitudes (in radians) for chunk, <lcid>
630 : !
631 : !-----------------------------------------------------------------------
632 : ! Dummy Arguments
633 : integer, intent(in) :: lcid ! local chunk id
634 : integer, intent(in) :: rlatdim ! declared size of output array
635 : real(r8), intent(out) :: rlats(rlatdim) ! array of latitudes
636 :
637 : ! Local variables
638 : integer :: index ! loop index
639 : integer :: phys_ind
640 : character(len=*), parameter :: subname = 'get_rlat_all_p: '
641 :
642 : !-----------------------------------------------------------------------
643 10904112 : if ((lcid < begchunk) .or. (lcid > endchunk)) then
644 0 : call endrun(subname//'chunk index out of range')
645 : end if
646 182073312 : do index = 1, MIN(get_ncols_p(lcid, subname_in=subname), rlatdim)
647 171169200 : phys_ind = chunks(lcid)%phys_cols(index)
648 182073312 : rlats(index) = phys_columns(phys_ind)%lat_rad
649 : end do
650 :
651 10904112 : end subroutine get_rlat_all_p
652 :
653 : !========================================================================
654 :
655 9161064 : subroutine get_rlon_all_p(lcid, rlondim, rlons)
656 : use cam_abortutils, only: endrun
657 : !-----------------------------------------------------------------------
658 : !
659 : ! get_rlon_all_p:: Return all longitudes (in radians) for chunk, <lcid>
660 : !
661 : !-----------------------------------------------------------------------
662 : ! Dummy Arguments
663 : integer, intent(in) :: lcid ! local chunk id
664 : integer, intent(in) :: rlondim ! declared size of output array
665 : real(r8), intent(out) :: rlons(rlondim) ! array of longitudes
666 :
667 : ! Local variables
668 : integer :: index ! loop index
669 : integer :: phys_ind
670 : character(len=*), parameter :: subname = 'get_rlon_all_p: '
671 :
672 : !-----------------------------------------------------------------------
673 9161064 : if ((lcid < begchunk) .or. (lcid > endchunk)) then
674 0 : call endrun(subname//'chunk index out of range')
675 : end if
676 152968464 : do index = 1, MIN(get_ncols_p(lcid, subname_in=subname), rlondim)
677 143807400 : phys_ind = chunks(lcid)%phys_cols(index)
678 152968464 : rlons(index) = phys_columns(phys_ind)%lon_rad
679 : end do
680 :
681 9161064 : end subroutine get_rlon_all_p
682 :
683 : !========================================================================
684 :
685 0 : real(r8) function get_lat_p(lcid, col)
686 : !-----------------------------------------------------------------------
687 : !
688 : ! get_lat_p: latitude of a physics column in degrees
689 : !
690 : !-----------------------------------------------------------------------
691 :
692 : ! Dummy argument
693 : integer, intent(in) :: lcid
694 : integer, intent(in) :: col
695 : ! Local variables
696 : integer :: index
697 : character(len=*), parameter :: subname = 'get_lat_p'
698 :
699 0 : index = chunk_info_to_index_p(lcid, col, subname_in=subname)
700 0 : get_lat_p = phys_columns(index)%lat_deg
701 :
702 0 : end function get_lat_p
703 :
704 : !========================================================================
705 :
706 0 : real(r8) function get_lon_p(lcid, col)
707 : !-----------------------------------------------------------------------
708 : !
709 : ! get_lon_p: longitude of a physics column in degrees
710 : !
711 : !-----------------------------------------------------------------------
712 :
713 : ! Dummy argument
714 : integer, intent(in) :: lcid
715 : integer, intent(in) :: col
716 : ! Local variables
717 : integer :: index
718 : character(len=*), parameter :: subname = 'get_lon_p'
719 :
720 0 : index = chunk_info_to_index_p(lcid, col, subname_in=subname)
721 0 : get_lon_p = phys_columns(index)%lon_deg
722 :
723 0 : end function get_lon_p
724 :
725 : !========================================================================
726 :
727 0 : subroutine get_lat_all_p_r8(lcid, latdim, lats)
728 : use cam_abortutils, only: endrun
729 : !-----------------------------------------------------------------------
730 : !
731 : ! get_lat_all_p: Return all latitudes (in degrees) for chunk, <lcid>
732 : !
733 : !-----------------------------------------------------------------------
734 : ! Dummy Arguments
735 : integer, intent(in) :: lcid ! local chunk id
736 : integer, intent(in) :: latdim ! declared size of output array
737 : real(r8), intent(out) :: lats(latdim) ! array of latitudes
738 :
739 : ! Local variables
740 : integer :: index ! loop index
741 : integer :: phys_ind
742 : character(len=*), parameter :: subname = 'get_lat_all_p: '
743 :
744 : !-----------------------------------------------------------------------
745 0 : if ((lcid < begchunk) .or. (lcid > endchunk)) then
746 0 : call endrun(subname//'chunk index out of range')
747 : end if
748 0 : do index = 1, MIN(get_ncols_p(lcid, subname_in=subname), latdim)
749 0 : phys_ind = chunks(lcid)%phys_cols(index)
750 0 : lats(index) = phys_columns(phys_ind)%lat_deg
751 : end do
752 :
753 0 : end subroutine get_lat_all_p_r8
754 :
755 : !========================================================================
756 :
757 0 : subroutine get_lon_all_p_r8(lcid, londim, lons)
758 : use cam_abortutils, only: endrun
759 : !-----------------------------------------------------------------------
760 : !
761 : ! get_lon_all_p:: Return all longitudes (in degrees) for chunk, <lcid>
762 : !
763 : !-----------------------------------------------------------------------
764 : ! Dummy Arguments
765 : integer, intent(in) :: lcid ! local chunk id
766 : integer, intent(in) :: londim ! declared size of output array
767 : real(r8), intent(out) :: lons(londim) ! array of longitudes
768 :
769 : ! Local variables
770 : integer :: index ! loop index
771 : integer :: phys_ind
772 : character(len=*), parameter :: subname = 'get_lon_all_p: '
773 :
774 : !-----------------------------------------------------------------------
775 0 : if ((lcid < begchunk) .or. (lcid > endchunk)) then
776 0 : call endrun(subname//'chunk index out of range')
777 : end if
778 0 : do index = 1, MIN(get_ncols_p(lcid, subname_in=subname), londim)
779 0 : phys_ind = chunks(lcid)%phys_cols(index)
780 0 : lons(index) = phys_columns(phys_ind)%lon_deg
781 : end do
782 :
783 0 : end subroutine get_lon_all_p_r8
784 :
785 : !========================================================================
786 :
787 2978352 : subroutine get_area_all_p(lcid, areadim, areas)
788 : use cam_abortutils, only: endrun
789 : !-----------------------------------------------------------------------
790 : !
791 : ! get_area_all_p: Return all areas for chunk, <lcid>
792 : !
793 : !-----------------------------------------------------------------------
794 : ! Dummy Arguments
795 : integer, intent(in) :: lcid ! local chunk id
796 : integer, intent(in) :: areadim ! declared size of output array
797 : real(r8), intent(out) :: areas(areadim) ! array of areas
798 :
799 : ! Local variables
800 : integer :: index ! loop index
801 : integer :: phys_ind
802 : character(len=*), parameter :: subname = 'get_area_all_p: '
803 :
804 : !-----------------------------------------------------------------------
805 2978352 : if ((lcid < begchunk) .or. (lcid > endchunk)) then
806 0 : call endrun(subname//'chunk index out of range')
807 : end if
808 49731552 : do index = 1, MIN(get_ncols_p(lcid, subname_in=subname), areadim)
809 46753200 : phys_ind = chunks(lcid)%phys_cols(index)
810 49731552 : areas(index) = phys_columns(phys_ind)%area
811 : end do
812 :
813 2978352 : end subroutine get_area_all_p
814 :
815 : !========================================================================
816 :
817 16467624 : subroutine get_wght_all_p(lcid, wghtdim, wghts)
818 : use cam_abortutils, only: endrun
819 : !-----------------------------------------------------------------------
820 : !
821 : ! get_wght_all_p: Return all weights for chunk, <lcid>
822 : !
823 : !-----------------------------------------------------------------------
824 : ! Dummy Arguments
825 : integer, intent(in) :: lcid ! local chunk id
826 : integer, intent(in) :: wghtdim ! declared size of output array
827 : real(r8), intent(out) :: wghts(wghtdim) ! array of weights
828 :
829 : ! Local variables
830 : integer :: index ! loop index
831 : integer :: phys_ind
832 : character(len=*), parameter :: subname = 'get_wght_all_p: '
833 :
834 : !-----------------------------------------------------------------------
835 16467624 : if ((lcid < begchunk) .or. (lcid > endchunk)) then
836 0 : call endrun(subname//'chunk index out of range')
837 : end if
838 274971024 : do index = 1, MIN(get_ncols_p(lcid, subname_in=subname), wghtdim)
839 258503400 : phys_ind = chunks(lcid)%phys_cols(index)
840 274971024 : wghts(index) = phys_columns(phys_ind)%weight
841 : end do
842 :
843 16467624 : end subroutine get_wght_all_p
844 :
845 : !========================================================================
846 :
847 194092992 : integer function get_ncols_p(lcid, subname_in)
848 : use cam_abortutils, only: endrun
849 : !-----------------------------------------------------------------------
850 : !
851 : ! get_ncols_p: Return number of columns in chunk given the local chunk id.
852 : !
853 : !-----------------------------------------------------------------------
854 : ! Dummy arguments
855 : integer, intent(in) :: lcid ! local chunk id
856 : character(len=*), optional, intent(in) :: subname_in
857 :
858 194092992 : if (.not. phys_grid_initialized()) then
859 0 : if (present(subname_in)) then
860 0 : call endrun(trim(subname_in)//'physics grid not initialized')
861 : else
862 0 : call endrun('get_ncols_p: physics grid not initialized')
863 : end if
864 : else
865 194092992 : get_ncols_p = chunks(lcid)%ncols
866 : end if
867 :
868 194092992 : end function get_ncols_p
869 :
870 : !========================================================================
871 :
872 70129800 : real(r8) function get_area_p(lcid, col)
873 : ! area of a physics column in radians squared
874 :
875 : ! Dummy arguments
876 : integer, intent(in) :: lcid ! Chunk number
877 : integer, intent(in) :: col ! <lcid> column
878 : ! Local variables
879 : integer :: index
880 : character(len=*), parameter :: subname = 'get_area_p'
881 :
882 70129800 : index = chunk_info_to_index_p(lcid, col, subname_in=subname)
883 70129800 : get_area_p = phys_columns(index)%area
884 :
885 70129800 : end function get_area_p
886 :
887 : !========================================================================
888 :
889 0 : real(r8) function get_wght_p(lcid, col)
890 : ! weight of a physics column in radians squared
891 :
892 : ! Dummy arguments
893 : integer, intent(in) :: lcid ! Chunk number
894 : integer, intent(in) :: col ! <lcid> column
895 : ! Local variables
896 : integer :: index
897 : character(len=*), parameter :: subname = 'get_wght_p'
898 :
899 0 : index = chunk_info_to_index_p(lcid, col, subname_in=subname)
900 0 : get_wght_p = phys_columns(index)%weight
901 :
902 0 : end function get_wght_p
903 :
904 : !========================================================================
905 :
906 194400 : integer function get_gcol_p(lcid, col)
907 : ! global column index of a physics column
908 :
909 : ! Dummy arguments
910 : integer, intent(in) :: lcid ! local chunk id
911 : integer, intent(in) :: col ! column index
912 : ! Local variables
913 : integer :: index
914 : character(len=*), parameter :: subname = 'get_gcol_p: '
915 :
916 194400 : index = chunk_info_to_index_p(lcid, col, subname_in=subname)
917 194400 : get_gcol_p = phys_columns(index)%global_col_num
918 :
919 194400 : end function get_gcol_p
920 :
921 : !========================================================================
922 :
923 0 : subroutine get_dyn_col_p_chunk(lcid, col, blk_num, blk_ind, caller)
924 : use cam_abortutils, only: endrun
925 : ! Return the dynamics local block number and block offset(s) for
926 : ! the physics column indicated by <lcid> (chunk) and <col> (column).
927 :
928 : ! Dummy arguments
929 : integer, intent(in) :: lcid ! local chunk id
930 : integer, intent(in) :: col ! Column index
931 : integer, intent(out) :: blk_num ! Local dynamics block index
932 : integer, intent(out) :: blk_ind(:) ! Local dynamics block offset(s)
933 : character(len=*), optional, intent(in) :: caller ! Calling routine
934 : ! Local variables
935 : integer :: index
936 : integer :: off_size
937 : character(len=*), parameter :: subname = 'get_dyn_col_p_chunk: '
938 :
939 0 : index = chunk_info_to_index_p(lcid, col)
940 0 : off_size = SIZE(phys_columns(index)%dyn_block_index, 1)
941 0 : if (SIZE(blk_ind, 1) < off_size) then
942 0 : if (present(caller)) then
943 0 : call endrun(trim(caller)//': blk_ind too small')
944 : else
945 0 : call endrun(subname//'blk_ind too small')
946 : end if
947 : end if
948 0 : blk_num = phys_columns(index)%local_dyn_block
949 0 : blk_ind(1:off_size) = phys_columns(index)%dyn_block_index(1:off_size)
950 0 : if (SIZE(blk_ind, 1) > off_size) then
951 0 : blk_ind(off_size+1:) = -1
952 : end if
953 :
954 0 : end subroutine get_dyn_col_p_chunk
955 :
956 : !========================================================================
957 :
958 46850400 : subroutine get_dyn_col_p_index(index, blk_num, blk_ind)
959 : use cam_logfile, only: iulog
960 : use cam_abortutils, only: endrun
961 : ! Return the dynamics local block number and block offset(s) for
962 : ! the physics column indicated by <index>.
963 :
964 : ! Dummy arguments
965 : integer, intent(in) :: index ! index of local physics column
966 : integer, intent(out) :: blk_num ! Local dynamics block index
967 : integer, intent(out) :: blk_ind(:) ! Local dynamics block offset(s)
968 : ! Local variables
969 : integer :: off_size
970 : character(len=128) :: errmsg
971 : character(len=*), parameter :: subname = 'get_dyn_col_p_index: '
972 :
973 46850400 : if (.not. phys_grid_initialized()) then
974 0 : call endrun(subname//'physics grid not initialized')
975 46850400 : else if ((index < 1) .or. (index > columns_on_task)) then
976 0 : write(errmsg, '(a,2(a,i0))') subname, 'index (', index, &
977 0 : ') out of range (1 to ', columns_on_task
978 0 : write(iulog, *) trim(errmsg)
979 0 : call endrun(trim(errmsg))
980 : else
981 46850400 : off_size = SIZE(phys_columns(index)%dyn_block_index, 1)
982 46850400 : if (SIZE(blk_ind, 1) < off_size) then
983 0 : call endrun(subname//'blk_ind too small')
984 : end if
985 46850400 : blk_num = phys_columns(index)%local_dyn_block
986 93700800 : blk_ind(1:off_size) = phys_columns(index)%dyn_block_index(1:off_size)
987 46850400 : if (SIZE(blk_ind, 1) > off_size) then
988 0 : blk_ind(off_size+1:) = -1
989 : end if
990 : end if
991 :
992 46850400 : end subroutine get_dyn_col_p_index
993 :
994 : !========================================================================
995 :
996 6192 : subroutine get_gcol_all_p(lcid, gdim, gcols)
997 : use cam_logfile, only: iulog
998 : use cam_abortutils, only: endrun
999 : use spmd_utils, only: masterproc
1000 : ! collect global column indices of all physics columns in a chunk
1001 :
1002 : ! Dummy arguments
1003 : integer, intent(in) :: lcid ! local chunk id
1004 : integer, intent(in) :: gdim ! gcols dimension
1005 : integer, intent(out) :: gcols(:) ! global column indices
1006 : ! Local variables
1007 : integer :: ncol, col_ind
1008 : character(len=128) :: errmsg
1009 : character(len=*), parameter :: subname = 'get_gcol_all_p: '
1010 :
1011 6192 : if (.not. phys_grid_initialized()) then
1012 0 : call endrun(subname//'physics grid not initialized')
1013 6192 : else if ((lcid < begchunk) .or. (lcid > endchunk)) then
1014 0 : write(errmsg, '(a,3(a,i0))') subname, 'lcid (', lcid, &
1015 0 : ') out of range (', begchunk, ' to ', endchunk
1016 0 : write(iulog, *) trim(errmsg)
1017 0 : call endrun(trim(errmsg))
1018 : else
1019 6192 : ncol = chunks(lcid)%ncols
1020 6192 : if (gdim < ncol) then
1021 0 : if (masterproc) then
1022 0 : write(iulog, '(2a,2(i0,a))') subname, 'WARNING: gdim (', gdim, &
1023 0 : ') < ncol (', ncol,'), not all indices will be filled.'
1024 : end if
1025 0 : gcols(gdim+1:ncol) = -1
1026 : end if
1027 103392 : do col_ind = 1, MIN(ncol, gdim)
1028 103392 : gcols(col_ind) = get_gcol_p(lcid, col_ind)
1029 : end do
1030 : end if
1031 :
1032 6192 : end subroutine get_gcol_all_p
1033 :
1034 : !========================================================================
1035 :
1036 46850400 : subroutine get_chunk_info_p(index, lchnk, icol)
1037 : use cam_logfile, only: iulog
1038 : use cam_abortutils, only: endrun
1039 : ! local chunk index and column number of a physics column
1040 :
1041 : ! Dummy arguments
1042 : integer, intent(in) :: index
1043 : integer, intent(out) :: lchnk
1044 : integer, intent(out) :: icol
1045 : ! Local variables
1046 : character(len=128) :: errmsg
1047 : character(len=*), parameter :: subname = 'get_chunk_info_p: '
1048 :
1049 46850400 : if (.not. phys_grid_initialized()) then
1050 0 : call endrun(subname//': physics grid not initialized')
1051 46850400 : else if ((index < 1) .or. (index > columns_on_task)) then
1052 0 : write(errmsg, '(a,2(a,i0))') subname, 'index (', index, &
1053 0 : ') out of range (1 to ', columns_on_task
1054 0 : write(iulog, *) errmsg
1055 0 : call endrun(errmsg)
1056 : else
1057 46850400 : lchnk = phys_columns(index)%local_phys_chunk
1058 46850400 : icol = phys_columns(index)%phys_chunk_index
1059 : end if
1060 :
1061 46850400 : end subroutine get_chunk_info_p
1062 :
1063 : !========================================================================
1064 :
1065 0 : subroutine get_grid_dims(hdim1_d_out, hdim2_d_out)
1066 : use cam_abortutils, only: endrun
1067 : ! retrieve dynamics field grid information
1068 : ! hdim1_d and hdim2_d are dimensions of rectangular horizontal grid
1069 : ! data structure, If 1D data structure, then hdim2_d == 1.
1070 : integer, intent(out) :: hdim1_d_out
1071 : integer, intent(out) :: hdim2_d_out
1072 :
1073 0 : if (.not. phys_grid_initialized()) then
1074 0 : call endrun('get_grid_dims: physics grid not initialized')
1075 : end if
1076 0 : hdim1_d_out = hdim1_d
1077 0 : hdim2_d_out = hdim2_d
1078 :
1079 0 : end subroutine get_grid_dims
1080 :
1081 : !========================================================================
1082 :
1083 : ! Note: This routine is a stub for future load-balancing
1084 0 : subroutine phys_decomp_to_dyn()
1085 : !-----------------------------------------------------------------------
1086 : !
1087 : ! phys_decomp_to_dyn: Transfer physics data to dynamics decomp
1088 : !
1089 : !-----------------------------------------------------------------------
1090 0 : end subroutine phys_decomp_to_dyn
1091 :
1092 : !========================================================================
1093 :
1094 : ! Note: This routine is a stub for future load-balancing
1095 0 : subroutine dyn_decomp_to_phys()
1096 : !-----------------------------------------------------------------------
1097 : !
1098 : ! dyn_decomp_to_phys: Transfer dynamics data to physics decomp
1099 : !
1100 : !-----------------------------------------------------------------------
1101 :
1102 0 : end subroutine dyn_decomp_to_phys
1103 :
1104 : !========================================================================
1105 :
1106 : subroutine dump_grid_map(grid_map)
1107 : use spmd_utils, only: iam, npes, mpicom
1108 : use cam_grid_support, only: iMap
1109 :
1110 : integer(iMap), pointer :: grid_map(:,:)
1111 :
1112 : integer :: num_cols
1113 : integer :: penum, icol
1114 : logical :: unstruct
1115 : integer :: file
1116 : integer :: ierr
1117 :
1118 : unstruct = SIZE(grid_map, 1) == 3
1119 : num_cols = SIZE(grid_map, 2)
1120 : if (iam == 0) then
1121 : open(newunit=file, file='physgrid_map.csv', status='replace')
1122 : if (unstruct) then
1123 : write(file, *) '"iam","col","block","map pos"'
1124 : else
1125 : write(file, *) '"iam","col","block","lon","lat"'
1126 : end if
1127 : close(unit=file)
1128 : end if
1129 : do penum = 0, npes - 1
1130 : if (iam == penum) then
1131 : open(newunit=file, file='physgrid_map.csv', status='old', &
1132 : action='readwrite', position='append')
1133 : do icol = 1, num_cols
1134 : if (unstruct) then
1135 : write(file, '(3(i0,","),i0)') iam, int(grid_map(1,icol)), &
1136 : int(grid_map(2,icol)), int(grid_map(3,icol))
1137 : else
1138 : write(file, '(4(i0,","),i0)') iam, int(grid_map(1,icol)), &
1139 : int(grid_map(2,icol)), int(grid_map(3,icol)), &
1140 : int(grid_map(4,icol))
1141 : end if
1142 : end do
1143 : close(unit=file)
1144 : end if
1145 : call MPI_barrier(mpicom, ierr)
1146 : end do
1147 : end subroutine dump_grid_map
1148 :
1149 : !=============================================================================
1150 : !==
1151 : !!!!!! DUMMY INTERFACEs TO TEST WEAK SCALING INFRASTRUCTURE, SHOULD GO AWAY
1152 : !==
1153 : !=============================================================================
1154 :
1155 0 : subroutine scatter_field_to_chunk(fdim,mdim,ldim, &
1156 : hdim1d,globalfield,localchunks)
1157 : use cam_abortutils, only: endrun
1158 : !-----------------------------------------------------------------------
1159 : !
1160 : ! Purpose: DUMMY FOR WEAK SCALING TESTS
1161 : !
1162 : !------------------------------Arguments--------------------------------
1163 : integer, intent(in) :: fdim ! declared length of first dimension
1164 : integer, intent(in) :: mdim ! declared length of middle dimension
1165 : integer, intent(in) :: ldim ! declared length of last dimension
1166 : integer, intent(in) :: hdim1d ! declared first horizontal index
1167 : real(r8), intent(in) :: globalfield(fdim,hdim1d,mdim,hdim2_d,ldim)
1168 : real(r8), intent(out):: localchunks(fdim,pcols,mdim, &
1169 : begchunk:endchunk,ldim)
1170 :
1171 0 : call endrun('scatter_field_to_chunk: NOT SUPPORTED WITH WEAK SCALING')
1172 0 : end subroutine scatter_field_to_chunk
1173 :
1174 : !========================================================================
1175 :
1176 0 : subroutine get_lat_all_p_int(lcid, latdim, lats)
1177 : use cam_abortutils, only: endrun
1178 : !-----------------------------------------------------------------------
1179 : !
1180 : ! get_lat_all_p: Return all latitudes (in degrees) for chunk, <lcid>
1181 : !
1182 : !-----------------------------------------------------------------------
1183 : ! Dummy Arguments
1184 : integer, intent(in) :: lcid ! local chunk id
1185 : integer, intent(in) :: latdim ! declared size of output array
1186 : integer, intent(out) :: lats(latdim) ! array of latitudes
1187 :
1188 0 : call endrun('get_lat_all_p: deprecated interface')
1189 :
1190 0 : end subroutine get_lat_all_p_int
1191 :
1192 : !========================================================================
1193 :
1194 0 : subroutine get_lon_all_p_int(lcid, londim, lons)
1195 : use cam_abortutils, only: endrun
1196 : !-----------------------------------------------------------------------
1197 : !
1198 : ! get_lon_all_p:: Return all longitudes (in degrees) for chunk, <lcid>
1199 : !
1200 : !-----------------------------------------------------------------------
1201 : ! Dummy Arguments
1202 : integer, intent(in) :: lcid ! local chunk id
1203 : integer, intent(in) :: londim ! declared size of output array
1204 : integer, intent(out) :: lons(londim) ! array of longitudes
1205 :
1206 0 : call endrun('get_lon_all_p: deprecated interface')
1207 :
1208 0 : end subroutine get_lon_all_p_int
1209 :
1210 : !========================================================================
1211 :
1212 0 : end module phys_grid
|