Oasis3-MCT
mod_oasis_grid.F90
Go to the documentation of this file.
1 
2 !> OASIS grid data and methods
3 
4 !> These interfaces support both grid data specified globally on the root task
5 !> as required in Oasis3 and grid data decomposed across tasks. If grid data
6 !> is decomposed across tasks, the optional partid argument must be specified
7 !> when it exists in the interface.
8 
10 !-----------------------------------------------------------------------
11 ! BOP
12 !
13 ! !MODULE: mod_prism_grid
14 ! !REMARKS:
15 !
16 ! **********************
17 ! THIS SHOULD BE CALLED BY A SINGLE PE ACCORDING TO THE OASIS3
18 ! STANDARD. THE DATA IS GLOBAL.
19 ! **********************
20 !
21 ! !REVISION HISTORY:
22 !
23 !
24 ! !PUBLIC MEMBER FUNCTIONS:
25 !
26 ! subroutine oasis_start_grids_writing(iwrite)
27 ! This subroutine initializes grid writing by receiving a
28 ! starting command from OASIS.
29 !
30 ! subroutine oasis_write_grid(cgrid, nx, ny, lon, lat, part_id)
31 ! This subroutine writes longitudes and latitudes for a model
32 ! grid. part_id is optional and indicates decomposed data is provided
33 !
34 ! subroutine oasis_write_corner(cgrid, nx, ny, nc, clon, clat, part_id)
35 ! This subroutine writes the longitudes and latitudes of the
36 ! grid cell corners. part_id is optional and indicates decomposed data
37 ! is provided
38 !
39 ! subroutine oasis_write_mask(cgrid, nx, ny, mask, part_id)
40 ! This subroutine writes the mask for a model grid. part_id is optional
41 ! and indicates decomposed data is provided
42 !
43 ! subroutine oasis_write_area(cgrid, nx, ny, area, part_id)
44 ! This subroutine writes the grid cell areas for a model grid. part_id
45 ! is optional and indicates decomposed data is provided
46 !
47 ! subroutine oasis_terminate_grids_writing()
48 ! This subroutine terminates grid writing by sending a flag
49 ! to OASIS, stating the all needed grid information was written.
50 !
51 
52 ! !USES:
53  USE mod_oasis_data
54  USE mod_oasis_io
55  USE mod_oasis_sys
56  USE mod_oasis_part
59  USE mod_oasis_timer
60  USE mct_mod
61 
62  implicit none
63 
64  private
65 
67  public oasis_write_grid
68  public oasis_write_angle
69  public oasis_write_corner
70  public oasis_write_mask
71  public oasis_write_area
73  public oasis_write2files
75 
76 #include "oasis_os.h"
77 
78  !> Generic interface to support writing 4 or 8 byte reals
79  interface oasis_write_grid
80 #ifndef __NO_4BYTE_REALS
81  module procedure oasis_write_grid_r4
82 #endif
83  module procedure oasis_write_grid_r8
84  end interface
85 
86  !> Generic interface to support writing 4 or 8 byte reals
88 #ifndef __NO_4BYTE_REALS
89  module procedure oasis_write_angle_r4
90 #endif
91  module procedure oasis_write_angle_r8
92  end interface
93 
94  !> Generic interface to support writing 4 or 8 byte reals
96 #ifndef __NO_4BYTE_REALS
97  module procedure oasis_write_corner_r4
98 #endif
99  module procedure oasis_write_corner_r8
100  end interface
101 
102  !> Generic interface to support writing 4 or 8 byte reals
104 #ifndef __NO_4BYTE_REALS
105  module procedure oasis_write_area_r4
106 #endif
107  module procedure oasis_write_area_r8
108  end interface
109 
110  !--- datatypes ---
111  public :: prism_grid_type !< Grid datatype
112 
113  integer(kind=ip_intwp_p),parameter :: mgrid = 100 !< maximum number of grids allowed
114  integer(kind=ip_intwp_p),save :: writing_grids_call=0
115 
116  !> Model grid data for creating mapping data and conserving fields
118  character(len=ic_med) :: gridname !< grid name
119  integer(kind=ip_i4_p) :: partid !< partition ID
120  integer(kind=ip_i4_p) :: nx !< global nx size
121  integer(kind=ip_i4_p) :: ny !< global ny size
122  integer(kind=ip_i4_p) :: nc !< number of corners per gridcell
123  logical :: grid_set !< flag to track user calls for grid
124  logical :: corner_set !< flag to track user calls for corner
125  logical :: angle_set !< flag to track user calls for angle
126  logical :: area_set !< flag to track user calls for area
127  logical :: mask_set !< flag to track user calls for mask
128  logical :: written !< flag to indicate grid has been written
129  logical :: terminated !< flag to indicate user grid calls complete
130  real(kind=ip_realwp_p),allocatable :: lon(:,:) !< user specified longitudes
131  real(kind=ip_realwp_p),allocatable :: lat(:,:) !< user specified latitudes
132  real(kind=ip_realwp_p),allocatable :: clon(:,:,:) !< user specified corner longitudes
133  real(kind=ip_realwp_p),allocatable :: clat(:,:,:) !< user specified corner latitudes
134  real(kind=ip_realwp_p),allocatable :: angle(:,:) !< user specified angle
135  real(kind=ip_realwp_p),allocatable :: area(:,:) !< user specified area
136  integer(kind=ip_i4_p) ,allocatable :: mask(:,:) !< user specified mask
137  end type prism_grid_type
138 
139  integer(kind=ip_intwp_p),public,save :: prism_ngrid = 0 !< counter for grids
140  type(prism_grid_type),public,save :: prism_grid(mgrid) !< array of grid datatypes
141  logical, parameter :: local_timers_on = .false.
142 
143 #ifdef use_netCDF
144 #include <netcdf.inc>
145 #endif
146 
147 !---------------------------------------------------------------------------
148 
149 CONTAINS
150 
151 !--------------------------------------------------------------------------
152 
153 !> Print grid information to log file.
154 
155  SUBROUTINE oasis_print_grid_data()
157  implicit none
158 
159  !-------------------------------------------------
160  integer(kind=ip_intwp_p) :: n
161  character(len=*),parameter :: subname = '(oasis_print_grid_data)'
162  !-------------------------------------------------
163 
164  call oasis_debug_enter(subname)
165  if (local_timers_on) call oasis_timer_start(trim(subname))
166 
167  if (oasis_debug >= 15) then
168  do n = 1,prism_ngrid
169  write(nulprt,*) ' '
170  write(nulprt,*) subname,trim(prism_grid(n)%gridname),' size',prism_grid(n)%nx,prism_grid(n)%ny
171  write(nulprt,*) subname,trim(prism_grid(n)%gridname),' set ',prism_grid(n)%grid_set, &
172  prism_grid(n)%corner_set, prism_grid(n)%angle_set, prism_grid(n)%area_set, prism_grid(n)%mask_set
173  if (prism_grid(n)%partid > 0 .and. prism_grid(n)%partid < prism_npart) then
174  write(nulprt,*) subname,'partid ',trim(prism_grid(n)%gridname),prism_grid(n)%partid, &
175  trim(prism_part(prism_grid(n)%partid)%partname)
176  else
177  write(nulprt,*) subname,'partid ',trim(prism_grid(n)%gridname),prism_grid(n)%partid
178  endif
179  if (prism_grid(n)%grid_set) write(nulprt,*) subname,trim(prism_grid(n)%gridname),' lon ', &
180  size(prism_grid(n)%lon,dim=1),size(prism_grid(n)%lon,dim=2), &
181  minval(prism_grid(n)%lon),maxval(prism_grid(n)%lon)
182  if (prism_grid(n)%grid_set) write(nulprt,*) subname,trim(prism_grid(n)%gridname),' lat ', &
183  size(prism_grid(n)%lat,dim=1),size(prism_grid(n)%lat,dim=2), &
184  minval(prism_grid(n)%lat),maxval(prism_grid(n)%lat)
185  if (prism_grid(n)%corner_set) write(nulprt,*) subname,trim(prism_grid(n)%gridname),' clon ', &
186  size(prism_grid(n)%clon,dim=1),size(prism_grid(n)%clon,dim=2), &
187  minval(prism_grid(n)%clon),maxval(prism_grid(n)%clon)
188  if (prism_grid(n)%corner_set) write(nulprt,*) subname,trim(prism_grid(n)%gridname),' clat ', &
189  size(prism_grid(n)%clat,dim=1),size(prism_grid(n)%clat,dim=2), &
190  minval(prism_grid(n)%clat),maxval(prism_grid(n)%clat)
191  if (prism_grid(n)%angle_set) write(nulprt,*) subname,trim(prism_grid(n)%gridname),' angl ', &
192  size(prism_grid(n)%angle,dim=1),size(prism_grid(n)%angle,dim=2), &
193  minval(prism_grid(n)%angle),maxval(prism_grid(n)%angle)
194  if (prism_grid(n)%mask_set) write(nulprt,*) subname,trim(prism_grid(n)%gridname),' mask ', &
195  size(prism_grid(n)%mask,dim=1),size(prism_grid(n)%mask,dim=2), &
196  minval(prism_grid(n)%mask),maxval(prism_grid(n)%mask)
197  if (prism_grid(n)%area_set) write(nulprt,*) subname,trim(prism_grid(n)%gridname),' area ', &
198  size(prism_grid(n)%area,dim=1),size(prism_grid(n)%area,dim=2), &
199  minval(prism_grid(n)%area),maxval(prism_grid(n)%area)
200  enddo
201  endif
202 
203  if (local_timers_on) call oasis_timer_stop(trim(subname))
204  call oasis_debug_exit(subname)
205 
206  END SUBROUTINE oasis_print_grid_data
207 
208 !--------------------------------------------------------------------------
209 
210 !> User interface to initialize grid writing
211 
212  SUBROUTINE oasis_start_grids_writing(iwrite)
214  implicit none
215 
216  integer(kind=ip_intwp_p), intent (OUT) :: iwrite !< flag, obsolete
217 
218  !-------------------------------------------------
219  character(len=*),parameter :: subname = '(oasis_start_grids_writing)'
220  !-------------------------------------------------
221 
222  call oasis_debug_enter(subname)
223  if (local_timers_on) call oasis_timer_start(trim(subname))
224 
225  if (oasis_debug >= 15) then
226  write(nulprt,*) subname,' prism_ngrid = ',prism_ngrid
227  endif
228 
229  if (prism_ngrid == 0) then ! first call
230  prism_grid(:)%gridname = 'unSet'
231  prism_grid(:)%nx = -1
232  prism_grid(:)%ny = -1
233  prism_grid(:)%grid_set = .false.
234  prism_grid(:)%corner_set = .false.
235  prism_grid(:)%angle_set = .false.
236  prism_grid(:)%area_set = .false.
237  prism_grid(:)%mask_set = .false.
238  prism_grid(:)%written = .false.
239  prism_grid(:)%terminated = .false.
240  prism_grid(:)%partid = -1
241  endif
242  iwrite = 1 ! just set grids are needed always
244 
245  if (local_timers_on) call oasis_timer_stop(trim(subname))
246  call oasis_debug_exit(subname)
247 
248  END SUBROUTINE oasis_start_grids_writing
249 
250 !--------------------------------------------------------------------------
251 
252 !> User interface to set latitudes and longitudes for 8 byte reals
253 
254  SUBROUTINE oasis_write_grid_r8(cgrid, nx, ny, lon, lat, partid)
256  !-------------------------------------------------
257  ! Routine to create a new grids file or to add a grid description to an
258  ! existing grids file.
259  !-------------------------------------------------
260 
261  implicit none
262 
263  character(len=*), intent (in) :: cgrid !< grid name
264  integer(kind=ip_intwp_p), intent (in) :: nx !< global nx size
265  integer(kind=ip_intwp_p), intent (in) :: ny !< global ny size
266  real(kind=ip_double_p), intent (in) :: lon(:,:) !< longitudes
267  real(kind=ip_double_p), intent (in) :: lat(:,:) !< latitudes
268  integer(kind=ip_intwp_p), intent (in),optional :: partid !< partition id if nonglobal data
269  !-------------------------------------------------
270  integer(kind=ip_intwp_p) :: GRIDID
271  integer(kind=ip_intwp_p) :: ierror
272  integer(kind=ip_intwp_p) :: lnx,lny
273  character(len=*),parameter :: subname = '(oasis_write_grid_r8)'
274  !-------------------------------------------------
275 
276  call oasis_debug_enter(subname)
277  if (local_timers_on) call oasis_timer_start(trim(subname))
278 
279  if (oasis_debug >= 15) then
280  write(nulprt,*) subname,' size = ',trim(cgrid),nx,ny
281  endif
282 
283  call oasis_findgrid(cgrid,nx,ny,gridid)
284 
285  lnx = size(lon,dim=1)
286  lny = size(lon,dim=2)
287 
288  allocate(prism_grid(gridid)%lon(lnx,lny),stat=ierror)
289  IF (ierror /= 0) WRITE(nulprt,*) subname,' model :',compid,' proc :',&
290  mpi_rank_local,' WARNING lon alloc'
291 
292  lnx = size(lat,dim=1)
293  lny = size(lat,dim=2)
294 
295  allocate(prism_grid(gridid)%lat(lnx,lny),stat=ierror)
296  if (ierror /= 0) write(nulprt,*) subname,' model :',compid,' proc :',&
297  mpi_rank_local,' WARNING lat alloc'
298 
299  prism_grid(gridid)%lon = lon
300  prism_grid(gridid)%lat = lat
301  prism_grid(gridid)%grid_set = .true.
302 
303  if (present(partid)) then
304  if (prism_grid(gridid)%partid > 0 .and. prism_grid(gridid)%partid /= partid) then
305  write(nulprt,*) subname,estr,'partid inconsistency',gridid,prism_grid(gridid)%partid,partid
306  call oasis_abort(file=__file__,line=__line__)
307  endif
308  prism_grid(gridid)%partid = partid
309  if (oasis_debug >= 15) then
310  write(nulprt,*) subname,' partid = ',trim(cgrid),partid
311  endif
312  endif
313 
314  if (local_timers_on) call oasis_timer_stop(trim(subname))
315  call oasis_debug_exit(subname)
316 
317  END SUBROUTINE oasis_write_grid_r8
318 
319 !--------------------------------------------------------------------------
320 
321 !> User interface to set latitudes and longitudes for 4 byte reals
322 
323  SUBROUTINE oasis_write_grid_r4(cgrid, nx, ny, lon, lat, partid)
325  !-------------------------------------------------
326  ! Routine to create a new grids file or to add a grid description to an
327  ! existing grids file.
328  !-------------------------------------------------
329 
330  implicit none
331 
332  character(len=*), intent (in) :: cgrid !< grid name
333  integer(kind=ip_intwp_p), intent (in) :: nx !< global nx size
334  integer(kind=ip_intwp_p), intent (in) :: ny !< global ny size
335  real(kind=ip_single_p), intent (in) :: lon(:,:) !< longitudes
336  real(kind=ip_single_p), intent (in) :: lat(:,:) !< latitudes
337  integer(kind=ip_intwp_p), intent (in),optional :: partid !< partition id if nonglobal data
338  !-------------------------------------------------
339  real(kind=ip_double_p), allocatable :: lon8(:,:)
340  real(kind=ip_double_p), allocatable :: lat8(:,:)
341  integer(kind=ip_intwp_p) :: ierror
342  integer(kind=ip_intwp_p) :: lpartid
343  integer(kind=ip_intwp_p) :: lnx,lny
344  character(len=*),parameter :: subname = '(oasis_write_grid_r4)'
345  !-------------------------------------------------
346 
347  call oasis_debug_enter(subname)
348  if (local_timers_on) call oasis_timer_start(trim(subname))
349 
350  if (oasis_debug >= 15) then
351  write(nulprt,*) subname,' size = ',trim(cgrid),nx,ny
352  endif
353 
354  lpartid = -1
355  if (present(partid)) then
356  lpartid = partid
357  endif
358  if (oasis_debug >= 15) then
359  write(nulprt,*) subname,' partid = ',trim(cgrid),lpartid
360  endif
361 
362  lnx = size(lon,dim=1)
363  lny = size(lon,dim=2)
364 
365  allocate(lon8(lnx,lny),stat=ierror)
366  IF (ierror /= 0) WRITE(nulprt,*) subname,' model :',compid,' proc :',&
367  mpi_rank_local,' WARNING lon alloc'
368 
369  lnx = size(lat,dim=1)
370  lny = size(lat,dim=2)
371 
372  allocate(lat8(lnx,lny),stat=ierror)
373  if (ierror /= 0) write(nulprt,*) subname,' model :',compid,' proc :',&
374  mpi_rank_local,' WARNING lat alloc'
375 
376  lon8 = lon
377  lat8 = lat
378  call oasis_write_grid_r8(cgrid,nx,ny,lon8,lat8,partid=lpartid)
379  deallocate(lon8)
380  deallocate(lat8)
381 
382  if (local_timers_on) call oasis_timer_stop(trim(subname))
383  call oasis_debug_exit(subname)
384 
385  END SUBROUTINE oasis_write_grid_r4
386 
387 !--------------------------------------------------------------------------
388 
389 !> User interface to set angle for 8 byte reals
390 
391  SUBROUTINE oasis_write_angle_r8(cgrid, nx, ny, angle, partid)
393  !-------------------------------------------------
394  ! Routine to add angles to an existing grid file.
395  !-------------------------------------------------
396 
397  implicit none
398 
399  character(len=*), intent (in) :: cgrid !< grid name
400  integer(kind=ip_intwp_p), intent (in) :: nx !< global nx size
401  integer(kind=ip_intwp_p), intent (in) :: ny !< global ny size
402  real(kind=ip_double_p), intent (in) :: angle(:,:) !< angles
403  integer(kind=ip_intwp_p), intent (in),optional :: partid !< partition id if nonglobal data
404  !-------------------------------------------------
405  integer(kind=ip_intwp_p) :: GRIDID
406  integer(kind=ip_intwp_p) :: ierror
407  integer(kind=ip_intwp_p) :: lnx,lny
408  character(len=*),parameter :: subname = '(oasis_write_angle_r8)'
409  !-------------------------------------------------
410 
411  call oasis_debug_enter(subname)
412  if (local_timers_on) call oasis_timer_start(trim(subname))
413 
414  if (oasis_debug >= 15) then
415  write(nulprt,*) subname,' size = ',trim(cgrid),nx,ny
416  endif
417 
418  call oasis_findgrid(cgrid,nx,ny,gridid)
419 
420  lnx = size(angle,dim=1)
421  lny = size(angle,dim=2)
422 
423  allocate(prism_grid(gridid)%angle(lnx,lny),stat=ierror)
424  if (ierror /= 0) write(nulprt,*) subname,' model :',compid,' proc :',&
425  mpi_rank_local,' WARNING angle alloc'
426 
427  prism_grid(gridid)%angle = angle
428  prism_grid(gridid)%angle_set = .true.
429  if (present(partid)) then
430  if (prism_grid(gridid)%partid > 0 .and. prism_grid(gridid)%partid /= partid) then
431  write(nulprt,*) subname,estr,'partid inconsistency',gridid,prism_grid(gridid)%partid,partid
432  call oasis_abort(file=__file__,line=__line__)
433  endif
434  prism_grid(gridid)%partid = partid
435  if (oasis_debug >= 15) then
436  write(nulprt,*) subname,' partid = ',trim(cgrid),partid
437  endif
438  endif
439 
440  if (local_timers_on) call oasis_timer_stop(trim(subname))
441  call oasis_debug_exit(subname)
442 
443  END SUBROUTINE oasis_write_angle_r8
444 
445 !--------------------------------------------------------------------------
446 
447 !> User interface to set angle for 4 byte reals
448 
449  SUBROUTINE oasis_write_angle_r4(cgrid, nx, ny, angle, partid)
451  !-------------------------------------------------
452  ! Routine to add angles to an existing grid file.
453  !-------------------------------------------------
454 
455  implicit none
456 
457  character(len=*), intent (in) :: cgrid !< grid name
458  integer(kind=ip_intwp_p), intent (in) :: nx !< global nx size
459  integer(kind=ip_intwp_p), intent (in) :: ny !< global ny size
460  real(kind=ip_single_p), intent (in) :: angle(:,:) !< angles
461  integer(kind=ip_intwp_p), intent (in),optional :: partid !< partition id if nonglobal data
462  !-------------------------------------------------
463  real(kind=ip_double_p),allocatable :: angle8(:,:)
464  integer(kind=ip_intwp_p) :: ierror
465  integer(kind=ip_intwp_p) :: lpartid
466  integer(kind=ip_intwp_p) :: lnx,lny
467  character(len=*),parameter :: subname = '(oasis_write_angle_r4)'
468  !-------------------------------------------------
469 
470  call oasis_debug_enter(subname)
471  if (local_timers_on) call oasis_timer_start(trim(subname))
472 
473  if (oasis_debug >= 15) then
474  write(nulprt,*) subname,' size = ',trim(cgrid),nx,ny
475  endif
476 
477  lpartid = -1
478  if (present(partid)) then
479  lpartid = partid
480  endif
481  if (oasis_debug >= 15) then
482  write(nulprt,*) subname,' partid = ',trim(cgrid),lpartid
483  endif
484 
485  lnx = size(angle,dim=1)
486  lny = size(angle,dim=2)
487 
488  allocate(angle8(lnx,lny),stat=ierror)
489  if (ierror /= 0) write(nulprt,*) subname,' model :',compid,' proc :',&
490  mpi_rank_local,' WARNING angle8 alloc'
491 
492  angle8 = angle
493  call oasis_write_angle_r8(cgrid,nx,ny,angle8,partid=lpartid)
494 
495  deallocate(angle8)
496 
497  if (local_timers_on) call oasis_timer_stop(trim(subname))
498  call oasis_debug_exit(subname)
499 
500  END SUBROUTINE oasis_write_angle_r4
501 
502 !--------------------------------------------------------------------------
503 
504 !> User interface to set corner latitudes and longitudes for 8 byte reals
505 
506  SUBROUTINE oasis_write_corner_r8(cgrid, nx, ny, nc, clon, clat, partid)
508  !-------------------------------------------------
509  ! Routine to add longitudes and latitudes of grid cell corners to an
510  ! existing grids file.
511  !-------------------------------------------------
512 
513  implicit none
514 
515  character(len=*), intent (in) :: cgrid !< grid name
516  integer(kind=ip_intwp_p), intent (in) :: nx !< global nx size
517  integer(kind=ip_intwp_p), intent (in) :: ny !< global ny size
518  integer(kind=ip_intwp_p), intent (in) :: nc !< number of corners per cell
519  real(kind=ip_double_p), intent (in) :: clon(:,:,:) !< corner longitudes
520  real(kind=ip_double_p), intent (in) :: clat(:,:,:) !< corner latitudes
521  integer(kind=ip_intwp_p), intent (in),optional :: partid !< partition id if nonglobal data
522  !-------------------------------------------------
523  integer(kind=ip_intwp_p) :: GRIDID
524  integer(kind=ip_intwp_p) :: ierror
525  integer(kind=ip_intwp_p) :: lnx,lny
526  character(len=*),parameter :: subname = '(oasis_write_corner_r8)'
527  !-------------------------------------------------
528 
529  call oasis_debug_enter(subname)
530  if (local_timers_on) call oasis_timer_start(trim(subname))
531 
532  if (oasis_debug >= 15) then
533  write(nulprt,*) subname,' size = ',trim(cgrid),nx,ny
534  endif
535 
536  call oasis_findgrid(cgrid,nx,ny,gridid)
537 
538  lnx = size(clon,dim=1)
539  lny = size(clon,dim=2)
540 
541  allocate(prism_grid(gridid)%clon(lnx,lny,nc),stat=ierror)
542  if (ierror /= 0) write(nulprt,*) subname,' model :',compid,' proc :',&
543  mpi_rank_local,' WARNING clon alloc'
544 
545  lnx = size(clat,dim=1)
546  lny = size(clat,dim=2)
547 
548  allocate(prism_grid(gridid)%clat(lnx,lny,nc),stat=ierror)
549  if (ierror /= 0) write(nulprt,*) subname,' model :',compid,' proc :',&
550  mpi_rank_local,' WARNING clat alloc'
551 
552  prism_grid(gridid)%nc = nc
553  prism_grid(gridid)%clon = clon
554  prism_grid(gridid)%clat = clat
555  prism_grid(gridid)%corner_set = .true.
556  if (present(partid)) then
557  if (prism_grid(gridid)%partid > 0 .and. prism_grid(gridid)%partid /= partid) then
558  write(nulprt,*) subname,estr,'partid inconsistency',gridid,prism_grid(gridid)%partid,partid
559  call oasis_abort(file=__file__,line=__line__)
560  endif
561  prism_grid(gridid)%partid = partid
562  if (oasis_debug >= 15) then
563  write(nulprt,*) subname,' partid = ',trim(cgrid),partid
564  endif
565  endif
566 
567  if (local_timers_on) call oasis_timer_stop(trim(subname))
568  call oasis_debug_exit(subname)
569 
570  END SUBROUTINE oasis_write_corner_r8
571 
572 !--------------------------------------------------------------------------
573 
574 !> User interface to set corner latitudes and longitudes for 4 byte reals
575 
576  SUBROUTINE oasis_write_corner_r4(cgrid, nx, ny, nc, clon, clat, partid)
578  !-------------------------------------------------
579  ! Routine to add longitudes and latitudes of grid cell corners to an
580  ! existing grids file.
581  !-------------------------------------------------
582 
583  implicit none
584 
585  character(len=*), intent (in) :: cgrid !< grid name
586  integer(kind=ip_intwp_p), intent (in) :: nx !< global nx size
587  integer(kind=ip_intwp_p), intent (in) :: ny !< global ny size
588  integer(kind=ip_intwp_p), intent (in) :: nc !< number of corners per cell
589  real(kind=ip_single_p), intent (in) :: clon(:,:,:) !< corner longitudes
590  real(kind=ip_single_p), intent (in) :: clat(:,:,:) !< corner latitudes
591  integer(kind=ip_intwp_p), intent (in),optional :: partid !< partition id if nonglobal data
592  !-------------------------------------------------
593  real(kind=ip_double_p), allocatable :: clon8(:,:,:),clat8(:,:,:)
594  integer(kind=ip_intwp_p) :: ierror
595  integer(kind=ip_intwp_p) :: lpartid
596  integer(kind=ip_intwp_p) :: lnx,lny
597  character(len=*),parameter :: subname = '(oasis_write_corner_r4)'
598  !-------------------------------------------------
599 
600  call oasis_debug_enter(subname)
601  if (local_timers_on) call oasis_timer_start(trim(subname))
602 
603  if (oasis_debug >= 15) then
604  write(nulprt,*) subname,' size = ',trim(cgrid),nx,ny
605  endif
606 
607  lpartid = -1
608  if (present(partid)) then
609  lpartid = partid
610  endif
611  if (oasis_debug >= 15) then
612  write(nulprt,*) subname,' partid = ',trim(cgrid),lpartid
613  endif
614 
615  lnx = size(clon,dim=1)
616  lny = size(clon,dim=2)
617 
618  allocate(clon8(lnx,lny,nc),stat=ierror)
619  if (ierror /= 0) write(nulprt,*) subname,' model :',compid,' proc :',&
620  mpi_rank_local,' WARNING clon8 alloc'
621 
622  lnx = size(clat,dim=1)
623  lny = size(clat,dim=2)
624 
625  allocate(clat8(lnx,lny,nc),stat=ierror)
626  if (ierror /= 0) write(nulprt,*) subname,' model :',compid,' proc :',&
627  mpi_rank_local,' WARNING clat8 alloc'
628 
629  clon8 = clon
630  clat8 = clat
631  call oasis_write_corner_r8(cgrid,nx,ny,nc,clon8,clat8,partid=lpartid)
632 
633  deallocate(clon8)
634  deallocate(clat8)
635 
636  if (local_timers_on) call oasis_timer_stop(trim(subname))
637  call oasis_debug_exit(subname)
638 
639  END SUBROUTINE oasis_write_corner_r4
640 
641 !--------------------------------------------------------------------------
642 
643 !> User interface to set integer mask values
644 
645  SUBROUTINE oasis_write_mask(cgrid, nx, ny, mask, partid)
647  !-------------------------------------------------
648  ! Routine to create a new masks file or to add a land see mask to an
649  ! existing masks file.
650  !-------------------------------------------------
651 
652  implicit none
653 
654  character(len=*), intent (in) :: cgrid !< grid name
655  integer(kind=ip_intwp_p), intent (in) :: nx !< global nx size
656  integer(kind=ip_intwp_p), intent (in) :: ny !< global ny size
657  integer(kind=ip_intwp_p), intent (in) :: mask(:,:) !< mask array
658  integer(kind=ip_intwp_p), intent (in),optional :: partid !< partition id if nonglobal data
659  !-------------------------------------------------
660  integer(kind=ip_intwp_p) :: GRIDID
661  integer(kind=ip_intwp_p) :: ierror
662  integer(kind=ip_intwp_p) :: lnx,lny
663  character(len=*),parameter :: subname = '(oasis_write_mask)'
664  !-------------------------------------------------
665 
666  call oasis_debug_enter(subname)
667  if (local_timers_on) call oasis_timer_start(trim(subname))
668 
669  if (oasis_debug >= 15) then
670  write(nulprt,*) subname,' size = ',trim(cgrid),nx,ny
671  endif
672 
673  call oasis_findgrid(cgrid,nx,ny,gridid)
674 
675  lnx = size(mask,dim=1)
676  lny = size(mask,dim=2)
677 
678  allocate(prism_grid(gridid)%mask(lnx,lny),stat=ierror)
679  if (ierror /= 0) write(nulprt,*) subname,' model :',compid,' proc :',&
680  mpi_rank_local,' WARNING mask alloc'
681 
682  prism_grid(gridid)%mask = mask
683  prism_grid(gridid)%mask_set = .true.
684  if (present(partid)) then
685  if (prism_grid(gridid)%partid > 0 .and. prism_grid(gridid)%partid /= partid) then
686  write(nulprt,*) subname,estr,'partid inconsistency',gridid,prism_grid(gridid)%partid,partid
687  call oasis_abort(file=__file__,line=__line__)
688  endif
689  prism_grid(gridid)%partid = partid
690  if (oasis_debug >= 15) then
691  write(nulprt,*) subname,' partid = ',trim(cgrid),partid
692  endif
693  endif
694 
695  if (local_timers_on) call oasis_timer_stop(trim(subname))
696  call oasis_debug_exit(subname)
697 
698  END SUBROUTINE oasis_write_mask
699 
700 !--------------------------------------------------------------------------
701 
702 !> User interface to set area values for 8 byte reals
703 
704  SUBROUTINE oasis_write_area_r8(cgrid, nx, ny, area, partid)
706  !-------------------------------------------------
707  ! Routine to create a new areas file or to add areas of a grid to an
708  ! existing areas file.
709  !-------------------------------------------------
710 
711  implicit none
712 
713  character(len=*), intent (in) :: cgrid !< grid name
714  integer(kind=ip_intwp_p), intent (in) :: nx !< global nx size
715  integer(kind=ip_intwp_p), intent (in) :: ny !< global ny size
716  real(kind=ip_double_p), intent (in) :: area(:,:) !< areas
717  integer(kind=ip_intwp_p), intent (in),optional :: partid !< partition id if nonglobal data
718  !-------------------------------------------------
719  integer(kind=ip_intwp_p) :: GRIDID
720  integer(kind=ip_intwp_p) :: ierror
721  integer(kind=ip_intwp_p) :: lnx,lny
722  character(len=*),parameter :: subname = '(oasis_write_area_r8)'
723  !-------------------------------------------------
724 
725  call oasis_debug_enter(subname)
726  if (local_timers_on) call oasis_timer_start(trim(subname))
727 
728  if (oasis_debug >= 15) then
729  write(nulprt,*) subname,' size = ',trim(cgrid),nx,ny
730  endif
731 
732  call oasis_findgrid(cgrid,nx,ny,gridid)
733 
734  lnx = size(area,dim=1)
735  lny = size(area,dim=2)
736 
737  allocate(prism_grid(gridid)%area(lnx,lny),stat=ierror)
738  if (ierror /= 0) write(nulprt,*) subname,' model :',compid,' proc :',&
739  mpi_rank_local,' WARNING area alloc'
740 
741  prism_grid(gridid)%area = area
742  prism_grid(gridid)%area_set = .true.
743  if (present(partid)) then
744  if (prism_grid(gridid)%partid > 0 .and. prism_grid(gridid)%partid /= partid) then
745  write(nulprt,*) subname,estr,'partid inconsistency',gridid,prism_grid(gridid)%partid,partid
746  call oasis_abort(file=__file__,line=__line__)
747  endif
748  prism_grid(gridid)%partid = partid
749  if (oasis_debug >= 15) then
750  write(nulprt,*) subname,' partid = ',trim(cgrid),partid
751  endif
752  endif
753 
754  if (local_timers_on) call oasis_timer_stop(trim(subname))
755  call oasis_debug_exit(subname)
756 
757  END SUBROUTINE oasis_write_area_r8
758 
759 !--------------------------------------------------------------------------
760 
761 !> User interface to set area values for 4 byte reals
762 
763  SUBROUTINE oasis_write_area_r4(cgrid, nx, ny, area, partid)
765  !-------------------------------------------------
766  ! Routine to create a new areas file or to add areas of a grid to an
767  ! existing areas file.
768  !-------------------------------------------------
769 
770  implicit none
771 
772  character(len=*), intent (in) :: cgrid !< grid name
773  integer(kind=ip_intwp_p), intent (in) :: nx !< global nx size
774  integer(kind=ip_intwp_p), intent (in) :: ny !< global ny size
775  real(kind=ip_single_p), intent (in) :: area(:,:) !< areas
776  integer(kind=ip_intwp_p), intent (in),optional :: partid !< partition id if nonglobal data
777  !-------------------------------------------------
778  real(kind=ip_double_p), allocatable :: area8(:,:)
779  integer(kind=ip_intwp_p) :: ierror
780  integer(kind=ip_intwp_p) :: lpartid
781  integer(kind=ip_intwp_p) :: lnx,lny
782  character(len=*),parameter :: subname = '(oasis_write_area_r4)'
783  !-------------------------------------------------
784 
785  call oasis_debug_enter(subname)
786  if (local_timers_on) call oasis_timer_start(trim(subname))
787 
788  if (oasis_debug >= 15) then
789  write(nulprt,*) subname,' size = ',trim(cgrid),nx,ny
790  endif
791 
792  lpartid = -1
793  if (present(partid)) then
794  lpartid = partid
795  endif
796  if (oasis_debug >= 15) then
797  write(nulprt,*) subname,' partid = ',trim(cgrid),lpartid
798  endif
799 
800  lnx = size(area,dim=1)
801  lny = size(area,dim=2)
802 
803  allocate(area8(lnx,lny),stat=ierror)
804  if (ierror /= 0) write(nulprt,*) subname,' model :',compid,' proc :',&
805  mpi_rank_local,' WARNING area8 alloc'
806 
807  area8 = area
808  call oasis_write_area_r8(cgrid,nx,ny,area8,partid=lpartid)
809 
810  deallocate(area8)
811 
812  if (local_timers_on) call oasis_timer_stop(trim(subname))
813  call oasis_debug_exit(subname)
814 
815  END SUBROUTINE oasis_write_area_r4
816 
817 !--------------------------------------------------------------------------
818 
819 !> User interface to indicate user defined grids are done
820 
821  SUBROUTINE oasis_terminate_grids_writing()
822  !-------------------------------------------------
823  ! Routine to terminate the grids writing.
824  !-------------------------------------------------
825 
826  implicit none
827  integer(kind=ip_i4_p) :: n
828  character(len=*),parameter :: subname = '(oasis_terminate_grids_writing)'
829 
830  call oasis_debug_enter(subname)
831  if (local_timers_on) call oasis_timer_start(trim(subname))
832 
833  if (oasis_debug >= 15) then
834  write(nulprt,*) subname,' prism_ngrid = ',prism_ngrid
835  endif
836 
837  do n = 1,prism_ngrid
838  prism_grid(n)%terminated = .true.
839  enddo
840 
841  call oasis_print_grid_data()
842 ! moved to prism_method_enddef for synchronization
843 ! call oasis_write2files()
844 
845  if (local_timers_on) call oasis_timer_stop(trim(subname))
846  call oasis_debug_exit(subname)
847 
848  END SUBROUTINE oasis_terminate_grids_writing
849 
850 !--------------------------------------------------------------------------
851 
852 !> Interface that actually writes fields to grid files
853 
854  SUBROUTINE oasis_write2files()
856  !-------------------------------------------------
857  !> Write fields to grid files.
858  !> Only write fields that have been buffered and
859  !> if prism_grid_terminate_grids_writing has been called.
860  !> This is called by all tasks from oasis_enddef.
861  !-------------------------------------------------
862 
863  implicit none
864 
865  !-------------------------------------------------
866  character(len=ic_med) :: filename ! grid filename
867  character(len=ic_med) :: fldname ! full field name
868  character(len=ic_med) :: cgrid ! grid name
869  logical :: exists ! check if file exists
870  integer(kind=ip_i4_p) :: m,n,n1,g,p ! counter
871  integer(kind=ip_i4_p) :: partid ! part id
872  integer(kind=ip_i4_p) :: taskid ! task id for writing
873  integer(kind=ip_i4_p) :: nx,ny,nc ! grid size
874  integer(kind=ip_i4_p) :: tnx,tny ! temporary grid size
875  logical :: partid_grid ! global or local grid
876  logical :: active_task ! determine which tasks are involved
877  logical :: write_task ! task for writing
878  real(kind=ip_realwp_p),allocatable :: rloc(:,:) ! local array
879  real(kind=ip_realwp_p),allocatable :: rglo(:,:) ! global array
880  real(kind=ip_realwp_p),allocatable :: r3glo(:,:,:) ! global array
881  integer(kind=ip_i4_p) ,allocatable :: iglo(:,:) ! global array
882  integer(kind=ip_intwp_p) :: gcnt
883  logical :: found
884  character(len=ic_med) ,pointer :: gname0(:),gname(:)
885  character(len=ic_lvar2) ,pointer :: pname0(:),pname(:)
886  character(len=*),parameter :: undefined_partname = '(UnDeFiNeD_PArtnaME)'
887  character(len=*),parameter :: subname = '(oasis_write2files)'
888  !-------------------------------------------------
889 
890  call oasis_debug_enter(subname)
891  call oasis_timer_start('oasis_gridw')
892 
893  call oasis_mpi_bcast(writing_grids_call,mpi_comm_local,subname//'writing_grids_call')
894  if (writing_grids_call .eq. 1) then
895 
896  if (local_timers_on) call oasis_timer_start('oasis_gridw_reducelists')
897  allocate(gname0(prism_ngrid))
898  allocate(pname0(prism_ngrid))
899  do n = 1,prism_ngrid
900  gname0(n) = prism_grid(n)%gridname
901  if (prism_grid(n)%partid > 0 .and. prism_grid(n)%partid <= prism_npart) then
902  pname0(n) = prism_part(prism_grid(n)%partid)%partname
903  elseif (prism_grid(n)%partid == -1) then
904  pname0(n) = undefined_partname
905  else
906  write(nulprt,*) subname,estr,'illegal partition id for grid ',trim(prism_grid(n)%gridname),prism_grid(n)%partid
907  endif
908  enddo
909 
910  call oasis_mpi_reducelists(gname0,mpi_comm_local,gcnt,gname,'write2files',fastcheck=.true., &
911  linp2=pname0,lout2=pname,spval2=undefined_partname)
912  deallocate(gname0)
913  deallocate(pname0)
914  if (local_timers_on) call oasis_timer_stop('oasis_gridw_reducelists')
915 
916  !-------------------------------------
917  !> * Check that a grid defined on a partitition is defined on all tasks on that partition.
918  !-------------------------------------
919 
920  if (local_timers_on) call oasis_timer_start('oasis_gridw_chkpart')
921  do n = 1,gcnt
922  if (pname(n) /= undefined_partname) then
923  do p = 1,prism_npart
924  if (pname(n) == prism_part(p)%partname .and. prism_part(p)%mpicom /= mpi_comm_null) then
925  found = .false.
926  do g = 1,prism_ngrid
927  if (prism_grid(g)%gridname == gname(n)) found = .true.
928  enddo
929  if (.not. found) then
930  write(nulprt,*) subname,estr,'grid with partition not defined on all partition tasks: ',trim(gname(n))
931  call oasis_abort(file=__file__,line=__line__)
932  endif
933  endif
934  enddo
935  endif
936  enddo
937  if (local_timers_on) call oasis_timer_stop('oasis_gridw_chkpart')
938 
939  if (local_timers_on) call oasis_timer_start('oasis_gridw_writefiles')
940 
941  !-------------------------------------
942  !> * Write grid information
943  !-------------------------------------
944 
945  do g = 1,gcnt
946  do n = 1,prism_ngrid
947  if (prism_grid(n)%terminated) then
948  if (prism_grid(n)%gridname == gname(g)) then
949 
950  cgrid = gname(g)
951  partid = prism_grid(n)%partid
952  prism_grid(n)%written = .true.
953  tnx = -1
954  tny = -1
955 
956  !-------------------------------------
957  !> * Determine which tasks are associated with the grid information
958  !-------------------------------------
959 
960  active_task = .false.
961  write_task = .false.
962  if (pname(g) == undefined_partname) then
963  partid_grid = .false.
964  if (mpi_rank_local == 0) active_task = .true.
965  if (mpi_rank_local == 0) write_task = .true.
966  else
967  partid_grid = .true.
968  if (partid > 0 .and. partid <= prism_npart) then
969  taskid = 0
970  if (prism_part(partid)%mpicom /= mpi_comm_null) active_task = .true.
971  if (prism_part(partid)%rank == taskid) write_task = .true.
972  elseif (partid == -1) then
973  active_task = .false.
974  write_task = .false.
975  else
976  write(nulprt,*) subname,estr,'illegal partid for grid:',trim(gname(g)),trim(pname(g)),partid
977  call oasis_abort(file=__file__,line=__line__)
978  endif
979  endif
980 
981  if (oasis_debug >= 15) then
982  write(nulprt,*) subname,' ',trim(gname(g)),':',trim(pname(g)),': partid_grid=', &
983  partid_grid,'active_task=',active_task,'write_task=',write_task
984  endif
985 
986  if (active_task) then
987 
988  nx = prism_grid(n)%nx
989  ny = prism_grid(n)%ny
990  nc = prism_grid(n)%nc
991 
992  allocate(rglo(nx,ny))
993 
994  !-------------------------------------
995  !> * Check that array sizes match for all fields
996  !-------------------------------------
997 
998  if (prism_grid(n)%grid_set) then
999  if (tnx <= 0 .or. tny <= 0) then
1000  tnx = size(prism_grid(n)%lon,dim=1)
1001  tny = size(prism_grid(n)%lon,dim=2)
1002  endif
1003  if (size(prism_grid(n)%lon,dim=1) /= tnx .or. &
1004  size(prism_grid(n)%lon,dim=2) /= tny .or. &
1005  size(prism_grid(n)%lat,dim=1) /= tnx .or. &
1006  size(prism_grid(n)%lat,dim=2) /= tny ) then
1007  write(nulprt,*) subname,estr,'inconsistent array size lon/lat ',tnx,tny, &
1008  size(prism_grid(n)%lon,dim=1),size(prism_grid(n)%lon,dim=2), &
1009  size(prism_grid(n)%lat,dim=1),size(prism_grid(n)%lat,dim=2)
1010  call oasis_abort(file=__file__,line=__line__)
1011  endif
1012 
1013  !-------------------------------------
1014  !> * Gather longitudes if needed and write from root
1015  !-------------------------------------
1016 
1017  filename = 'grids.nc'
1018  fldname = trim(cgrid)//'.lon'
1019  if (.not.oasis_io_varexists(filename,fldname)) then
1020  if (partid_grid) then
1021  call oasis_grid_loc2glo(prism_grid(n)%lon,rglo,partid,0)
1022  else
1023  rglo = prism_grid(n)%lon
1024  endif
1025  if (write_task) call oasis_io_write_2dgridfld_fromroot(filename,fldname,rglo,nx,ny)
1026  endif
1027 
1028  !-------------------------------------
1029  !> * Gather latitudes if needed and write from root
1030  !-------------------------------------
1031 
1032  filename = 'grids.nc'
1033  fldname = trim(cgrid)//'.lat'
1034  if (.not.oasis_io_varexists(filename,fldname)) then
1035  if (partid_grid) then
1036  call oasis_grid_loc2glo(prism_grid(n)%lat,rglo,partid,0)
1037  else
1038  rglo = prism_grid(n)%lat
1039  endif
1040  if (write_task) call oasis_io_write_2dgridfld_fromroot(filename,fldname,rglo,nx,ny)
1041  endif
1042  endif ! grid_set
1043 
1044  if (prism_grid(n)%corner_set) then
1045  if (tnx <= 0 .or. tny <= 0) then
1046  tnx = size(prism_grid(n)%clon,dim=1)
1047  tny = size(prism_grid(n)%clon,dim=2)
1048  endif
1049  if (size(prism_grid(n)%clon,dim=1) /= tnx .or. &
1050  size(prism_grid(n)%clon,dim=2) /= tny .or. &
1051  size(prism_grid(n)%clat,dim=1) /= tnx .or. &
1052  size(prism_grid(n)%clat,dim=2) /= tny ) then
1053  write(nulprt,*) subname,estr,'inconsistent array size clon/clat ',tnx,tny, &
1054  size(prism_grid(n)%clon,dim=1),size(prism_grid(n)%clon,dim=2), &
1055  size(prism_grid(n)%clat,dim=1),size(prism_grid(n)%clat,dim=2)
1056  call oasis_abort(file=__file__,line=__line__)
1057  endif
1058 
1059  !-------------------------------------
1060  !> * Gather corner longitudes if needed and write from root
1061  !-------------------------------------
1062 
1063  allocate(r3glo(nx,ny,nc))
1064  filename = 'grids.nc'
1065  fldname = trim(cgrid)//'.clo'
1066  if (.not.oasis_io_varexists(filename,fldname)) then
1067  if (partid_grid) then
1068  allocate(rloc(tnx,tny))
1069  do n1 = 1,nc
1070  rloc(:,:) = prism_grid(n)%clon(:,:,n1)
1071  call oasis_grid_loc2glo(rloc,rglo,partid,0)
1072  r3glo(:,:,n1) = rglo(:,:)
1073  enddo
1074  deallocate(rloc)
1075  else
1076  r3glo = prism_grid(n)%clon
1077  endif
1078  if (write_task) call oasis_io_write_3dgridfld_fromroot(filename,fldname,r3glo,nx,ny,nc)
1079  endif
1080 
1081  !-------------------------------------
1082  !> * Gather corner latitudes if needed and write from root
1083  !-------------------------------------
1084 
1085  filename = 'grids.nc'
1086  fldname = trim(cgrid)//'.cla'
1087  if (.not.oasis_io_varexists(filename,fldname)) then
1088  if (partid_grid) then
1089  allocate(rloc(tnx,tny))
1090  do n1 = 1,nc
1091  rloc(:,:) = prism_grid(n)%clat(:,:,n1)
1092  call oasis_grid_loc2glo(rloc,rglo,partid,0)
1093  r3glo(:,:,n1) = rglo(:,:)
1094  enddo
1095  deallocate(rloc)
1096  else
1097  r3glo = prism_grid(n)%clat
1098  endif
1099  if (write_task) call oasis_io_write_3dgridfld_fromroot(filename,fldname,r3glo,nx,ny,nc)
1100  endif
1101  deallocate(r3glo)
1102  endif ! corner_set
1103 
1104  if (prism_grid(n)%area_set) then
1105  if (tnx <= 0 .or. tny <= 0) then
1106  tnx = size(prism_grid(n)%area,dim=1)
1107  tny = size(prism_grid(n)%area,dim=2)
1108  endif
1109  if (size(prism_grid(n)%area,dim=1) /= tnx .or. &
1110  size(prism_grid(n)%area,dim=2) /= tny ) then
1111  write(nulprt,*) subname,estr,'inconsistent array size area ',tnx,tny, &
1112  size(prism_grid(n)%area,dim=1),size(prism_grid(n)%area,dim=2)
1113  call oasis_abort(file=__file__,line=__line__)
1114  endif
1115 
1116  !-------------------------------------
1117  !> * Gather areas if needed and write from root
1118  !-------------------------------------
1119 
1120  filename = 'areas.nc'
1121  fldname = trim(cgrid)//'.srf'
1122  if (.not.oasis_io_varexists(filename,fldname)) then
1123  if (partid_grid) then
1124  call oasis_grid_loc2glo(prism_grid(n)%area,rglo,partid,0)
1125  else
1126  rglo = prism_grid(n)%area
1127  endif
1128  if (write_task) call oasis_io_write_2dgridfld_fromroot(filename,fldname,rglo,nx,ny)
1129  endif
1130  endif ! area_set
1131 
1132  if (prism_grid(n)%angle_set) then
1133  if (tnx <= 0 .or. tny <= 0) then
1134  tnx = size(prism_grid(n)%angle,dim=1)
1135  tny = size(prism_grid(n)%angle,dim=2)
1136  endif
1137  if (size(prism_grid(n)%angle,dim=1) /= tnx .or. &
1138  size(prism_grid(n)%angle,dim=2) /= tny ) then
1139  write(nulprt,*) subname,estr,'inconsistent array size angle ',tnx,tny, &
1140  size(prism_grid(n)%angle,dim=1),size(prism_grid(n)%angle,dim=2)
1141  call oasis_abort(file=__file__,line=__line__)
1142  endif
1143 
1144  !-------------------------------------
1145  !> * Gather angles if needed and write from root
1146  !-------------------------------------
1147 
1148  filename = 'grids.nc'
1149  fldname = trim(cgrid)//'.ang'
1150  if (.not.oasis_io_varexists(filename,fldname)) then
1151  if (partid_grid) then
1152  call oasis_grid_loc2glo(prism_grid(n)%lon,rglo,partid,0)
1153  else
1154  rglo = prism_grid(n)%angle
1155  endif
1156  if (write_task) call oasis_io_write_2dgridfld_fromroot(filename,fldname,rglo,nx,ny)
1157  endif
1158  endif ! angle_set
1159 
1160  if (prism_grid(n)%mask_set) then
1161  if (tnx <= 0 .or. tny <= 0) then
1162  tnx = size(prism_grid(n)%mask,dim=1)
1163  tny = size(prism_grid(n)%mask,dim=2)
1164  endif
1165  if (size(prism_grid(n)%mask,dim=1) /= tnx .or. &
1166  size(prism_grid(n)%mask,dim=2) /= tny ) then
1167  write(nulprt,*) subname,estr,'inconsistent array size mask ',tnx,tny, &
1168  size(prism_grid(n)%mask,dim=1),size(prism_grid(n)%mask,dim=2)
1169  call oasis_abort(file=__file__,line=__line__)
1170  endif
1171 
1172  !-------------------------------------
1173  !> * Gather masks if needed and write from root
1174  !-------------------------------------
1175 
1176  filename = 'masks.nc'
1177  fldname = trim(cgrid)//'.msk'
1178  if (.not.oasis_io_varexists(filename,fldname)) then
1179  allocate(iglo(nx,ny))
1180  if (partid_grid) then
1181  allocate(rloc(tnx,tny))
1182  rloc = prism_grid(n)%mask
1183  call oasis_grid_loc2glo(rloc,rglo,partid,0)
1184  iglo = nint(rglo)
1185  deallocate(rloc)
1186  else
1187  iglo = prism_grid(n)%mask
1188  endif
1189  if (write_task) call oasis_io_write_2dgridint_fromroot(filename,fldname,iglo,nx,ny)
1190  deallocate(iglo)
1191  endif
1192  endif ! mask_set
1193 
1194  deallocate(rglo)
1195 
1196  endif ! active_task
1197 
1198  endif ! grid_name = gname
1199  endif ! terminated
1200  enddo ! n = 1,prism_ngrid
1201  enddo ! g = 1,gcnt
1202 
1203  deallocate(gname,pname)
1204 
1205  if (local_timers_on) call oasis_timer_stop('oasis_gridw_writefiles')
1206  endif ! writing_grids_call
1207 
1208  call oasis_timer_stop('oasis_gridw')
1209  call oasis_debug_exit(subname)
1210 
1211  END SUBROUTINE oasis_write2files
1212 !--------------------------------------------------------------------------
1213 
1214 !> Local interface to find gridID for a specified grid name
1215 
1216  SUBROUTINE oasis_findgrid(cgrid,nx,ny,gridID)
1217  !-------------------------------------------------
1218  ! Routine that sets gridID, identifies existing
1219  ! grid with cgrid name or starts a new one
1220  !-------------------------------------------------
1221  implicit none
1222 
1223  character(len=*), intent (in) :: cgrid !< grid name
1224  integer(kind=ip_intwp_p), intent (in) :: nx !< global nx size
1225  integer(kind=ip_intwp_p), intent (in) :: ny !< global ny size
1226  integer(kind=ip_intwp_p), intent(out) :: gridID !< gridID matching cgrid
1227  !-------------------------------------------------
1228  integer(kind=ip_intwp_p) :: n
1229  character(len=*),parameter :: subname = '(oasis_findgrid)'
1230  !-------------------------------------------------
1231 
1232  call oasis_debug_enter(subname)
1233  if (local_timers_on) call oasis_timer_start(trim(subname))
1234 
1235  gridid = -1
1236  do n = 1,prism_ngrid
1237  if (trim(cgrid) == trim(prism_grid(n)%gridname)) then
1238  gridid = n
1239  ! since grid is defined before, make sure nx,ny match
1240  if (nx /= prism_grid(gridid)%nx .or. ny /= prism_grid(gridid)%ny) then
1241  write(nulprt,*) subname,estr,'in predefined grid size = ',nx,ny, &
1242  prism_grid(gridid)%nx,prism_grid(gridid)%ny
1243  call oasis_abort(file=__file__,line=__line__)
1244  endif
1245  endif
1246  enddo
1247 
1248  if (gridid < 1) then
1250  gridid = prism_ngrid
1251  endif
1252 
1253  prism_grid(gridid)%gridname = trim(cgrid)
1254  prism_grid(gridid)%nx = nx
1255  prism_grid(gridid)%ny = ny
1256 
1257  if (local_timers_on) call oasis_timer_stop(trim(subname))
1258  call oasis_debug_exit(subname)
1259 
1260  END SUBROUTINE oasis_findgrid
1261 
1262 !--------------------------------------------------------------------------
1263 
1264 !> Local routine that gathers the local array using partition information
1265 
1266  SUBROUTINE oasis_grid_loc2glo(aloc,aglo,partid,taskid)
1267  implicit none
1268 
1269  real(kind=ip_realwp_p),intent(in) :: aloc(:,:) !< local array
1270  real(kind=ip_realwp_p),intent(inout) :: aglo(:,:) !< global array
1271  integer(kind=ip_i4_p) ,intent(in) :: partid !< partition id for local data
1272  integer(kind=ip_i4_p) ,intent(in) :: taskid !< task id to gather data to
1273  !-------------------------------------------------
1274  type(mct_avect) :: avloc,avglo
1275  integer(kind=ip_i4_p) :: i,j,n
1276  integer(kind=ip_i4_p) :: lnx,lny,gnx,gny
1277  character(len=*),parameter :: subname = '(oasis_grid_loc2glo)'
1278  !-------------------------------------------------
1279 
1280  call oasis_debug_enter(subname)
1281  if (local_timers_on) call oasis_timer_start(trim(subname))
1282 
1283  if (prism_part(partid)%mpicom /= mpi_comm_null) then
1284 
1285  lnx = size(aloc,dim=1)
1286  lny = size(aloc,dim=2)
1287  gnx = size(aglo,dim=1)
1288  gny = size(aglo,dim=2)
1289  call mct_avect_init(avloc,rlist='field',lsize=lnx*lny)
1290 
1291  n = 0
1292  do j = 1,lny
1293  do i = 1,lnx
1294  n = n + 1
1295  avloc%rattr(1,n) = aloc(i,j)
1296  enddo
1297  enddo
1298 
1299  call mct_avect_gather(avloc,avglo,prism_part(partid)%pgsmap,taskid,prism_part(partid)%mpicom)
1300 
1301  if (prism_part(partid)%rank == taskid) then
1302  n = 0
1303  do j = 1,gny
1304  do i = 1,gnx
1305  n = n + 1
1306  aglo(i,j) = avglo%rattr(1,n)
1307  enddo
1308  enddo
1309  call mct_avect_clean(avglo)
1310  endif
1311 
1312  call mct_avect_clean(avloc)
1313 
1314  endif
1315 
1316  if (local_timers_on) call oasis_timer_stop(trim(subname))
1317  call oasis_debug_exit(subname)
1318 
1319  END SUBROUTINE oasis_grid_loc2glo
1320 
1321 !--------------------------------------------------------------------------
1322 END MODULE mod_oasis_grid
1323 !--------------------------------------------------------------------------
1324 
1325 
1326 
subroutine, public oasis_write_mask(cgrid, nx, ny, mask, partid)
User interface to set integer mask values.
System type methods.
subroutine, public oasis_terminate_grids_writing()
User interface to indicate user defined grids are done.
subroutine oasis_write_grid_r8(cgrid, nx, ny, lon, lat, partid)
User interface to set latitudes and longitudes for 8 byte reals.
subroutine, public oasis_mpi_chkerr(rcode, string)
Checks MPI error codes and aborts.
Provides a common location for several OASIS variables.
Generic interface to support writing 4 or 8 byte reals.
subroutine oasis_write_corner_r8(cgrid, nx, ny, nc, clon, clat, partid)
User interface to set corner latitudes and longitudes for 8 byte reals.
Provides reusable IO routines for OASIS.
Definition: mod_oasis_io.F90:4
subroutine oasis_write_angle_r8(cgrid, nx, ny, angle, partid)
User interface to set angle for 8 byte reals.
Generic overloaded interface into MPI max reduction.
subroutine, public oasis_write2files()
Interface that actually writes fields to grid files.
type(prism_part_type), dimension(mpart), public prism_part
list of defined partitions
integer(kind=ip_intwp_p) nulprt
Generic overloaded interface into MPI broadcast.
Generic interface to support writing 4 or 8 byte reals.
type(prism_grid_type), dimension(mgrid), save, public prism_grid
array of grid datatypes
subroutine oasis_write_grid_r4(cgrid, nx, ny, lon, lat, partid)
User interface to set latitudes and longitudes for 4 byte reals.
subroutine, public oasis_abort(id_compid, cd_routine, cd_message, file, line, rcode)
OASIS abort method, publically available to users.
subroutine, public oasis_io_write_2dgridint_fromroot(filename, fldname, fld, nx, ny)
Write an integer array named field from the root task to a file.
subroutine oasis_grid_loc2glo(aloc, aglo, partid, taskid)
Local routine that gathers the local array using partition information.
subroutine, public oasis_io_write_2dgridfld_fromroot(filename, fldname, fld, nx, ny)
Write a real array named field from the root task to a file.
integer(kind=ip_i4_p) compid
Generic interface to support writing 4 or 8 byte reals.
subroutine oasis_write_area_r4(cgrid, nx, ny, area, partid)
User interface to set area values for 4 byte reals.
Generic interface to support writing 4 or 8 byte reals.
integer(kind=ip_i4_p) mpi_rank_local
Provides a generic and simpler interface into MPI calls for OASIS.
logical, parameter local_timers_on
subroutine, public oasis_debug_enter(string)
Used when a subroutine is entered, write info to log file at some debug level.
subroutine, public oasis_start_grids_writing(iwrite)
User interface to initialize grid writing.
Generic overloaded interface into MPI min reduction.
subroutine oasis_findgrid(cgrid, nx, ny, gridID)
Local interface to find gridID for a specified grid name.
subroutine, public oasis_mpi_reducelists(linp1, comm, cntout, lout1, callstr, fastcheck, fastcheckout, linp2, lout2, spval2, linp3, lout3, spval3, linp4, lout4, spval4)
Custom method for reducing MPI lists across pes for OASIS.
integer(kind=ip_intwp_p), parameter mgrid
maximum number of grids allowed
subroutine, public oasis_io_write_3dgridfld_fromroot(filename, fldname, fld, nx, ny, nc)
Write a 3d real array named field from the root task to a file.
OASIS partition data and methods.
subroutine, public oasis_print_grid_data()
Print grid information to log file.
integer(kind=ip_intwp_p), save writing_grids_call
OASIS grid data and methods.
subroutine oasis_write_corner_r4(cgrid, nx, ny, nc, clon, clat, partid)
User interface to set corner latitudes and longitudes for 4 byte reals.
subroutine, public oasis_timer_start(timer_label, barrier)
Start a timer.
integer(kind=ip_i4_p) oasis_debug
subroutine, public oasis_timer_stop(timer_label)
Stop a timer.
subroutine oasis_write_area_r8(cgrid, nx, ny, area, partid)
User interface to set area values for 8 byte reals.
character(len= *), parameter, public estr
integer(kind=ip_i4_p) mpi_comm_local
subroutine, public oasis_mpi_barrier(comm, string)
Call MPI_BARRIER for a particular communicator.
subroutine oasis_write_angle_r4(cgrid, nx, ny, angle, partid)
User interface to set angle for 4 byte reals.
integer(kind=ip_intwp_p), public prism_npart
number of partitions defined
logical function, public oasis_io_varexists(filename, fldname)
Checks whether the var fldname is in the file.
Model grid data for creating mapping data and conserving fields.
Performance timer methods.
subroutine, public oasis_debug_exit(string)
Used when a subroutine is exited, write info to log file at some debug level.
integer(kind=ip_intwp_p), save, public prism_ngrid
counter for grids