@@ -17,10 +17,12 @@ module m_mpi_common
1717 use m_helper
1818 use ieee_arithmetic
1919 use m_nvtx
20- use m_constants, only: recon_type_weno, format_silo
20+ use m_constants, only: recon_type_weno
2121
2222 implicit none
2323
24+ private :: s_apply_decomposition_policies
25+
2426 integer , private :: v_size
2527 $:GPU_DECLARE(create= ' [v_size]' )
2628
@@ -1314,21 +1316,29 @@ contains
13141316 !> The purpose of this procedure is to optimally decompose the computational domain among the available processors. This is
13151317 !! performed by attempting to award each processor, in each of the coordinate directions, approximately the same number of
13161318 !! cells, and then recomputing the affected global parameters.
1317- subroutine s_mpi_decompose_computational_domain
1319+ subroutine s_mpi_decompose_computational_domain (write_silo_ghost_offsets , adjust_local_domains , output_offsets , local_domains )
1320+
1321+ logical , intent (in ) :: write_silo_ghost_offsets
1322+ logical , intent (in ) :: adjust_local_domains
1323+ type(int_bounds_info), dimension (3 ), intent (inout ), optional :: output_offsets
1324+ type(bounds_info), dimension (3 ), intent (inout ), optional :: local_domains
13181325
13191326#ifdef MFC_MPI
13201327 !> Non- optimal number of processors in the x- , y- and z- directions
13211328 real (wp) :: tmp_num_procs_x, tmp_num_procs_y, tmp_num_procs_z
13221329 real (wp) :: fct_min !< Processor factorization (fct) minimization parameter
13231330 integer :: MPI_COMM_CART !< Cartesian processor topology communicator
13241331 integer :: rem_cells !< Remaining cells after distribution among processors
1332+ integer :: rem_cells_by_dim(3 )
13251333 integer :: recon_order !< WENO or MUSCL reconstruction order
13261334 integer :: i, j, k !< Generic loop iterators
13271335 integer :: ierr !< Generic flag used to identify and report MPI errors
13281336
13291337 ! temp array to store neighbor rank coordinates
13301338 integer , dimension (1 :num_dims) :: neighbor_coords
13311339
1340+ rem_cells_by_dim = 0
1341+
13321342 ! Zeroing out communication needs for moving EL bubbles/ particles
13331343 nidx(1 )%beg = 0 ; nidx(1 )%end = 0
13341344 nidx(2 )%beg = 0 ; nidx(2 )%end = 0
@@ -1470,6 +1480,7 @@ contains
14701480
14711481 ! Number of remaining cells
14721482 rem_cells = mod (p + 1 , num_procs_z)
1483+ rem_cells_by_dim(3 ) = rem_cells
14731484
14741485 ! Optimal number of cells per processor
14751486 p = (p + 1 )/ num_procs_z - 1
@@ -1497,44 +1508,13 @@ contains
14971508 nidx(3 )%end = 1
14981509 end if
14991510
1500- #ifdef MFC_POST_PROCESS
1501- ! Ghost zone at the beginning
1502- if (proc_coords(3 ) > 0 .and. format == format_silo) then
1503- offset_z%beg = 2
1504- else
1505- offset_z%beg = 0
1506- end if
1507-
1508- ! Ghost zone at the end
1509- if (proc_coords(3 ) < num_procs_z - 1 .and. format == format_silo) then
1510- offset_z%end = 2
1511- else
1512- offset_z%end = 0
1513- end if
1514- #endif
1515-
15161511 ! Beginning and end sub- domain boundary locations
15171512 if (parallel_io) then
15181513 if (proc_coords(3 ) < rem_cells) then
15191514 start_idx(3 ) = (p + 1 )* proc_coords(3 )
15201515 else
15211516 start_idx(3 ) = (p + 1 )* proc_coords(3 ) + rem_cells
15221517 end if
1523- else
1524- #ifdef MFC_PRE_PROCESS
1525- if (old_grid .neqv. .true. ) then
1526- dz_min = (z_domain%end - z_domain%beg)/ real (p_glb + 1 , wp)
1527-
1528- if (proc_coords(3 ) < rem_cells) then
1529- z_domain%beg = z_domain%beg + dz_min* real ((p + 1 )* proc_coords(3 ))
1530- z_domain%end = z_domain%end - dz_min* real ((p + 1 )* (num_procs_z - proc_coords(3 ) - 1 ) - (num_procs_z &
1531- & - rem_cells))
1532- else
1533- z_domain%beg = z_domain%beg + dz_min* real ((p + 1 )* proc_coords(3 ) + rem_cells)
1534- z_domain%end = z_domain%end - dz_min* real ((p + 1 )* (num_procs_z - proc_coords(3 ) - 1 ))
1535- end if
1536- end if
1537- #endif
15381518 end if
15391519
15401520 ! 2D Cartesian Processor Topology
@@ -1584,6 +1564,7 @@ contains
15841564
15851565 ! Number of remaining cells
15861566 rem_cells = mod (n + 1 , num_procs_y)
1567+ rem_cells_by_dim(2 ) = rem_cells
15871568
15881569 ! Optimal number of cells per processor
15891570 n = (n + 1 )/ num_procs_y - 1
@@ -1611,44 +1592,13 @@ contains
16111592 nidx(2 )%end = 1
16121593 end if
16131594
1614- #ifdef MFC_POST_PROCESS
1615- ! Ghost zone at the beginning
1616- if (proc_coords(2 ) > 0 .and. format == format_silo) then
1617- offset_y%beg = 2
1618- else
1619- offset_y%beg = 0
1620- end if
1621-
1622- ! Ghost zone at the end
1623- if (proc_coords(2 ) < num_procs_y - 1 .and. format == format_silo) then
1624- offset_y%end = 2
1625- else
1626- offset_y%end = 0
1627- end if
1628- #endif
1629-
16301595 ! Beginning and end sub- domain boundary locations
16311596 if (parallel_io) then
16321597 if (proc_coords(2 ) < rem_cells) then
16331598 start_idx(2 ) = (n + 1 )* proc_coords(2 )
16341599 else
16351600 start_idx(2 ) = (n + 1 )* proc_coords(2 ) + rem_cells
16361601 end if
1637- else
1638- #ifdef MFC_PRE_PROCESS
1639- if (old_grid .neqv. .true. ) then
1640- dy_min = (y_domain%end - y_domain%beg)/ real (n_glb + 1 , wp)
1641-
1642- if (proc_coords(2 ) < rem_cells) then
1643- y_domain%beg = y_domain%beg + dy_min* real ((n + 1 )* proc_coords(2 ))
1644- y_domain%end = y_domain%end - dy_min* real ((n + 1 )* (num_procs_y - proc_coords(2 ) - 1 ) - (num_procs_y &
1645- & - rem_cells))
1646- else
1647- y_domain%beg = y_domain%beg + dy_min* real ((n + 1 )* proc_coords(2 ) + rem_cells)
1648- y_domain%end = y_domain%end - dy_min* real ((n + 1 )* (num_procs_y - proc_coords(2 ) - 1 ))
1649- end if
1650- end if
1651- #endif
16521602 end if
16531603
16541604 ! 1D Cartesian Processor Topology
@@ -1667,6 +1617,7 @@ contains
16671617
16681618 ! Number of remaining cells
16691619 rem_cells = mod (m + 1 , num_procs_x)
1620+ rem_cells_by_dim(1 ) = rem_cells
16701621
16711622 ! Optimal number of cells per processor
16721623 m = (m + 1 )/ num_procs_x - 1
@@ -1696,46 +1647,19 @@ contains
16961647 nidx(1 )%end = 1
16971648 end if
16981649
1699- #ifdef MFC_POST_PROCESS
1700- ! Ghost zone at the beginning
1701- if (proc_coords(1 ) > 0 .and. format == format_silo) then
1702- offset_x%beg = 2
1703- else
1704- offset_x%beg = 0
1705- end if
1706-
1707- ! Ghost zone at the end
1708- if (proc_coords(1 ) < num_procs_x - 1 .and. format == format_silo) then
1709- offset_x%end = 2
1710- else
1711- offset_x%end = 0
1712- end if
1713- #endif
1714-
17151650 ! Beginning and end sub- domain boundary locations
17161651 if (parallel_io) then
17171652 if (proc_coords(1 ) < rem_cells) then
17181653 start_idx(1 ) = (m + 1 )* proc_coords(1 )
17191654 else
17201655 start_idx(1 ) = (m + 1 )* proc_coords(1 ) + rem_cells
17211656 end if
1722- else
1723- #ifdef MFC_PRE_PROCESS
1724- if (old_grid .neqv. .true. ) then
1725- dx_min = (x_domain%end - x_domain%beg)/ real (m_glb + 1 , wp)
1726-
1727- if (proc_coords(1 ) < rem_cells) then
1728- x_domain%beg = x_domain%beg + dx_min* real ((m + 1 )* proc_coords(1 ))
1729- x_domain%end = x_domain%end - dx_min* real ((m + 1 )* (num_procs_x - proc_coords(1 ) - 1 ) - (num_procs_x &
1730- & - rem_cells))
1731- else
1732- x_domain%beg = x_domain%beg + dx_min* real ((m + 1 )* proc_coords(1 ) + rem_cells)
1733- x_domain%end = x_domain%end - dx_min* real ((m + 1 )* (num_procs_x - proc_coords(1 ) - 1 ))
1734- end if
1735- end if
1736- #endif
17371657 end if
17381658
1659+ call s_apply_decomposition_policies((/ num_procs_x, num_procs_y, num_procs_z/ ), rem_cells_by_dim, (/ m, n, p/ ), (/ m_glb, &
1660+ & n_glb, p_glb/ ), write_silo_ghost_offsets, &
1661+ & adjust_local_domains .and. (.not. parallel_io), output_offsets, local_domains)
1662+
17391663 @:ALLOCATE(neighbor_ranks(nidx(1 )%beg:nidx(1 )%end, nidx(2 )%beg:nidx(2 )%end, nidx(3 )%beg:nidx(3 )%end))
17401664 do k = nidx(3 )%beg, nidx(3 )%end
17411665 do j = nidx(2 )%beg, nidx(2 )%end
@@ -1753,6 +1677,68 @@ contains
17531677
17541678 end subroutine s_mpi_decompose_computational_domain
17551679
1680+ !> Apply executable- configured output and local- domain policies after the shared Cartesian decomposition.
1681+ subroutine s_apply_decomposition_policies (proc_counts , remainders , local_cells , global_cells , write_silo_ghost_offsets , &
1682+ & adjust_local_domains , output_offsets , local_domains )
1683+
1684+ integer , dimension (3 ), intent (in ) :: proc_counts, remainders, local_cells, global_cells
1685+ logical , intent (in ) :: write_silo_ghost_offsets, adjust_local_domains
1686+ type(int_bounds_info), dimension (3 ), intent (inout ), optional :: output_offsets
1687+ type(bounds_info), dimension (3 ), intent (inout ), optional :: local_domains
1688+ integer :: dim
1689+ real (wp) :: domain_beg, domain_end, spacing
1690+
1691+ if (write_silo_ghost_offsets .and. .not. present (output_offsets)) then
1692+ call s_mpi_abort(' Silo ghost-offset policy requires output offset storage.' )
1693+ end if
1694+ if (adjust_local_domains .and. .not. present (local_domains)) then
1695+ call s_mpi_abort(' Local-domain adjustment policy requires domain storage.' )
1696+ end if
1697+
1698+ if (present (output_offsets)) then
1699+ do dim = 1 , 3
1700+ output_offsets(dim)%beg = 0
1701+ output_offsets(dim)%end = 0
1702+ end do
1703+
1704+ if (write_silo_ghost_offsets) then
1705+ do dim = 1 , num_dims
1706+ if (proc_coords(dim) > 0 ) output_offsets(dim)%beg = 2
1707+ if (proc_coords(dim) < proc_counts(dim) - 1 ) output_offsets(dim)%end = 2
1708+ end do
1709+ end if
1710+ end if
1711+
1712+ if (adjust_local_domains) then
1713+ do dim = 1 , num_dims
1714+ domain_beg = local_domains(dim)%beg
1715+ domain_end = local_domains(dim)%end
1716+ spacing = (domain_end - domain_beg)/ real (global_cells(dim) + 1 , wp)
1717+
1718+ select case (dim)
1719+ case (1 )
1720+ dx_min = spacing
1721+ case (2 )
1722+ dy_min = spacing
1723+ case (3 )
1724+ dz_min = spacing
1725+ end select
1726+
1727+ if (proc_coords(dim) < remainders(dim)) then
1728+ local_domains(dim)%beg = domain_beg + spacing* real ((local_cells(dim) + 1 )* proc_coords(dim), wp)
1729+ local_domains(dim)%end = domain_end - spacing* real ((local_cells(dim) + 1 )* (proc_counts(dim) - proc_coords(dim) &
1730+ & - 1 ) - (proc_counts(dim) - remainders(dim)), wp)
1731+ else
1732+ local_domains(dim)%beg = domain_beg + spacing* real ((local_cells(dim) + 1 )* proc_coords(dim) + remainders(dim), &
1733+ & wp)
1734+ local_domains(dim)%end = domain_end - spacing* real ((local_cells(dim) + 1 )* (proc_counts(dim) - proc_coords(dim) &
1735+ & - 1 ), wp)
1736+ end if
1737+ end do
1738+ end if
1739+
1740+ end subroutine s_apply_decomposition_policies
1741+
17561742 !> The goal of this procedure is to populate the buffers of the grid variables by communicating with the neighboring processors.
17571743 !! Note that only the buffers of the cell- width distributions are handled in such a way. This is because the buffers of
17581744 !! cell- boundary locations may be calculated directly from those of the cell- width distributions.
0 commit comments