7 use mom_coms, only : pe_here, root_pe, num_pes, mom_infra_init, mom_infra_end
8 use mom_coms, only : broadcast, sum_across_pes, min_across_pes, max_across_pes
10 use mom_error_handler, only : mom_error, mom_mesg, note, warning, fatal, is_root_pe
15 use mpp_domains_mod
, only : mpp_define_layout, mpp_get_boundary
16 use mpp_domains_mod
, only : mom_define_io_domain => mpp_define_io_domain
17 use mpp_domains_mod
, only : mom_define_domain => mpp_define_domains
18 use mpp_domains_mod
, only : domain2d, domain1d, mpp_get_data_domain
19 use mpp_domains_mod
, only : mpp_get_compute_domain, mpp_get_global_domain
20 use mpp_domains_mod
, only : global_field_sum => mpp_global_sum
21 use mpp_domains_mod
, only : mpp_update_domains, cyclic_global_domain, fold_north_edge
22 use mpp_domains_mod
, only : mpp_start_update_domains, mpp_complete_update_domains
23 use mpp_domains_mod
, only : mpp_create_group_update, mpp_do_group_update
24 use mpp_domains_mod
, only : group_pass_type => mpp_group_update_type
25 use mpp_domains_mod
, only : mpp_reset_group_update_field
26 use mpp_domains_mod
, only : mpp_group_update_initialized
27 use mpp_domains_mod
, only : mpp_start_group_update, mpp_complete_group_update
28 use mpp_domains_mod
, only : compute_block_extent => mpp_compute_block_extent
29 use mpp_domains_mod
, only : agrid, bgrid_ne, cgrid_ne, scalar_pair, bitwise_exact_sum
30 use mpp_domains_mod
, only : to_east => wupdate, to_west => eupdate, omit_corners => edgeupdate
31 use mpp_domains_mod
, only : to_north => supdate, to_south => nupdate
32 use mpp_domains_mod
, only : center, corner, north_face => north, east_face => east
33 use fms_io_mod
, only : file_exist, parse_mask_table
34 use fms_affinity_mod
, only : fms_affinity_init, fms_affinity_set, fms_affinity_get
36 implicit none ;
private 38 public :: mom_domains_init, mom_infra_init, mom_infra_end, get_domain_extent, get_domain_extent_dsamp2
43 public :: global_field_sum, sum_across_pes, min_across_pes, max_across_pes
44 public :: agrid, bgrid_ne, cgrid_ne, scalar_pair, bitwise_exact_sum
45 public :: corner, center, north_face, east_face
46 public :: to_east, to_west, to_north, to_south, to_all, omit_corners
48 public :: start_group_pass, complete_group_pass
49 public :: compute_block_extent, get_global_shape
50 public :: get_simple_array_i_ind, get_simple_array_j_ind
55 module procedure pass_var_3d, pass_var_2d
60 module procedure pass_vector_3d, pass_vector_2d
65 module procedure pass_var_start_3d, pass_var_start_2d
70 module procedure pass_var_complete_3d, pass_var_complete_2d
75 module procedure pass_vector_start_3d, pass_vector_start_2d
80 module procedure pass_vector_complete_3d, pass_vector_complete_2d
85 module procedure create_var_group_pass_2d
86 module procedure create_var_group_pass_3d
87 module procedure create_vector_group_pass_2d
88 module procedure create_vector_group_pass_3d
94 module procedure fill_vector_symmetric_edges_2d
100 module procedure clone_md_to_md, clone_md_to_d2d
105 type(domain2d),
pointer :: mpp_domain => null()
107 type(domain2d),
pointer :: mpp_domain_d2 => null()
115 logical :: nonblocking_updates
117 logical :: thin_halo_updates
124 integer :: io_layout(2)
129 logical,
pointer :: maskmap(:,:) => null()
137 integer,
parameter :: to_all = to_east + to_west + to_north + to_south
142 subroutine pass_var_3d(array, MOM_dom, sideflag, complete, position, halo, &
144 real,
dimension(:,:,:),
intent(inout) :: array
149 integer,
optional,
intent(in) :: sideflag
153 logical,
optional,
intent(in) :: complete
157 integer,
optional,
intent(in) :: position
160 integer,
optional,
intent(in) :: halo
162 integer,
optional,
intent(in) :: clock
166 logical :: block_til_complete
168 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 171 if (
present(sideflag))
then ;
if (sideflag > 0) dirflag = sideflag ;
endif 172 block_til_complete = .true.
173 if (
present(complete)) block_til_complete = complete
175 if (
present(halo) .and. mom_dom%thin_halo_updates)
then 176 call mpp_update_domains(array, mom_dom%mpp_domain, flags=dirflag, &
177 complete=block_til_complete, position=position, &
178 whalo=halo, ehalo=halo, shalo=halo, nhalo=halo)
180 call mpp_update_domains(array, mom_dom%mpp_domain, flags=dirflag, &
181 complete=block_til_complete, position=position)
184 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 186 end subroutine pass_var_3d
189 subroutine pass_var_2d(array, MOM_dom, sideflag, complete, position, halo, inner_halo, clock)
190 real,
dimension(:,:),
intent(inout) :: array
194 integer,
optional,
intent(in) :: sideflag
198 logical,
optional,
intent(in) :: complete
202 integer,
optional,
intent(in) :: position
205 integer,
optional,
intent(in) :: halo
207 integer,
optional,
intent(in) :: inner_halo
211 integer,
optional,
intent(in) :: clock
215 real,
allocatable,
dimension(:,:) :: tmp
216 integer :: pos, i_halo, j_halo
217 integer :: isc, iec, jsc, jec, isd, ied, jsd, jed, IscB, IecB, JscB, JecB
218 integer :: inner, i, j, isfw, iefw, isfe, iefe, jsfs, jefs, jsfn, jefn
220 logical :: block_til_complete
222 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 225 if (
present(sideflag))
then ;
if (sideflag > 0) dirflag = sideflag ;
endif 226 block_til_complete = .true. ;
if (
present(complete)) block_til_complete = complete
227 pos = center ;
if (
present(position)) pos = position
229 if (
present(inner_halo))
then ;
if (inner_halo >= 0)
then 231 allocate(tmp(
size(array,1),
size(array,2)))
232 tmp(:,:) = array(:,:)
233 block_til_complete = .true.
236 if (
present(halo) .and. mom_dom%thin_halo_updates)
then 237 call mpp_update_domains(array, mom_dom%mpp_domain, flags=dirflag, &
238 complete=block_til_complete, position=position, &
239 whalo=halo, ehalo=halo, shalo=halo, nhalo=halo)
241 call mpp_update_domains(array, mom_dom%mpp_domain, flags=dirflag, &
242 complete=block_til_complete, position=position)
245 if (
present(inner_halo))
then ;
if (inner_halo >= 0)
then 246 call mpp_get_compute_domain(mom_dom%mpp_domain, isc, iec, jsc, jec)
247 call mpp_get_data_domain(mom_dom%mpp_domain, isd, ied, jsd, jed)
249 isc = isc - (isd-1) ; iec = iec - (isd-1) ; ied = ied - (isd-1) ; isd = 1
250 jsc = jsc - (jsd-1) ; jec = jec - (jsd-1) ; jed = jed - (jsd-1) ; jsd = 1
251 i_halo = min(inner_halo, isc-1) ; j_halo = min(inner_halo, jsc-1)
254 if (pos == center)
then 255 if (
size(array,1) == ied)
then 256 isfw = isc - i_halo ; iefw = isc ; isfe = iec ; iefe = iec + i_halo
257 else ;
call mom_error(fatal,
"pass_var_2d: wrong i-size for CENTER array.") ;
endif 258 if (
size(array,2) == jed)
then 259 isfw = isc - i_halo ; iefw = isc ; isfe = iec ; iefe = iec + i_halo
260 else ;
call mom_error(fatal,
"pass_var_2d: wrong j-size for CENTER array.") ;
endif 261 elseif (pos == corner)
then 262 if (
size(array,1) == ied)
then 263 isfw = max(isc - (i_halo+1), 1) ; iefw = isc ; isfe = iec ; iefe = iec + i_halo
264 elseif (
size(array,1) == ied+1)
then 265 isfw = isc - i_halo ; iefw = isc+1 ; isfe = iec+1 ; iefe = min(iec + 1 + i_halo, ied+1)
266 else ;
call mom_error(fatal,
"pass_var_2d: wrong i-size for CORNER array.") ;
endif 267 if (
size(array,2) == jed)
then 268 jsfs = max(jsc - (j_halo+1), 1) ; jefs = jsc ; jsfn = jec ; jefn = jec + j_halo
269 elseif (
size(array,2) == jed+1)
then 270 jsfs = jsc - j_halo ; jefs = jsc+1 ; jsfn = jec+1 ; jefn = min(jec + 1 + j_halo, jed+1)
271 else ;
call mom_error(fatal,
"pass_var_2d: wrong j-size for CORNER array.") ;
endif 272 elseif (pos == north_face)
then 273 if (
size(array,1) == ied)
then 274 isfw = isc - i_halo ; iefw = isc ; isfe = iec ; iefe = iec + i_halo
275 else ;
call mom_error(fatal,
"pass_var_2d: wrong i-size for NORTH_FACE array.") ;
endif 276 if (
size(array,2) == jed)
then 277 jsfs = max(jsc - (j_halo+1), 1) ; jefs = jsc ; jsfn = jec ; jefn = jec + j_halo
278 elseif (
size(array,2) == jed+1)
then 279 jsfs = jsc - j_halo ; jefs = jsc+1 ; jsfn = jec+1 ; jefn = min(jec + 1 + j_halo, jed+1)
280 else ;
call mom_error(fatal,
"pass_var_2d: wrong j-size for NORTH_FACE array.") ;
endif 281 elseif (pos == east_face)
then 282 if (
size(array,1) == ied)
then 283 isfw = max(isc - (i_halo+1), 1) ; iefw = isc ; isfe = iec ; iefe = iec + i_halo
284 elseif (
size(array,1) == ied+1)
then 285 isfw = isc - i_halo ; iefw = isc+1 ; isfe = iec+1 ; iefe = min(iec + 1 + i_halo, ied+1)
286 else ;
call mom_error(fatal,
"pass_var_2d: wrong i-size for EAST_FACE array.") ;
endif 287 if (
size(array,2) == jed)
then 288 isfw = isc - i_halo ; iefw = isc ; isfe = iec ; iefe = iec + i_halo
289 else ;
call mom_error(fatal,
"pass_var_2d: wrong j-size for EAST_FACE array.") ;
endif 291 call mom_error(fatal,
"pass_var_2d: Unrecognized position")
295 do j=jsfs,jefn ;
do i=isfw,iefw ; array(i,j) = tmp(i,j) ;
enddo ;
enddo 296 do j=jsfs,jefn ;
do i=isfe,iefe ; array(i,j) = tmp(i,j) ;
enddo ;
enddo 297 do j=jsfs,jefs ;
do i=isfw,iefe ; array(i,j) = tmp(i,j) ;
enddo ;
enddo 298 do j=jsfn,jefn ;
do i=isfw,iefe ; array(i,j) = tmp(i,j) ;
enddo ;
enddo 303 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 305 end subroutine pass_var_2d
308 function pass_var_start_2d(array, MOM_dom, sideflag, position, complete, halo, &
310 real,
dimension(:,:),
intent(inout) :: array
315 integer,
optional,
intent(in) :: sideflag
319 integer,
optional,
intent(in) :: position
322 logical,
optional,
intent(in) :: complete
326 integer,
optional,
intent(in) :: halo
328 integer,
optional,
intent(in) :: clock
330 integer :: pass_var_start_2d
334 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 337 if (
present(sideflag))
then ;
if (sideflag > 0) dirflag = sideflag ;
endif 339 if (
present(halo) .and. mom_dom%thin_halo_updates)
then 340 pass_var_start_2d = mpp_start_update_domains(array, mom_dom%mpp_domain, &
341 flags=dirflag, position=position, &
342 whalo=halo, ehalo=halo, shalo=halo, nhalo=halo)
344 pass_var_start_2d = mpp_start_update_domains(array, mom_dom%mpp_domain, &
345 flags=dirflag, position=position)
348 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 350 end function pass_var_start_2d
353 function pass_var_start_3d(array, MOM_dom, sideflag, position, complete, halo, &
355 real,
dimension(:,:,:),
intent(inout) :: array
360 integer,
optional,
intent(in) :: sideflag
364 integer,
optional,
intent(in) :: position
367 logical,
optional,
intent(in) :: complete
371 integer,
optional,
intent(in) :: halo
373 integer,
optional,
intent(in) :: clock
375 integer :: pass_var_start_3d
379 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 382 if (
present(sideflag))
then ;
if (sideflag > 0) dirflag = sideflag ;
endif 384 if (
present(halo) .and. mom_dom%thin_halo_updates)
then 385 pass_var_start_3d = mpp_start_update_domains(array, mom_dom%mpp_domain, &
386 flags=dirflag, position=position, &
387 whalo=halo, ehalo=halo, shalo=halo, nhalo=halo)
389 pass_var_start_3d = mpp_start_update_domains(array, mom_dom%mpp_domain, &
390 flags=dirflag, position=position)
393 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 395 end function pass_var_start_3d
398 subroutine pass_var_complete_2d(id_update, array, MOM_dom, sideflag, position, halo, &
400 integer,
intent(in) :: id_update
403 real,
dimension(:,:),
intent(inout) :: array
408 integer,
optional,
intent(in) :: sideflag
412 integer,
optional,
intent(in) :: position
415 integer,
optional,
intent(in) :: halo
417 integer,
optional,
intent(in) :: clock
422 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 425 if (
present(sideflag))
then ;
if (sideflag > 0) dirflag = sideflag ;
endif 427 if (
present(halo) .and. mom_dom%thin_halo_updates)
then 428 call mpp_complete_update_domains(id_update, array, mom_dom%mpp_domain, &
429 flags=dirflag, position=position, &
430 whalo=halo, ehalo=halo, shalo=halo, nhalo=halo)
432 call mpp_complete_update_domains(id_update, array, mom_dom%mpp_domain, &
433 flags=dirflag, position=position)
436 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 438 end subroutine pass_var_complete_2d
441 subroutine pass_var_complete_3d(id_update, array, MOM_dom, sideflag, position, halo, &
443 integer,
intent(in) :: id_update
446 real,
dimension(:,:,:),
intent(inout) :: array
451 integer,
optional,
intent(in) :: sideflag
455 integer,
optional,
intent(in) :: position
458 integer,
optional,
intent(in) :: halo
460 integer,
optional,
intent(in) :: clock
465 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 468 if (
present(sideflag))
then ;
if (sideflag > 0) dirflag = sideflag ;
endif 470 if (
present(halo) .and. mom_dom%thin_halo_updates)
then 471 call mpp_complete_update_domains(id_update, array, mom_dom%mpp_domain, &
472 flags=dirflag, position=position, &
473 whalo=halo, ehalo=halo, shalo=halo, nhalo=halo)
475 call mpp_complete_update_domains(id_update, array, mom_dom%mpp_domain, &
476 flags=dirflag, position=position)
479 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 481 end subroutine pass_var_complete_3d
485 subroutine pass_vector_2d(u_cmpt, v_cmpt, MOM_dom, direction, stagger, complete, halo, &
487 real,
dimension(:,:),
intent(inout) :: u_cmpt
490 real,
dimension(:,:),
intent(inout) :: v_cmpt
496 integer,
optional,
intent(in) :: direction
502 integer,
optional,
intent(in) :: stagger
505 logical,
optional,
intent(in) :: complete
508 integer,
optional,
intent(in) :: halo
510 integer,
optional,
intent(in) :: clock
514 integer :: stagger_local
516 logical :: block_til_complete
518 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 520 stagger_local = cgrid_ne
521 if (
present(stagger)) stagger_local = stagger
524 if (
present(direction))
then ;
if (direction > 0) dirflag = direction ;
endif 525 block_til_complete = .true.
526 if (
present(complete)) block_til_complete = complete
528 if (
present(halo) .and. mom_dom%thin_halo_updates)
then 529 call mpp_update_domains(u_cmpt, v_cmpt, mom_dom%mpp_domain, flags=dirflag, &
530 gridtype=stagger_local, complete = block_til_complete, &
531 whalo=halo, ehalo=halo, shalo=halo, nhalo=halo)
533 call mpp_update_domains(u_cmpt, v_cmpt, mom_dom%mpp_domain, flags=dirflag, &
534 gridtype=stagger_local, complete = block_til_complete)
537 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 539 end subroutine pass_vector_2d
546 subroutine fill_vector_symmetric_edges_2d(u_cmpt, v_cmpt, MOM_dom, stagger, scalar, &
548 real,
dimension(:,:),
intent(inout) :: u_cmpt
551 real,
dimension(:,:),
intent(inout) :: v_cmpt
557 integer,
optional,
intent(in) :: stagger
560 logical,
optional,
intent(in) :: scalar
561 integer,
optional,
intent(in) :: clock
565 integer :: stagger_local
567 integer :: i, j, isc, iec, jsc, jec, isd, ied, jsd, jed, IscB, IecB, JscB, JecB
568 real,
allocatable,
dimension(:) :: sbuff_x, sbuff_y, wbuff_x, wbuff_y
569 logical :: block_til_complete
571 if (.not. mom_dom%symmetric)
then 575 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 577 stagger_local = cgrid_ne
578 if (
present(stagger)) stagger_local = stagger
580 if (.not.(stagger_local == cgrid_ne .or. stagger_local == bgrid_ne))
return 582 call mpp_get_compute_domain(mom_dom%mpp_domain, isc, iec, jsc, jec)
583 call mpp_get_data_domain(mom_dom%mpp_domain, isd, ied, jsd, jed)
587 isc = isc - (isd-1) ; iec = iec - (isd-1)
588 jsc = jsc - (jsd-1) ; jec = jec - (jsd-1)
589 iscb = isc ; iecb = iec+1 ; jscb = jsc ; jecb = jec+1
592 if (
present(scalar))
then ;
if (scalar) dirflag = to_all+scalar_pair ;
endif 594 if (stagger_local == cgrid_ne)
then 595 allocate(wbuff_x(jsc:jec)) ;
allocate(sbuff_y(isc:iec))
596 wbuff_x(:) = 0.0 ; sbuff_y(:) = 0.0
597 call mpp_get_boundary(u_cmpt, v_cmpt, mom_dom%mpp_domain, flags=dirflag, &
598 wbufferx=wbuff_x, sbuffery=sbuff_y, &
601 v_cmpt(i,jscb) = sbuff_y(i)
604 u_cmpt(iscb,j) = wbuff_x(j)
606 deallocate(wbuff_x) ;
deallocate(sbuff_y)
607 elseif (stagger_local == bgrid_ne)
then 608 allocate(wbuff_x(jscb:jecb)) ;
allocate(sbuff_x(iscb:iecb))
609 allocate(wbuff_y(jscb:jecb)) ;
allocate(sbuff_y(iscb:iecb))
610 wbuff_x(:) = 0.0 ; wbuff_y(:) = 0.0 ; sbuff_x(:) = 0.0 ; sbuff_y(:) = 0.0
611 call mpp_get_boundary(u_cmpt, v_cmpt, mom_dom%mpp_domain, flags=dirflag, &
612 wbufferx=wbuff_x, sbufferx=sbuff_x, &
613 wbuffery=wbuff_y, sbuffery=sbuff_y, &
616 u_cmpt(i,jscb) = sbuff_x(i) ; v_cmpt(i,jscb) = sbuff_y(i)
619 u_cmpt(iscb,j) = wbuff_x(j) ; v_cmpt(iscb,j) = wbuff_y(j)
621 deallocate(wbuff_x) ;
deallocate(sbuff_x)
622 deallocate(wbuff_y) ;
deallocate(sbuff_y)
625 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 627 end subroutine fill_vector_symmetric_edges_2d
631 subroutine pass_vector_3d(u_cmpt, v_cmpt, MOM_dom, direction, stagger, complete, halo, &
633 real,
dimension(:,:,:),
intent(inout) :: u_cmpt
636 real,
dimension(:,:,:),
intent(inout) :: v_cmpt
642 integer,
optional,
intent(in) :: direction
648 integer,
optional,
intent(in) :: stagger
651 logical,
optional,
intent(in) :: complete
654 integer,
optional,
intent(in) :: halo
656 integer,
optional,
intent(in) :: clock
660 integer :: stagger_local
662 logical :: block_til_complete
664 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 666 stagger_local = cgrid_ne
667 if (
present(stagger)) stagger_local = stagger
670 if (
present(direction))
then ;
if (direction > 0) dirflag = direction ;
endif 671 block_til_complete = .true.
672 if (
present(complete)) block_til_complete = complete
674 if (
present(halo) .and. mom_dom%thin_halo_updates)
then 675 call mpp_update_domains(u_cmpt, v_cmpt, mom_dom%mpp_domain, flags=dirflag, &
676 gridtype=stagger_local, complete = block_til_complete, &
677 whalo=halo, ehalo=halo, shalo=halo, nhalo=halo)
679 call mpp_update_domains(u_cmpt, v_cmpt, mom_dom%mpp_domain, flags=dirflag, &
680 gridtype=stagger_local, complete = block_til_complete)
683 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 685 end subroutine pass_vector_3d
689 function pass_vector_start_2d(u_cmpt, v_cmpt, MOM_dom, direction, stagger, complete, halo, &
691 real,
dimension(:,:),
intent(inout) :: u_cmpt
694 real,
dimension(:,:),
intent(inout) :: v_cmpt
700 integer,
optional,
intent(in) :: direction
706 integer,
optional,
intent(in) :: stagger
709 logical,
optional,
intent(in) :: complete
712 integer,
optional,
intent(in) :: halo
714 integer,
optional,
intent(in) :: clock
716 integer :: pass_vector_start_2d
720 integer :: stagger_local
723 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 725 stagger_local = cgrid_ne
726 if (
present(stagger)) stagger_local = stagger
729 if (
present(direction))
then ;
if (direction > 0) dirflag = direction ;
endif 731 if (
present(halo) .and. mom_dom%thin_halo_updates)
then 732 pass_vector_start_2d = mpp_start_update_domains(u_cmpt, v_cmpt, &
733 mom_dom%mpp_domain, flags=dirflag, gridtype=stagger_local, &
734 whalo=halo, ehalo=halo, shalo=halo, nhalo=halo)
736 pass_vector_start_2d = mpp_start_update_domains(u_cmpt, v_cmpt, &
737 mom_dom%mpp_domain, flags=dirflag, gridtype=stagger_local)
740 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 742 end function pass_vector_start_2d
746 function pass_vector_start_3d(u_cmpt, v_cmpt, MOM_dom, direction, stagger, complete, halo, &
748 real,
dimension(:,:,:),
intent(inout) :: u_cmpt
751 real,
dimension(:,:,:),
intent(inout) :: v_cmpt
757 integer,
optional,
intent(in) :: direction
763 integer,
optional,
intent(in) :: stagger
766 logical,
optional,
intent(in) :: complete
769 integer,
optional,
intent(in) :: halo
771 integer,
optional,
intent(in) :: clock
773 integer :: pass_vector_start_3d
776 integer :: stagger_local
779 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 781 stagger_local = cgrid_ne
782 if (
present(stagger)) stagger_local = stagger
785 if (
present(direction))
then ;
if (direction > 0) dirflag = direction ;
endif 787 if (
present(halo) .and. mom_dom%thin_halo_updates)
then 788 pass_vector_start_3d = mpp_start_update_domains(u_cmpt, v_cmpt, &
789 mom_dom%mpp_domain, flags=dirflag, gridtype=stagger_local, &
790 whalo=halo, ehalo=halo, shalo=halo, nhalo=halo)
792 pass_vector_start_3d = mpp_start_update_domains(u_cmpt, v_cmpt, &
793 mom_dom%mpp_domain, flags=dirflag, gridtype=stagger_local)
796 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 798 end function pass_vector_start_3d
802 subroutine pass_vector_complete_2d(id_update, u_cmpt, v_cmpt, MOM_dom, direction, stagger, halo, &
804 integer,
intent(in) :: id_update
807 real,
dimension(:,:),
intent(inout) :: u_cmpt
810 real,
dimension(:,:),
intent(inout) :: v_cmpt
816 integer,
optional,
intent(in) :: direction
822 integer,
optional,
intent(in) :: stagger
825 integer,
optional,
intent(in) :: halo
827 integer,
optional,
intent(in) :: clock
830 integer :: stagger_local
833 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 835 stagger_local = cgrid_ne
836 if (
present(stagger)) stagger_local = stagger
839 if (
present(direction))
then ;
if (direction > 0) dirflag = direction ;
endif 841 if (
present(halo) .and. mom_dom%thin_halo_updates)
then 842 call mpp_complete_update_domains(id_update, u_cmpt, v_cmpt, &
843 mom_dom%mpp_domain, flags=dirflag, gridtype=stagger_local, &
844 whalo=halo, ehalo=halo, shalo=halo, nhalo=halo)
846 call mpp_complete_update_domains(id_update, u_cmpt, v_cmpt, &
847 mom_dom%mpp_domain, flags=dirflag, gridtype=stagger_local)
850 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 852 end subroutine pass_vector_complete_2d
856 subroutine pass_vector_complete_3d(id_update, u_cmpt, v_cmpt, MOM_dom, direction, stagger, halo, &
858 integer,
intent(in) :: id_update
861 real,
dimension(:,:,:),
intent(inout) :: u_cmpt
864 real,
dimension(:,:,:),
intent(inout) :: v_cmpt
870 integer,
optional,
intent(in) :: direction
876 integer,
optional,
intent(in) :: stagger
879 integer,
optional,
intent(in) :: halo
881 integer,
optional,
intent(in) :: clock
884 integer :: stagger_local
887 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 889 stagger_local = cgrid_ne
890 if (
present(stagger)) stagger_local = stagger
893 if (
present(direction))
then ;
if (direction > 0) dirflag = direction ;
endif 895 if (
present(halo) .and. mom_dom%thin_halo_updates)
then 896 call mpp_complete_update_domains(id_update, u_cmpt, v_cmpt, &
897 mom_dom%mpp_domain, flags=dirflag, gridtype=stagger_local, &
898 whalo=halo, ehalo=halo, shalo=halo, nhalo=halo)
900 call mpp_complete_update_domains(id_update, u_cmpt, v_cmpt, &
901 mom_dom%mpp_domain, flags=dirflag, gridtype=stagger_local)
904 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 906 end subroutine pass_vector_complete_3d
909 subroutine create_var_group_pass_2d(group, array, MOM_dom, sideflag, position, &
911 type(group_pass_type),
intent(inout) :: group
914 real,
dimension(:,:),
intent(inout) :: array
919 integer,
optional,
intent(in) :: sideflag
923 integer,
optional,
intent(in) :: position
926 integer,
optional,
intent(in) :: halo
928 integer,
optional,
intent(in) :: clock
933 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 936 if (
present(sideflag))
then ;
if (sideflag > 0) dirflag = sideflag ;
endif 938 if (mpp_group_update_initialized(group))
then 939 call mpp_reset_group_update_field(group,array)
940 elseif (
present(halo) .and. mom_dom%thin_halo_updates)
then 941 call mpp_create_group_update(group, array, mom_dom%mpp_domain, flags=dirflag, &
942 position=position, whalo=halo, ehalo=halo, &
943 shalo=halo, nhalo=halo)
945 call mpp_create_group_update(group, array, mom_dom%mpp_domain, flags=dirflag, &
949 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 951 end subroutine create_var_group_pass_2d
954 subroutine create_var_group_pass_3d(group, array, MOM_dom, sideflag, position, halo, &
956 type(group_pass_type),
intent(inout) :: group
959 real,
dimension(:,:,:),
intent(inout) :: array
964 integer,
optional,
intent(in) :: sideflag
968 integer,
optional,
intent(in) :: position
971 integer,
optional,
intent(in) :: halo
973 integer,
optional,
intent(in) :: clock
978 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 981 if (
present(sideflag))
then ;
if (sideflag > 0) dirflag = sideflag ;
endif 983 if (mpp_group_update_initialized(group))
then 984 call mpp_reset_group_update_field(group,array)
985 elseif (
present(halo) .and. mom_dom%thin_halo_updates)
then 986 call mpp_create_group_update(group, array, mom_dom%mpp_domain, flags=dirflag, &
987 position=position, whalo=halo, ehalo=halo, &
988 shalo=halo, nhalo=halo)
990 call mpp_create_group_update(group, array, mom_dom%mpp_domain, flags=dirflag, &
994 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 996 end subroutine create_var_group_pass_3d
999 subroutine create_vector_group_pass_2d(group, u_cmpt, v_cmpt, MOM_dom, direction, stagger, halo, &
1001 type(group_pass_type),
intent(inout) :: group
1004 real,
dimension(:,:),
intent(inout) :: u_cmpt
1007 real,
dimension(:,:),
intent(inout) :: v_cmpt
1014 integer,
optional,
intent(in) :: direction
1020 integer,
optional,
intent(in) :: stagger
1023 integer,
optional,
intent(in) :: halo
1025 integer,
optional,
intent(in) :: clock
1028 integer :: stagger_local
1031 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 1033 stagger_local = cgrid_ne
1034 if (
present(stagger)) stagger_local = stagger
1037 if (
present(direction))
then ;
if (direction > 0) dirflag = direction ;
endif 1039 if (mpp_group_update_initialized(group))
then 1040 call mpp_reset_group_update_field(group,u_cmpt, v_cmpt)
1041 elseif (
present(halo) .and. mom_dom%thin_halo_updates)
then 1042 call mpp_create_group_update(group, u_cmpt, v_cmpt, mom_dom%mpp_domain, &
1043 flags=dirflag, gridtype=stagger_local, whalo=halo, ehalo=halo, &
1044 shalo=halo, nhalo=halo)
1046 call mpp_create_group_update(group, u_cmpt, v_cmpt, mom_dom%mpp_domain, &
1047 flags=dirflag, gridtype=stagger_local)
1050 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 1052 end subroutine create_vector_group_pass_2d
1055 subroutine create_vector_group_pass_3d(group, u_cmpt, v_cmpt, MOM_dom, direction, stagger, halo, &
1057 type(group_pass_type),
intent(inout) :: group
1060 real,
dimension(:,:,:),
intent(inout) :: u_cmpt
1063 real,
dimension(:,:,:),
intent(inout) :: v_cmpt
1070 integer,
optional,
intent(in) :: direction
1076 integer,
optional,
intent(in) :: stagger
1079 integer,
optional,
intent(in) :: halo
1081 integer,
optional,
intent(in) :: clock
1085 integer :: stagger_local
1088 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 1090 stagger_local = cgrid_ne
1091 if (
present(stagger)) stagger_local = stagger
1094 if (
present(direction))
then ;
if (direction > 0) dirflag = direction ;
endif 1096 if (mpp_group_update_initialized(group))
then 1097 call mpp_reset_group_update_field(group,u_cmpt, v_cmpt)
1098 elseif (
present(halo) .and. mom_dom%thin_halo_updates)
then 1099 call mpp_create_group_update(group, u_cmpt, v_cmpt, mom_dom%mpp_domain, &
1100 flags=dirflag, gridtype=stagger_local, whalo=halo, ehalo=halo, &
1101 shalo=halo, nhalo=halo)
1103 call mpp_create_group_update(group, u_cmpt, v_cmpt, mom_dom%mpp_domain, &
1104 flags=dirflag, gridtype=stagger_local)
1107 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 1109 end subroutine create_vector_group_pass_3d
1112 subroutine do_group_pass(group, MOM_dom, clock)
1113 type(group_pass_type),
intent(inout) :: group
1119 integer,
optional,
intent(in) :: clock
1123 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 1125 call mpp_do_group_update(group, mom_dom%mpp_domain, d_type)
1127 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 1129 end subroutine do_group_pass
1132 subroutine start_group_pass(group, MOM_dom, clock)
1133 type(group_pass_type),
intent(inout) :: group
1139 integer,
optional,
intent(in) :: clock
1144 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 1146 call mpp_start_group_update(group, mom_dom%mpp_domain, d_type)
1148 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 1150 end subroutine start_group_pass
1153 subroutine complete_group_pass(group, MOM_dom, clock)
1154 type(group_pass_type),
intent(inout) :: group
1160 integer,
optional,
intent(in) :: clock
1164 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_begin(clock) ;
endif 1166 call mpp_complete_group_update(group, mom_dom%mpp_domain, d_type)
1168 if (
present(clock))
then ;
if (clock>0)
call cpu_clock_end(clock) ;
endif 1170 end subroutine complete_group_pass
1175 subroutine mom_domains_init(MOM_dom, param_file, symmetric, static_memory, &
1176 NIHALO, NJHALO, NIGLOBAL, NJGLOBAL, NIPROC, NJPROC, &
1177 min_halo, domain_name, include_name, param_suffix)
1182 logical,
optional,
intent(in) :: symmetric
1185 logical,
optional,
intent(in) :: static_memory
1188 integer,
optional,
intent(in) :: NIHALO
1190 integer,
optional,
intent(in) :: NJHALO
1192 integer,
optional,
intent(in) :: NIGLOBAL
1194 integer,
optional,
intent(in) :: NJGLOBAL
1196 integer,
optional,
intent(in) :: NIPROC
1198 integer,
optional,
intent(in) :: NJPROC
1200 integer,
dimension(2),
optional,
intent(inout) :: min_halo
1203 character(len=*),
optional,
intent(in) :: domain_name
1205 character(len=*),
optional,
intent(in) :: include_name
1207 character(len=*),
optional,
intent(in) :: param_suffix
1211 integer,
dimension(2) :: layout = (/ 1, 1 /)
1212 integer,
dimension(2) :: io_layout = (/ 0, 0 /)
1213 integer,
dimension(4) :: global_indices
1217 integer :: nihalo_dflt, njhalo_dflt
1218 integer :: pe, proc_used
1219 integer :: X_FLAGS, Y_FLAGS
1220 logical :: reentrant_x, reentrant_y, tripolar_N, is_static
1221 logical :: mask_table_exists
1222 character(len=128) :: mask_table, inputdir
1223 character(len=64) :: dom_name, inc_nm
1224 character(len=200) :: mesg
1226 integer :: xsiz, ysiz, nip_parsed, njp_parsed
1227 integer :: isc,iec,jsc,jec
1228 character(len=8) :: char_xsiz, char_ysiz, char_niglobal, char_njglobal
1229 character(len=40) :: nihalo_nm, njhalo_nm, layout_nm, io_layout_nm, masktable_nm
1230 character(len=40) :: niproc_nm, njproc_nm
1231 integer :: xhalo_d2,yhalo_d2
1233 #include "version_variable.h" 1234 character(len=40) :: mdl
1236 if (.not.
associated(mom_dom))
then 1238 allocate(mom_dom%mpp_domain)
1239 allocate(mom_dom%mpp_domain_d2)
1243 proc_used = num_pes()
1247 mom_dom%symmetric = .true.
1248 if (
present(symmetric))
then ; mom_dom%symmetric = symmetric ;
endif 1249 if (
present(min_halo)) mdl = trim(mdl)//
" min_halo" 1251 dom_name =
"MOM" ; inc_nm =
"MOM_memory.h" 1252 if (
present(domain_name)) dom_name = trim(domain_name)
1253 if (
present(include_name)) inc_nm = trim(include_name)
1255 nihalo_nm =
"NIHALO" ; njhalo_nm =
"NJHALO" 1256 layout_nm =
"LAYOUT" ; io_layout_nm =
"IO_LAYOUT" ; masktable_nm =
"MASKTABLE" 1257 niproc_nm =
"NIPROC" ; njproc_nm =
"NJPROC" 1258 if (
present(param_suffix))
then ;
if (len(trim(adjustl(param_suffix))) > 0)
then 1259 nihalo_nm =
"NIHALO"//(trim(adjustl(param_suffix)))
1260 njhalo_nm =
"NJHALO"//(trim(adjustl(param_suffix)))
1261 layout_nm =
"LAYOUT"//(trim(adjustl(param_suffix)))
1262 io_layout_nm =
"IO_LAYOUT"//(trim(adjustl(param_suffix)))
1263 masktable_nm =
"MASKTABLE"//(trim(adjustl(param_suffix)))
1264 niproc_nm =
"NIPROC"//(trim(adjustl(param_suffix)))
1265 njproc_nm =
"NJPROC"//(trim(adjustl(param_suffix)))
1268 is_static = .false. ;
if (
present(static_memory)) is_static = static_memory
1270 if (.not.
present(nihalo))
call mom_error(fatal,
"NIHALO must be "// &
1271 "present in the call to MOM_domains_init with static memory.")
1272 if (.not.
present(njhalo))
call mom_error(fatal,
"NJHALO must be "// &
1273 "present in the call to MOM_domains_init with static memory.")
1274 if (.not.
present(niglobal))
call mom_error(fatal,
"NIGLOBAL must be "// &
1275 "present in the call to MOM_domains_init with static memory.")
1276 if (.not.
present(njglobal))
call mom_error(fatal,
"NJGLOBAL must be "// &
1277 "present in the call to MOM_domains_init with static memory.")
1278 if (.not.
present(niproc))
call mom_error(fatal,
"NIPROC must be "// &
1279 "present in the call to MOM_domains_init with static memory.")
1280 if (.not.
present(njproc))
call mom_error(fatal,
"NJPROC must be "// &
1281 "present in the call to MOM_domains_init with static memory.")
1285 call log_version(param_file, mdl, version,
"", log_to_all=.true., layout=.true.)
1286 call get_param(param_file, mdl,
"REENTRANT_X", reentrant_x, &
1287 "If true, the domain is zonally reentrant.", default=.true.)
1288 call get_param(param_file, mdl,
"REENTRANT_Y", reentrant_y, &
1289 "If true, the domain is meridionally reentrant.", &
1291 call get_param(param_file, mdl,
"TRIPOLAR_N", tripolar_n, &
1292 "Use tripolar connectivity at the northern edge of the "//&
1293 "domain. With TRIPOLAR_N, NIGLOBAL must be even.", &
1296 #ifndef NOT_SET_AFFINITY 1315 call log_param(param_file, mdl,
"!SYMMETRIC_MEMORY_", mom_dom%symmetric, &
1316 "If defined, the velocity point data domain includes "//&
1317 "every face of the thickness points. In other words, "//&
1318 "some arrays are larger than others, depending on where "//&
1319 "they are on the staggered grid. Also, the starting "//&
1320 "index of the velocity-point arrays is usually 0, not 1. "//&
1321 "This can only be set at compile time.",&
1323 call get_param(param_file, mdl,
"NONBLOCKING_UPDATES", mom_dom%nonblocking_updates, &
1324 "If true, non-blocking halo updates may be used.", &
1325 default=.false., layoutparam=.true.)
1326 call get_param(param_file, mdl,
"THIN_HALO_UPDATES", mom_dom%thin_halo_updates, &
1327 "If true, optional arguments may be used to specify the "//&
1328 "the width of the halos that are updated with each call.", &
1329 default=.true., layoutparam=.true.)
1331 nihalo_dflt = 4 ; njhalo_dflt = 4
1332 if (
present(nihalo)) nihalo_dflt = nihalo
1333 if (
present(njhalo)) njhalo_dflt = njhalo
1335 call log_param(param_file, mdl,
"!STATIC_MEMORY_", is_static, &
1336 "If STATIC_MEMORY_ is defined, the principle variables "//&
1337 "will have sizes that are statically determined at "//&
1338 "compile time. Otherwise the sizes are not determined "//&
1339 "until run time. The STATIC option is substantially "//&
1340 "faster, but does not allow the PE count to be changed "//&
1341 "at run time. This can only be set at compile time.",&
1345 call get_param(param_file, mdl,
"NIGLOBAL", mom_dom%niglobal, &
1346 "The total number of thickness grid points in the "//&
1347 "x-direction in the physical domain. With STATIC_MEMORY_ "//&
1348 "this is set in "//trim(inc_nm)//
" at compile time.", &
1349 static_value=niglobal)
1350 call get_param(param_file, mdl,
"NJGLOBAL", mom_dom%njglobal, &
1351 "The total number of thickness grid points in the "//&
1352 "y-direction in the physical domain. With STATIC_MEMORY_ "//&
1353 "this is set in "//trim(inc_nm)//
" at compile time.", &
1354 static_value=njglobal)
1355 if (mom_dom%niglobal /= niglobal)
call mom_error(fatal,
"MOM_domains_init: " // &
1356 "static mismatch for NIGLOBAL_ domain size. Header file does not match input namelist")
1357 if (mom_dom%njglobal /= njglobal)
call mom_error(fatal,
"MOM_domains_init: " // &
1358 "static mismatch for NJGLOBAL_ domain size. Header file does not match input namelist")
1361 call get_param(param_file, mdl,
"NIGLOBAL", mom_dom%niglobal, &
1362 "The total number of thickness grid points in the "//&
1363 "x-direction in the physical domain. With STATIC_MEMORY_ "//&
1364 "this is set in "//trim(inc_nm)//
" at compile time.", &
1365 fail_if_missing=.true.)
1366 call get_param(param_file, mdl,
"NJGLOBAL", mom_dom%njglobal, &
1367 "The total number of thickness grid points in the "//&
1368 "y-direction in the physical domain. With STATIC_MEMORY_ "//&
1369 "this is set in "//trim(inc_nm)//
" at compile time.", &
1370 fail_if_missing=.true.)
1373 call get_param(param_file, mdl, trim(nihalo_nm), mom_dom%nihalo, &
1374 "The number of halo points on each side in the x-direction. How this is set "//&
1375 "varies with the calling component and static or dynamic memory configuration.", &
1376 default=nihalo_dflt, static_value=nihalo_dflt)
1377 call get_param(param_file, mdl, trim(njhalo_nm), mom_dom%njhalo, &
1378 "The number of halo points on each side in the y-direction. How this is set "//&
1379 "varies with the calling component and static or dynamic memory configuration.", &
1380 default=njhalo_dflt, static_value=njhalo_dflt)
1381 if (
present(min_halo))
then 1382 mom_dom%nihalo = max(mom_dom%nihalo, min_halo(1))
1383 min_halo(1) = mom_dom%nihalo
1384 mom_dom%njhalo = max(mom_dom%njhalo, min_halo(2))
1385 min_halo(2) = mom_dom%njhalo
1387 call log_param(param_file, mdl,
"!NIHALO min_halo", mom_dom%nihalo, layoutparam=.true.)
1388 call log_param(param_file, mdl,
"!NJHALO min_halo", mom_dom%nihalo, layoutparam=.true.)
1390 if (is_static .and. .not.
present(min_halo))
then 1391 if (mom_dom%nihalo /= nihalo)
call mom_error(fatal,
"MOM_domains_init: " // &
1392 "static mismatch for "//trim(nihalo_nm)//
" domain size")
1393 if (mom_dom%njhalo /= njhalo)
call mom_error(fatal,
"MOM_domains_init: " // &
1394 "static mismatch for "//trim(njhalo_nm)//
" domain size")
1397 global_indices(1) = 1 ; global_indices(2) = mom_dom%niglobal
1398 global_indices(3) = 1 ; global_indices(4) = mom_dom%njglobal
1400 call get_param(param_file, mdl,
"INPUTDIR", inputdir, do_not_log=.true., default=
".")
1401 inputdir = slasher(inputdir)
1403 call get_param(param_file, mdl, trim(masktable_nm), mask_table, &
1404 "A text file to specify n_mask, layout and mask_list. "//&
1405 "This feature masks out processors that contain only land points. "//&
1406 "The first line of mask_table is the number of regions to be masked out. "//&
1407 "The second line is the layout of the model and must be "//&
1408 "consistent with the actual model layout. "//&
1409 "The following (n_mask) lines give the logical positions "//&
1410 "of the processors that are masked out. The mask_table "//&
1411 "can be created by tools like check_mask. The "//&
1412 "following example of mask_table masks out 2 processors, "//&
1413 "(1,2) and (3,6), out of the 24 in a 4x6 layout: \n"//&
1414 " 2\n 4,6\n 1,2\n 3,6\n", default=
"MOM_mask_table", &
1416 mask_table = trim(inputdir)//trim(mask_table)
1417 mask_table_exists = file_exist(mask_table)
1420 layout(1) = niproc ; layout(2) = njproc
1422 call get_param(param_file, mdl, trim(layout_nm), layout, &
1423 "The processor layout to be used, or 0, 0 to automatically "//&
1424 "set the layout based on the number of processors.", default=0, &
1426 call get_param(param_file, mdl, trim(niproc_nm), nip_parsed, &
1427 "The number of processors in the x-direction.", default=-1, &
1429 call get_param(param_file, mdl, trim(njproc_nm), njp_parsed, &
1430 "The number of processors in the y-direction.", default=-1, &
1432 if (nip_parsed > -1)
then 1433 if ((layout(1) > 0) .and. (layout(1) /= nip_parsed)) &
1434 call mom_error(fatal, trim(layout_nm)//
" and "//trim(niproc_nm)//
" set inconsistently. "//&
1435 "Only LAYOUT should be used.")
1436 layout(1) = nip_parsed
1437 call mom_mesg(trim(niproc_nm)//
" used to set "//trim(layout_nm)//
" in dynamic mode. "//&
1438 "Shift to using "//trim(layout_nm)//
" instead.")
1440 if (njp_parsed > -1)
then 1441 if ((layout(2) > 0) .and. (layout(2) /= njp_parsed)) &
1442 call mom_error(fatal, trim(layout_nm)//
" and "//trim(njproc_nm)//
" set inconsistently. "//&
1443 "Only "//trim(layout_nm)//
" should be used.")
1444 layout(2) = njp_parsed
1445 call mom_mesg(trim(njproc_nm)//
" used to set "//trim(layout_nm)//
" in dynamic mode. "//&
1446 "Shift to using "//trim(layout_nm)//
" instead.")
1449 if ( layout(1)==0 .and. layout(2)==0 ) &
1450 call mpp_define_layout(global_indices, proc_used, layout)
1451 if ( layout(1)/=0 .and. layout(2)==0 ) layout(2) = proc_used/layout(1)
1452 if ( layout(1)==0 .and. layout(2)/=0 ) layout(1) = proc_used/layout(2)
1454 if (layout(1)*layout(2) /= proc_used .and. (.not. mask_table_exists) )
then 1455 write(mesg,
'("MOM_domains_init: The product of the two components of layout, ", & 1456 & 2i4,", is not the number of PEs used, ",i5,".")') &
1457 layout(1),layout(2),proc_used
1458 call mom_error(fatal, mesg)
1461 call log_param(param_file, mdl, trim(niproc_nm), layout(1), &
1462 "The number of processors in the x-direction. With "//&
1463 "STATIC_MEMORY_ this is set in "//trim(inc_nm)//
" at compile time.",&
1465 call log_param(param_file, mdl, trim(njproc_nm), layout(2), &
1466 "The number of processors in the y-direction. With "//&
1467 "STATIC_MEMORY_ this is set in "//trim(inc_nm)//
" at compile time.",&
1469 call log_param(param_file, mdl, trim(layout_nm), layout, &
1470 "The processor layout that was actually used.",&
1474 if (layout(1)*layout(2)>mom_dom%niglobal*mom_dom%njglobal)
then 1475 write(mesg,
'(a,2(i5,x,a))')
'You requested to use',layout(1)*layout(2), &
1476 'PEs but there are only',mom_dom%niglobal*mom_dom%njglobal,
'columns in the model' 1477 call mom_error(fatal, mesg)
1480 if (mask_table_exists)
then 1481 call mom_error(note,
'MOM_domains_init: reading maskmap information from '//&
1483 allocate(mom_dom%maskmap(layout(1), layout(2)))
1484 call parse_mask_table(mask_table, mom_dom%maskmap, dom_name)
1489 io_layout(:) = (/ 1, 1 /)
1490 call get_param(param_file, mdl, trim(io_layout_nm), io_layout, &
1491 "The processor layout to be used, or 0,0 to automatically "//&
1492 "set the io_layout to be the same as the layout.", default=1, &
1495 if (io_layout(1) < 0)
then 1496 write(mesg,
'("MOM_domains_init: IO_LAYOUT(1) = ",i4,". Negative values "//& 1497 &"are not allowed in ")') io_layout(1)
1498 call mom_error(fatal, mesg//trim(io_layout_nm))
1499 elseif (io_layout(1) > 0)
then ;
if (modulo(layout(1), io_layout(1)) /= 0)
then 1500 write(mesg,
'("MOM_domains_init: The i-direction I/O-layout, IO_LAYOUT(1)=",i4, & 1501 &", does not evenly divide the i-direction layout, NIPROC=,",i4,".")') &
1502 io_layout(1),layout(1)
1503 call mom_error(fatal, mesg)
1506 if (io_layout(2) < 0)
then 1507 write(mesg,
'("MOM_domains_init: IO_LAYOUT(2) = ",i4,". Negative values "//& 1508 &"are not allowed in ")') io_layout(2)
1509 call mom_error(fatal, mesg//trim(io_layout_nm))
1510 elseif (io_layout(2) /= 0)
then ;
if (modulo(layout(2), io_layout(2)) /= 0)
then 1511 write(mesg,
'("MOM_domains_init: The j-direction I/O-layout, IO_LAYOUT(2)=",i4, & 1512 &", does not evenly divide the j-direction layout, NJPROC=,",i4,".")') &
1513 io_layout(2),layout(2)
1514 call mom_error(fatal, mesg)
1517 if (io_layout(2) == 0) io_layout(2) = layout(2)
1518 if (io_layout(1) == 0) io_layout(1) = layout(1)
1520 x_flags = 0 ; y_flags = 0
1521 if (reentrant_x) x_flags = cyclic_global_domain
1522 if (reentrant_y) y_flags = cyclic_global_domain
1523 if (tripolar_n)
then 1524 y_flags = fold_north_edge
1525 if (reentrant_y)
call mom_error(fatal,
"MOM_domains: "// &
1526 "TRIPOLAR_N and REENTRANT_Y may not be defined together.")
1529 global_indices(1) = 1 ; global_indices(2) = mom_dom%niglobal
1530 global_indices(3) = 1 ; global_indices(4) = mom_dom%njglobal
1532 if (mask_table_exists)
then 1533 call mom_define_domain( global_indices, layout, mom_dom%mpp_domain, &
1534 xflags=x_flags, yflags=y_flags, &
1535 xhalo=mom_dom%nihalo, yhalo=mom_dom%njhalo, &
1536 symmetry = mom_dom%symmetric, name=dom_name, &
1537 maskmap=mom_dom%maskmap )
1539 call mom_define_domain( global_indices, layout, mom_dom%mpp_domain, &
1540 xflags=x_flags, yflags=y_flags, &
1541 xhalo=mom_dom%nihalo, yhalo=mom_dom%njhalo, &
1542 symmetry = mom_dom%symmetric, name=dom_name)
1545 if ((io_layout(1) > 0) .and. (io_layout(2) > 0) .and. &
1546 (layout(1)*layout(2) > 1))
then 1547 call mom_define_io_domain(mom_dom%mpp_domain, io_layout)
1551 mom_dom%X_FLAGS = x_flags
1552 mom_dom%Y_FLAGS = y_flags
1553 mom_dom%layout = layout
1554 mom_dom%io_layout = io_layout
1559 call mpp_get_compute_domain(mom_dom%mpp_domain,isc,iec,jsc,jec)
1560 xsiz = iec - isc + 1
1561 ysiz = jec - jsc + 1
1562 if (xsiz*niproc /= mom_dom%niglobal .OR. ysiz*njproc /= mom_dom%njglobal)
then 1563 write( char_xsiz,
'(i4)' ) niproc
1564 write( char_ysiz,
'(i4)' ) njproc
1565 write( char_niglobal,
'(i4)' ) mom_dom%niglobal
1566 write( char_njglobal,
'(i4)' ) mom_dom%njglobal
1567 call mom_error(warning,
'MOM_domains: Processor decomposition (NIPROC_,NJPROC_) = (' &
1568 //trim(char_xsiz)//
','//trim(char_ysiz)// &
1569 ') does not evenly divide size set by preprocessor macro ('&
1570 //trim(char_niglobal)//
','//trim(char_njglobal)//
'). ')
1571 call mom_error(fatal,
'MOM_domains: #undef STATIC_MEMORY_ in "//trim(inc_nm)//" to use & 1572 &dynamic allocation, or change processor decomposition to evenly divide the domain.')
1576 global_indices(1) = 1 ; global_indices(2) = int(mom_dom%niglobal/2)
1577 global_indices(3) = 1 ; global_indices(4) = int(mom_dom%njglobal/2)
1581 xhalo_d2 = int(mom_dom%nihalo/2)
1582 yhalo_d2 = int(mom_dom%njhalo/2)
1583 if (mask_table_exists)
then 1584 call mom_define_domain( global_indices, layout, mom_dom%mpp_domain_d2, &
1585 xflags=x_flags, yflags=y_flags, &
1586 xhalo=xhalo_d2, yhalo=yhalo_d2, &
1587 symmetry = mom_dom%symmetric, name=trim(
"MOMc"), &
1588 maskmap=mom_dom%maskmap )
1590 call mom_define_domain( global_indices, layout, mom_dom%mpp_domain_d2, &
1591 xflags=x_flags, yflags=y_flags, &
1592 xhalo=xhalo_d2, yhalo=yhalo_d2, &
1593 symmetry = mom_dom%symmetric, name=trim(
"MOMc"))
1596 if ((io_layout(1) > 0) .and. (io_layout(2) > 0) .and. &
1597 (layout(1)*layout(2) > 1))
then 1598 call mom_define_io_domain(mom_dom%mpp_domain_d2, io_layout)
1601 end subroutine mom_domains_init
1605 subroutine clone_md_to_md(MD_in, MOM_dom, min_halo, halo_size, symmetric, &
1611 integer,
dimension(2), &
1612 optional,
intent(inout) :: min_halo
1615 integer,
optional,
intent(in) :: halo_size
1618 logical,
optional,
intent(in) :: symmetric
1622 optional,
intent(in) :: domain_name
1624 integer,
optional,
intent(in) :: turns
1626 integer :: global_indices(4)
1627 logical :: mask_table_exists
1628 character(len=64) :: dom_name
1632 if (
present(turns)) qturns = turns
1634 if (.not.
associated(mom_dom))
then 1636 allocate(mom_dom%mpp_domain)
1637 allocate(mom_dom%mpp_domain_d2)
1641 mom_dom%symmetric = md_in%symmetric
1642 mom_dom%nonblocking_updates = md_in%nonblocking_updates
1643 mom_dom%thin_halo_updates = md_in%thin_halo_updates
1645 if (modulo(qturns, 2) /= 0)
then 1646 mom_dom%niglobal = md_in%njglobal ; mom_dom%njglobal = md_in%niglobal
1647 mom_dom%nihalo = md_in%njhalo ; mom_dom%njhalo = md_in%nihalo
1649 mom_dom%X_FLAGS = md_in%Y_FLAGS ; mom_dom%Y_FLAGS = md_in%X_FLAGS
1650 mom_dom%layout(:) = md_in%layout(2:1:-1)
1651 mom_dom%io_layout(:) = md_in%io_layout(2:1:-1)
1653 mom_dom%niglobal = md_in%niglobal ; mom_dom%njglobal = md_in%njglobal
1654 mom_dom%nihalo = md_in%nihalo ; mom_dom%njhalo = md_in%njhalo
1656 mom_dom%X_FLAGS = md_in%X_FLAGS ; mom_dom%Y_FLAGS = md_in%Y_FLAGS
1657 mom_dom%layout(:) = md_in%layout(:)
1658 mom_dom%io_layout(:) = md_in%io_layout(:)
1661 global_indices(1) = 1 ; global_indices(2) = mom_dom%niglobal
1662 global_indices(3) = 1 ; global_indices(4) = mom_dom%njglobal
1664 if (
associated(md_in%maskmap))
then 1665 mask_table_exists = .true.
1666 allocate(mom_dom%maskmap(mom_dom%layout(1), mom_dom%layout(2)))
1667 if (qturns /= 0)
then 1668 call rotate_array(md_in%maskmap(:,:), qturns, mom_dom%maskmap(:,:))
1670 mom_dom%maskmap(:,:) = md_in%maskmap(:,:)
1673 mask_table_exists = .false.
1676 if (
present(halo_size) .and.
present(min_halo))
call mom_error(fatal, &
1677 "clone_MOM_domain can not have both halo_size and min_halo present.")
1679 if (
present(min_halo))
then 1680 mom_dom%nihalo = max(mom_dom%nihalo, min_halo(1))
1681 min_halo(1) = mom_dom%nihalo
1682 mom_dom%njhalo = max(mom_dom%njhalo, min_halo(2))
1683 min_halo(2) = mom_dom%njhalo
1686 if (
present(halo_size))
then 1687 mom_dom%nihalo = halo_size ; mom_dom%njhalo = halo_size
1690 if (
present(symmetric))
then ; mom_dom%symmetric = symmetric ;
endif 1693 if (
present(domain_name)) dom_name = trim(domain_name)
1695 if (mask_table_exists)
then 1696 call mom_define_domain(global_indices, mom_dom%layout, mom_dom%mpp_domain, &
1697 xflags=mom_dom%X_FLAGS, yflags=mom_dom%Y_FLAGS, &
1698 xhalo=mom_dom%nihalo, yhalo=mom_dom%njhalo, &
1699 symmetry=mom_dom%symmetric, name=dom_name, &
1700 maskmap=mom_dom%maskmap)
1702 global_indices(2) = global_indices(2) / 2
1703 global_indices(4) = global_indices(4) / 2
1704 call mom_define_domain(global_indices, mom_dom%layout, &
1705 mom_dom%mpp_domain_d2, &
1706 xflags=mom_dom%X_FLAGS, yflags=mom_dom%Y_FLAGS, &
1707 xhalo=(mom_dom%nihalo/2), yhalo=(mom_dom%njhalo/2), &
1708 symmetry=mom_dom%symmetric, name=dom_name, &
1709 maskmap=mom_dom%maskmap)
1711 call mom_define_domain(global_indices, mom_dom%layout, mom_dom%mpp_domain, &
1712 xflags=mom_dom%X_FLAGS, yflags=mom_dom%Y_FLAGS, &
1713 xhalo=mom_dom%nihalo, yhalo=mom_dom%njhalo, &
1714 symmetry=mom_dom%symmetric, name=dom_name)
1716 global_indices(2) = global_indices(2) / 2
1717 global_indices(4) = global_indices(4) / 2
1718 call mom_define_domain(global_indices, mom_dom%layout, &
1719 mom_dom%mpp_domain_d2, &
1720 xflags=mom_dom%X_FLAGS, yflags=mom_dom%Y_FLAGS, &
1721 xhalo=(mom_dom%nihalo/2), yhalo=(mom_dom%njhalo/2), &
1722 symmetry=mom_dom%symmetric, name=dom_name)
1725 if ((mom_dom%io_layout(1) + mom_dom%io_layout(2) > 0) .and. &
1726 (mom_dom%layout(1)*mom_dom%layout(2) > 1))
then 1727 call mom_define_io_domain(mom_dom%mpp_domain, mom_dom%io_layout)
1730 end subroutine clone_md_to_md
1735 subroutine clone_md_to_d2d(MD_in, mpp_domain, min_halo, halo_size, symmetric, &
1738 type(domain2d),
intent(inout) :: mpp_domain
1739 integer,
dimension(2), &
1740 optional,
intent(inout) :: min_halo
1743 integer,
optional,
intent(in) :: halo_size
1746 logical,
optional,
intent(in) :: symmetric
1750 optional,
intent(in) :: domain_name
1752 integer,
optional,
intent(in) :: turns
1754 integer :: global_indices(4), layout(2), io_layout(2)
1755 integer :: X_FLAGS, Y_FLAGS, niglobal, njglobal, nihalo, njhalo
1756 logical :: symmetric_dom
1757 character(len=64) :: dom_name
1759 if (
present(turns)) &
1760 call mom_error(fatal,
"Rotation not supported for MOM_domain to domain2d")
1763 niglobal = md_in%niglobal ; njglobal = md_in%njglobal
1764 nihalo = md_in%nihalo ; njhalo = md_in%njhalo
1766 symmetric_dom = md_in%symmetric
1768 x_flags = md_in%X_FLAGS ; y_flags = md_in%Y_FLAGS
1769 layout(:) = md_in%layout(:) ; io_layout(:) = md_in%io_layout(:)
1771 if (
present(halo_size) .and.
present(min_halo))
call mom_error(fatal, &
1772 "clone_MOM_domain can not have both halo_size and min_halo present.")
1774 if (
present(min_halo))
then 1775 nihalo = max(nihalo, min_halo(1))
1776 njhalo = max(njhalo, min_halo(2))
1777 min_halo(1) = nihalo ; min_halo(2) = njhalo
1780 if (
present(halo_size))
then 1781 nihalo = halo_size ; njhalo = halo_size
1784 if (
present(symmetric))
then ; symmetric_dom = symmetric ;
endif 1787 if (
present(domain_name)) dom_name = trim(domain_name)
1789 global_indices(1) = 1 ; global_indices(2) = niglobal
1790 global_indices(3) = 1 ; global_indices(4) = njglobal
1791 if (
associated(md_in%maskmap))
then 1792 call mom_define_domain( global_indices, layout, mpp_domain, &
1793 xflags=x_flags, yflags=y_flags, &
1794 xhalo=nihalo, yhalo=njhalo, &
1795 symmetry = symmetric, name=dom_name, &
1796 maskmap=md_in%maskmap )
1798 call mom_define_domain( global_indices, layout, mpp_domain, &
1799 xflags=x_flags, yflags=y_flags, &
1800 xhalo=nihalo, yhalo=njhalo, &
1801 symmetry = symmetric, name=dom_name)
1804 if ((io_layout(1) + io_layout(2) > 0) .and. &
1805 (layout(1)*layout(2) > 1))
then 1806 call mom_define_io_domain(mpp_domain, io_layout)
1809 end subroutine clone_md_to_d2d
1812 subroutine get_domain_extent(Domain, isc, iec, jsc, jec, isd, ied, jsd, jed, &
1813 isg, ieg, jsg, jeg, idg_offset, jdg_offset, &
1814 symmetric, local_indexing, index_offset)
1816 intent(in) :: Domain
1817 integer,
intent(out) :: isc
1818 integer,
intent(out) :: iec
1819 integer,
intent(out) :: jsc
1820 integer,
intent(out) :: jec
1821 integer,
intent(out) :: isd
1822 integer,
intent(out) :: ied
1823 integer,
intent(out) :: jsd
1824 integer,
intent(out) :: jed
1825 integer,
intent(out) :: isg
1826 integer,
intent(out) :: ieg
1827 integer,
intent(out) :: jsg
1828 integer,
intent(out) :: jeg
1829 integer,
intent(out) :: idg_offset
1831 integer,
intent(out) :: jdg_offset
1833 logical,
intent(out) :: symmetric
1834 logical,
optional,
intent(in) :: local_indexing
1836 integer,
optional,
intent(in) :: index_offset
1843 local = .true. ;
if (
present(local_indexing)) local = local_indexing
1844 ind_off = 0 ;
if (
present(index_offset)) ind_off = index_offset
1846 call mpp_get_compute_domain(domain%mpp_domain, isc, iec, jsc, jec)
1847 call mpp_get_data_domain(domain%mpp_domain, isd, ied, jsd, jed)
1848 call mpp_get_global_domain(domain%mpp_domain, isg, ieg, jsg, jeg)
1852 idg_offset = isd-1 ; jdg_offset = jsd-1
1853 isc = isc-isd+1 ; iec = iec-isd+1 ; jsc = jsc-jsd+1 ; jec = jec-jsd+1
1854 ied = ied-isd+1 ; jed = jed-jsd+1
1857 idg_offset = 0 ; jdg_offset = 0
1859 if (ind_off /= 0)
then 1860 idg_offset = idg_offset + ind_off ; jdg_offset = jdg_offset + ind_off
1861 isc = isc + ind_off ; iec = iec + ind_off
1862 jsc = jsc + ind_off ; jec = jec + ind_off
1863 isd = isd + ind_off ; ied = ied + ind_off
1864 jsd = jsd + ind_off ; jed = jed + ind_off
1866 symmetric = domain%symmetric
1868 end subroutine get_domain_extent
1870 subroutine get_domain_extent_dsamp2(Domain, isc_d2, iec_d2, jsc_d2, jec_d2,&
1871 isd_d2, ied_d2, jsd_d2, jed_d2,&
1872 isg_d2, ieg_d2, jsg_d2, jeg_d2)
1874 intent(in) :: Domain
1875 integer,
intent(out) :: isc_d2
1876 integer,
intent(out) :: iec_d2
1877 integer,
intent(out) :: jsc_d2
1878 integer,
intent(out) :: jec_d2
1879 integer,
intent(out) :: isd_d2
1880 integer,
intent(out) :: ied_d2
1881 integer,
intent(out) :: jsd_d2
1882 integer,
intent(out) :: jed_d2
1883 integer,
intent(out) :: isg_d2
1884 integer,
intent(out) :: ieg_d2
1885 integer,
intent(out) :: jsg_d2
1886 integer,
intent(out) :: jeg_d2
1888 call mpp_get_compute_domain(domain%mpp_domain_d2, isc_d2, iec_d2, jsc_d2, jec_d2)
1889 call mpp_get_data_domain(domain%mpp_domain_d2, isd_d2, ied_d2, jsd_d2, jed_d2)
1890 call mpp_get_global_domain (domain%mpp_domain_d2, isg_d2, ieg_d2, jsg_d2, jeg_d2)
1892 isc_d2 = isc_d2-isd_d2+1 ; iec_d2 = iec_d2-isd_d2+1
1893 jsc_d2 = jsc_d2-jsd_d2+1 ; jec_d2 = jec_d2-jsd_d2+1
1894 ied_d2 = ied_d2-isd_d2+1 ; jed_d2 = jed_d2-jsd_d2+1
1895 isd_d2 = 1 ; jsd_d2 = 1
1896 end subroutine get_domain_extent_dsamp2
1900 subroutine get_simple_array_i_ind(domain, size, is, ie, symmetric)
1902 integer,
intent(in) :: size
1903 integer,
intent(out) :: is
1904 integer,
intent(out) :: ie
1905 logical,
optional,
intent(in) :: symmetric
1909 character(len=120) :: mesg, mesg2
1910 integer :: isc, iec, jsc, jec, isd, ied, jsd, jed
1912 call mpp_get_compute_domain(domain%mpp_domain, isc, iec, jsc, jec)
1913 call mpp_get_data_domain(domain%mpp_domain, isd, ied, jsd, jed)
1915 isc = isc-isd+1 ; iec = iec-isd+1 ; ied = ied-isd+1 ; isd = 1
1916 sym = domain%symmetric ;
if (
present(symmetric)) sym = symmetric
1918 if (
size == ied)
then ; is = isc ; ie = iec
1919 elseif (
size == 1+iec-isc)
then ; is = 1 ; ie =
size 1920 elseif (sym .and. (
size == 1+ied))
then ; is = isc ; ie = iec+1
1921 elseif (sym .and. (
size == 2+iec-isc))
then ; is = 1 ; ie = size+1
1923 write(mesg,
'("Unrecognized size ", i6, "in call to get_simple_array_i_ind. \")')
size 1925 write(mesg2,
'("Valid sizes are : ", 2i7)') ied, 1+iec-isc
1927 write(mesg2,
'("Valid sizes are : ", 4i7)') ied, 1+iec-isc, 1+ied, 2+iec-isc
1929 call mom_error(fatal, trim(mesg)//trim(mesg2))
1932 end subroutine get_simple_array_i_ind
1937 subroutine get_simple_array_j_ind(domain, size, js, je, symmetric)
1939 integer,
intent(in) :: size
1940 integer,
intent(out) :: js
1941 integer,
intent(out) :: je
1942 logical,
optional,
intent(in) :: symmetric
1946 character(len=120) :: mesg, mesg2
1947 integer :: isc, iec, jsc, jec, isd, ied, jsd, jed
1949 call mpp_get_compute_domain(domain%mpp_domain, isc, iec, jsc, jec)
1950 call mpp_get_data_domain(domain%mpp_domain, isd, ied, jsd, jed)
1952 jsc = jsc-jsd+1 ; jec = jec-jsd+1 ; jed = jed-jsd+1 ; jsd = 1
1953 sym = domain%symmetric ;
if (
present(symmetric)) sym = symmetric
1955 if (
size == jed)
then ; js = jsc ; je = jec
1956 elseif (
size == 1+jec-jsc)
then ; js = 1 ; je =
size 1957 elseif (sym .and. (
size == 1+jed))
then ; js = jsc ; je = jec+1
1958 elseif (sym .and. (
size == 2+jec-jsc))
then ; js = 1 ; je = size+1
1960 write(mesg,
'("Unrecognized size ", i6, "in call to get_simple_array_j_ind. \")')
size 1962 write(mesg2,
'("Valid sizes are : ", 2i7)') jed, 1+jec-jsc
1964 write(mesg2,
'("Valid sizes are : ", 4i7)') jed, 1+jec-jsc, 1+jed, 2+jec-jsc
1966 call mom_error(fatal, trim(mesg)//trim(mesg2))
1969 end subroutine get_simple_array_j_ind
1972 subroutine get_global_shape(domain, niglobal, njglobal)
1974 integer,
intent(out) :: niglobal
1975 integer,
intent(out) :: njglobal
1977 niglobal = domain%niglobal
1978 njglobal = domain%njglobal
1980 end subroutine get_global_shape
Complete a halo update on a pair of arrays representing the two components of a vector.
A structure that can be parsed to read and document run-time parameters.
Complete a non-blocking halo update on an array.
Wraps the MPP cpu clock functions.
The MOM6 facility to parse input files for runtime parameters.
Do a set of halo updates that fill in the values at the duplicated edges of a staggered symmetric mem...
Initiate a non-blocking halo update on an array.
An overloaded interface to log the values of various types of parameters.
Do a halo update on a pair of arrays representing the two components of a vector. ...
Interfaces to non-domain-oriented communication subroutines, including the MOM6 reproducing sums faci...
Copy one MOM_domain_type into another.
Initiate a halo update on a pair of arrays representing the two components of a vector.
Describes the decomposed MOM domain and has routines for communications across PEs.
Routines for error handling and I/O management.
An overloaded interface to log version information about modules.
The MOM_domain_type contains information about the domain decompositoin.
Set up a group of halo updates.
Handy functions for manipulating strings.
Do a halo update on an array.
An overloaded interface to read and log the values of various types of parameters.