1260 type(mom_domain_type),
pointer :: mom_dom
1262 type(param_file_type),
intent(in) :: param_file
1264 logical,
optional,
intent(in) :: symmetric
1267 logical,
optional,
intent(in) :: static_memory
1270 integer,
optional,
intent(in) :: nihalo
1272 integer,
optional,
intent(in) :: njhalo
1274 integer,
optional,
intent(in) :: niglobal
1276 integer,
optional,
intent(in) :: njglobal
1278 integer,
optional,
intent(in) :: niproc
1280 integer,
optional,
intent(in) :: njproc
1282 integer,
dimension(2),
optional,
intent(inout) :: min_halo
1285 character(len=*),
optional,
intent(in) :: domain_name
1287 character(len=*),
optional,
intent(in) :: include_name
1289 character(len=*),
optional,
intent(in) :: param_suffix
1312 integer,
dimension(2) :: layout = (/ 1, 1 /)
1313 integer,
dimension(2) :: io_layout = (/ 0, 0 /)
1314 integer,
dimension(4) :: global_indices
1319 integer :: nihalo_dflt, njhalo_dflt
1320 integer :: pe, proc_used
1321 integer :: x_flags, y_flags
1322 logical :: reentrant_x, reentrant_y, tripolar_n, is_static
1323 logical :: mask_table_exists
1324 character(len=128) :: mask_table, inputdir
1325 character(len=64) :: dom_name, inc_nm
1326 character(len=200) :: mesg
1328 integer :: xsiz, ysiz, nip_parsed, njp_parsed
1329 integer :: isc,iec,jsc,jec
1330 character(len=8) :: char_xsiz, char_ysiz, char_niglobal, char_njglobal
1331 character(len=40) :: nihalo_nm, njhalo_nm, layout_nm, io_layout_nm, masktable_nm
1332 character(len=40) :: niproc_nm, njproc_nm
1335 #include "version_variable.h" 1336 character(len=40) :: mdl
1338 if (.not.
associated(mom_dom))
then 1340 allocate(mom_dom%mpp_domain)
1344 proc_used = num_pes()
1348 mom_dom%symmetric = .true.
1349 if (
present(symmetric))
then ; mom_dom%symmetric = symmetric ;
endif 1350 if (
present(min_halo)) mdl = trim(mdl)//
" min_halo" 1352 dom_name =
"MOM" ; inc_nm =
"MOM_memory.h" 1353 if (
present(domain_name)) dom_name = trim(domain_name)
1354 if (
present(include_name)) inc_nm = trim(include_name)
1356 nihalo_nm =
"NIHALO" ; njhalo_nm =
"NJHALO" 1357 layout_nm =
"LAYOUT" ; io_layout_nm =
"IO_LAYOUT" ; masktable_nm =
"MASKTABLE" 1358 niproc_nm =
"NIPROC" ; njproc_nm =
"NJPROC" 1359 if (
present(param_suffix))
then ;
if (len(trim(adjustl(param_suffix))) > 0)
then 1360 nihalo_nm =
"NIHALO"//(trim(adjustl(param_suffix)))
1361 njhalo_nm =
"NJHALO"//(trim(adjustl(param_suffix)))
1362 layout_nm =
"LAYOUT"//(trim(adjustl(param_suffix)))
1363 io_layout_nm =
"IO_LAYOUT"//(trim(adjustl(param_suffix)))
1364 masktable_nm =
"MASKTABLE"//(trim(adjustl(param_suffix)))
1365 niproc_nm =
"NIPROC"//(trim(adjustl(param_suffix)))
1366 njproc_nm =
"NJPROC"//(trim(adjustl(param_suffix)))
1369 is_static = .false. ;
if (
present(static_memory)) is_static = static_memory
1371 if (.not.
present(nihalo))
call mom_error(fatal,
"NIHALO must be "// &
1372 "present in the call to MOM_domains_init with static memory.")
1373 if (.not.
present(njhalo))
call mom_error(fatal,
"NJHALO must be "// &
1374 "present in the call to MOM_domains_init with static memory.")
1375 if (.not.
present(niglobal))
call mom_error(fatal,
"NIGLOBAL must be "// &
1376 "present in the call to MOM_domains_init with static memory.")
1377 if (.not.
present(njglobal))
call mom_error(fatal,
"NJGLOBAL must be "// &
1378 "present in the call to MOM_domains_init with static memory.")
1379 if (.not.
present(niproc))
call mom_error(fatal,
"NIPROC must be "// &
1380 "present in the call to MOM_domains_init with static memory.")
1381 if (.not.
present(njproc))
call mom_error(fatal,
"NJPROC must be "// &
1382 "present in the call to MOM_domains_init with static memory.")
1386 call log_version(param_file, mdl, version,
"")
1387 call get_param(param_file, mdl,
"REENTRANT_X", reentrant_x, &
1388 "If true, the domain is zonally reentrant.", default=.true.)
1389 call get_param(param_file, mdl,
"REENTRANT_Y", reentrant_y, &
1390 "If true, the domain is meridionally reentrant.", &
1392 call get_param(param_file, mdl,
"TRIPOLAR_N", tripolar_n, &
1393 "Use tripolar connectivity at the northern edge of the \n"//&
1394 "domain. With TRIPOLAR_N, NIGLOBAL must be even.", &
1397 #ifndef NOT_SET_AFFINITY 1426 call log_param(param_file, mdl,
"!SYMMETRIC_MEMORY_", mom_dom%symmetric, &
1427 "If defined, the velocity point data domain includes \n"//&
1428 "every face of the thickness points. In other words, \n"//&
1429 "some arrays are larger than others, depending on where \n"//&
1430 "they are on the staggered grid. Also, the starting \n"//&
1431 "index of the velocity-point arrays is usually 0, not 1. \n"//&
1432 "This can only be set at compile time.",&
1434 call get_param(param_file, mdl,
"NONBLOCKING_UPDATES", mom_dom%nonblocking_updates, &
1435 "If true, non-blocking halo updates may be used.", &
1436 default=.false., layoutparam=.true.)
1437 call get_param(param_file, mdl,
"THIN_HALO_UPDATES", mom_dom%thin_halo_updates, &
1438 "If true, optional arguments may be used to specify the \n"//&
1439 "The width of the halos that are updated with each call.", &
1440 default=.true., layoutparam=.true.)
1442 nihalo_dflt = 4 ; njhalo_dflt = 4
1443 if (
present(nihalo)) nihalo_dflt = nihalo
1444 if (
present(njhalo)) njhalo_dflt = njhalo
1446 call log_param(param_file, mdl,
"!STATIC_MEMORY_", is_static, &
1447 "If STATIC_MEMORY_ is defined, the principle variables \n"//&
1448 "will have sizes that are statically determined at \n"//&
1449 "compile time. Otherwise the sizes are not determined \n"//&
1450 "until run time. The STATIC option is substantially \n"//&
1451 "faster, but does not allow the PE count to be changed \n"//&
1452 "at run time. This can only be set at compile time.",&
1455 call get_param(param_file, mdl, trim(nihalo_nm), mom_dom%nihalo, &
1456 "The number of halo points on each side in the \n"//&
1457 "x-direction. With STATIC_MEMORY_ this is set as NIHALO_ \n"//&
1458 "in "//trim(inc_nm)//
" at compile time; without STATIC_MEMORY_ \n"//&
1459 "the default is NIHALO_ in "//trim(inc_nm)//
" (if defined) or 2.", &
1460 default=4, static_value=nihalo_dflt, layoutparam=.true.)
1461 call get_param(param_file, mdl, trim(njhalo_nm), mom_dom%njhalo, &
1462 "The number of halo points on each side in the \n"//&
1463 "y-direction. With STATIC_MEMORY_ this is set as NJHALO_ \n"//&
1464 "in "//trim(inc_nm)//
" at compile time; without STATIC_MEMORY_ \n"//&
1465 "the default is NJHALO_ in "//trim(inc_nm)//
" (if defined) or 2.", &
1466 default=4, static_value=njhalo_dflt, layoutparam=.true.)
1467 if (
present(min_halo))
then 1468 mom_dom%nihalo = max(mom_dom%nihalo, min_halo(1))
1469 min_halo(1) = mom_dom%nihalo
1470 mom_dom%njhalo = max(mom_dom%njhalo, min_halo(2))
1471 min_halo(2) = mom_dom%njhalo
1472 call log_param(param_file, mdl,
"!NIHALO min_halo", mom_dom%nihalo, layoutparam=.true.)
1473 call log_param(param_file, mdl,
"!NJHALO min_halo", mom_dom%nihalo, layoutparam=.true.)
1476 call get_param(param_file, mdl,
"NIGLOBAL", mom_dom%niglobal, &
1477 "The total number of thickness grid points in the \n"//&
1478 "x-direction in the physical domain. With STATIC_MEMORY_ \n"//&
1479 "this is set in "//trim(inc_nm)//
" at compile time.", &
1480 static_value=niglobal)
1481 call get_param(param_file, mdl,
"NJGLOBAL", mom_dom%njglobal, &
1482 "The total number of thickness grid points in the \n"//&
1483 "y-direction in the physical domain. With STATIC_MEMORY_ \n"//&
1484 "this is set in "//trim(inc_nm)//
" at compile time.", &
1485 static_value=njglobal)
1486 if (mom_dom%niglobal /= niglobal)
call mom_error(fatal,
"MOM_domains_init: " // &
1487 "static mismatch for NIGLOBAL_ domain size. Header file does not match input namelist")
1488 if (mom_dom%njglobal /= njglobal)
call mom_error(fatal,
"MOM_domains_init: " // &
1489 "static mismatch for NJGLOBAL_ domain size. Header file does not match input namelist")
1491 if (.not.
present(min_halo))
then 1492 if (mom_dom%nihalo /= nihalo)
call mom_error(fatal,
"MOM_domains_init: " // &
1493 "static mismatch for "//trim(nihalo_nm)//
" domain size")
1494 if (mom_dom%njhalo /= njhalo)
call mom_error(fatal,
"MOM_domains_init: " // &
1495 "static mismatch for "//trim(njhalo_nm)//
" domain size")
1498 call get_param(param_file, mdl,
"NIGLOBAL", mom_dom%niglobal, &
1499 "The total number of thickness grid points in the \n"//&
1500 "x-direction in the physical domain. With STATIC_MEMORY_ \n"//&
1501 "this is set in "//trim(inc_nm)//
" at compile time.", &
1502 fail_if_missing=.true.)
1503 call get_param(param_file, mdl,
"NJGLOBAL", mom_dom%njglobal, &
1504 "The total number of thickness grid points in the \n"//&
1505 "y-direction in the physical domain. With STATIC_MEMORY_ \n"//&
1506 "this is set in "//trim(inc_nm)//
" at compile time.", &
1507 fail_if_missing=.true.)
1510 global_indices(1) = 1 ; global_indices(2) = mom_dom%niglobal
1511 global_indices(3) = 1 ; global_indices(4) = mom_dom%njglobal
1513 call get_param(param_file, mdl,
"INPUTDIR", inputdir, do_not_log=.true., default=
".")
1514 inputdir = slasher(inputdir)
1516 call get_param(param_file, mdl, trim(masktable_nm), mask_table, &
1517 "A text file to specify n_mask, layout and mask_list. \n"//&
1518 "This feature masks out processors that contain only land points. \n"//&
1519 "The first line of mask_table is the number of regions to be masked out.\n"//&
1520 "The second line is the layout of the model and must be \n"//&
1521 "consistent with the actual model layout.\n"//&
1522 "The following (n_mask) lines give the logical positions \n"//&
1523 "of the processors that are masked out. The mask_table \n"//&
1524 "can be created by tools like check_mask. The \n"//&
1525 "following example of mask_table masks out 2 processors, \n"//&
1526 "(1,2) and (3,6), out of the 24 in a 4x6 layout: \n"//&
1527 " 2\n 4,6\n 1,2\n 3,6\n", default=
"MOM_mask_table", &
1529 mask_table = trim(inputdir)//trim(mask_table)
1530 mask_table_exists = file_exist(mask_table)
1533 layout(1) = niproc ; layout(2) = njproc
1535 call get_param(param_file, mdl, trim(layout_nm), layout, &
1536 "The processor layout to be used, or 0, 0 to automatically \n"//&
1537 "set the layout based on the number of processors.", default=0, &
1539 call get_param(param_file, mdl, trim(niproc_nm), nip_parsed, &
1540 "The number of processors in the x-direction.", default=-1, &
1542 call get_param(param_file, mdl, trim(njproc_nm), njp_parsed, &
1543 "The number of processors in the y-direction.", default=-1, &
1545 if (nip_parsed > -1)
then 1546 if ((layout(1) > 0) .and. (layout(1) /= nip_parsed)) &
1547 call mom_error(fatal, trim(layout_nm)//
" and "//trim(niproc_nm)//
" set inconsistently. "//&
1548 "Only LAYOUT should be used.")
1549 layout(1) = nip_parsed
1550 call mom_mesg(trim(niproc_nm)//
" used to set "//trim(layout_nm)//
" in dynamic mode. "//&
1551 "Shift to using "//trim(layout_nm)//
" instead.")
1553 if (njp_parsed > -1)
then 1554 if ((layout(2) > 0) .and. (layout(2) /= njp_parsed)) &
1555 call mom_error(fatal, trim(layout_nm)//
" and "//trim(njproc_nm)//
" set inconsistently. "//&
1556 "Only "//trim(layout_nm)//
" should be used.")
1557 layout(2) = njp_parsed
1558 call mom_mesg(trim(njproc_nm)//
" used to set "//trim(layout_nm)//
" in dynamic mode. "//&
1559 "Shift to using "//trim(layout_nm)//
" instead.")
1562 if ( layout(1)==0 .and. layout(2)==0 ) &
1563 call mpp_define_layout(global_indices, proc_used, layout)
1564 if ( layout(1)/=0 .and. layout(2)==0 ) layout(2) = proc_used/layout(1)
1565 if ( layout(1)==0 .and. layout(2)/=0 ) layout(1) = proc_used/layout(2)
1567 if (layout(1)*layout(2) /= proc_used .and. (.not. mask_table_exists) )
then 1568 write(mesg,
'("MOM_domains_init: The product of the two components of layout, ", & 1569 & 2i4,", is not the number of PEs used, ",i5,".")') &
1570 layout(1),layout(2),proc_used
1571 call mom_error(fatal, mesg)
1574 call log_param(param_file, mdl, trim(niproc_nm), layout(1), &
1575 "The number of processors in the x-direction. With \n"//&
1576 "STATIC_MEMORY_ this is set in "//trim(inc_nm)//
" at compile time.",&
1578 call log_param(param_file, mdl, trim(njproc_nm), layout(2), &
1579 "The number of processors in the x-direction. With \n"//&
1580 "STATIC_MEMORY_ this is set in "//trim(inc_nm)//
" at compile time.",&
1582 call log_param(param_file, mdl, trim(layout_nm), layout, &
1583 "The processor layout that was acutally used.",&
1587 if (layout(1)*layout(2)>mom_dom%niglobal*mom_dom%njglobal)
then 1588 write(mesg,
'(a,2(i5,x,a))')
'You requested to use',layout(1)*layout(2), &
1589 'PEs but there are only',mom_dom%niglobal*mom_dom%njglobal,
'columns in the model' 1590 call mom_error(fatal, mesg)
1593 if (mask_table_exists)
then 1594 call mom_error(note,
'MOM_domains_init: reading maskmap information from '//&
1596 allocate(mom_dom%maskmap(layout(1), layout(2)))
1597 call parse_mask_table(mask_table, mom_dom%maskmap, dom_name)
1602 io_layout(:) = (/ 1, 1 /)
1603 call get_param(param_file, mdl, trim(io_layout_nm), io_layout, &
1604 "The processor layout to be used, or 0,0 to automatically \n"//&
1605 "set the io_layout to be the same as the layout.", default=1, &
1608 if (io_layout(1) < 0)
then 1609 write(mesg,
'("MOM_domains_init: IO_LAYOUT(1) = ",i4,". Negative values "//& 1610 &"are not allowed in ")') io_layout(1)
1611 call mom_error(fatal, mesg//trim(io_layout_nm))
1612 elseif (io_layout(1) > 0)
then ;
if (modulo(layout(1), io_layout(1)) /= 0)
then 1613 write(mesg,
'("MOM_domains_init: The x-direction I/O-layout, IO_LAYOUT(1)=",i4, & 1614 &", does not evenly divide the x-direction layout, NIPROC=,",i4,".")') &
1615 io_layout(1),layout(1)
1616 call mom_error(fatal, mesg)
1619 if (io_layout(2) < 0)
then 1620 write(mesg,
'("MOM_domains_init: IO_LAYOUT(2) = ",i4,". Negative values "//& 1621 &"are not allowed in ")') io_layout(2)
1622 call mom_error(fatal, mesg//trim(io_layout_nm))
1623 elseif (io_layout(2) /= 0)
then ;
if (modulo(layout(2), io_layout(2)) /= 0)
then 1624 write(mesg,
'("MOM_domains_init: The y-direction I/O-layout, IO_LAYOUT(2)=",i4, & 1625 &", does not evenly divide the y-direction layout, NJPROC=,",i4,".")') &
1626 io_layout(2),layout(2)
1627 call mom_error(fatal, mesg)
1630 if (io_layout(2) == 0) io_layout(2) = layout(2)
1631 if (io_layout(1) == 0) io_layout(1) = layout(1)
1633 x_flags = 0 ; y_flags = 0
1634 if (reentrant_x) x_flags = cyclic_global_domain
1635 if (reentrant_y) y_flags = cyclic_global_domain
1636 if (tripolar_n)
then 1637 y_flags = fold_north_edge
1638 if (reentrant_y)
call mom_error(fatal,
"MOM_domains: "// &
1639 "TRIPOLAR_N and REENTRANT_Y may not be defined together.")
1642 global_indices(1) = 1 ; global_indices(2) = mom_dom%niglobal
1643 global_indices(3) = 1 ; global_indices(4) = mom_dom%njglobal
1645 if (mask_table_exists)
then 1646 call mom_define_domain( global_indices, layout, mom_dom%mpp_domain, &
1647 xflags=x_flags, yflags=y_flags, &
1648 xhalo=mom_dom%nihalo, yhalo=mom_dom%njhalo, &
1649 symmetry = mom_dom%symmetric, name=dom_name, &
1650 maskmap=mom_dom%maskmap )
1652 call mom_define_domain( global_indices, layout, mom_dom%mpp_domain, &
1653 xflags=x_flags, yflags=y_flags, &
1654 xhalo=mom_dom%nihalo, yhalo=mom_dom%njhalo, &
1655 symmetry = mom_dom%symmetric, name=dom_name)
1658 if ((io_layout(1) > 0) .and. (io_layout(2) > 0) .and. &
1659 (layout(1)*layout(2) > 1))
then 1660 call mom_define_io_domain(mom_dom%mpp_domain, io_layout)
1664 mom_dom%X_FLAGS = x_flags
1665 mom_dom%Y_FLAGS = y_flags
1666 mom_dom%layout = layout
1667 mom_dom%io_layout = io_layout
1668 mom_dom%use_io_layout = (io_layout(1) + io_layout(2) > 0)
1673 call mpp_get_compute_domain(mom_dom%mpp_domain,isc,iec,jsc,jec)
1674 xsiz = iec - isc + 1
1675 ysiz = jec - jsc + 1
1676 if (xsiz*niproc /= mom_dom%niglobal .OR. ysiz*njproc /= mom_dom%njglobal)
then 1677 write( char_xsiz,
'(i4)' ) niproc
1678 write( char_ysiz,
'(i4)' ) njproc
1679 write( char_niglobal,
'(i4)' ) mom_dom%niglobal
1680 write( char_njglobal,
'(i4)' ) mom_dom%njglobal
1681 call mom_error(warning,
'MOM_domains: Processor decomposition (NIPROC_,NJPROC_) = (' &
1682 //trim(char_xsiz)//
','//trim(char_ysiz)// &
1683 ') does not evenly divide size set by preprocessor macro ('&
1684 //trim(char_niglobal)//
','//trim(char_njglobal)//
'). ')
1685 call mom_error(fatal,
'MOM_domains: #undef STATIC_MEMORY_ in "//trim(inc_nm)//" to use & 1686 &dynamic allocation, or change processor decomposition to evenly divide the domain.')