Sacado Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BoxElemPart.cpp
Go to the documentation of this file.
1 //@HEADER
2 // ************************************************************************
3 //
4 // Kokkos v. 4.0
5 // Copyright (2022) National Technology & Engineering
6 // Solutions of Sandia, LLC (NTESS).
7 //
8 // Under the terms of Contract DE-NA0003525 with NTESS,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
12 // See https://kokkos.org/LICENSE for license information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //@HEADER
16 
17 #include <utility>
18 #include <iostream>
19 #include <sstream>
20 #include <stdexcept>
21 #include <limits>
22 #include <BoxElemPart.hpp>
23 
24 //----------------------------------------------------------------------------
25 
26 namespace Kokkos {
27 namespace Example {
28 
29 void box_partition( const unsigned global_size ,
30  const unsigned global_rank ,
31  const unsigned global_box[][2] ,
32  unsigned box[][2] )
33 {
34  box[0][0] = global_box[0][0] ; box[0][1] = global_box[0][1] ;
35  box[1][0] = global_box[1][0] ; box[1][1] = global_box[1][1] ;
36  box[2][0] = global_box[2][0] ; box[2][1] = global_box[2][1] ;
37 
38  unsigned ip = 0 ;
39  unsigned np = global_size ;
40 
41  while ( 1 < np ) {
42 
43  // P = [ ip + j * portion , ip + ( j + 1 ) * portion )
44 
45  unsigned jip , jup ;
46 
47  {
48  const unsigned part = ( 0 == ( np % 5 ) ) ? 5 : (
49  ( 0 == ( np % 3 ) ) ? 3 : 2 );
50 
51  const unsigned portion = np / part ;
52 
53  if ( 2 < part || global_rank < ip + portion ) {
54  jip = portion * size_t( double( global_rank - ip ) / double(portion) );
55  jup = jip + portion ;
56  }
57  else {
58  jip = portion ;
59  jup = np ;
60  }
61  }
62 
63  // Choose axis with largest count:
64 
65  const unsigned nb[3] = {
66  box[0][1] - box[0][0] ,
67  box[1][1] - box[1][0] ,
68  box[2][1] - box[2][0] };
69 
70  const unsigned axis = nb[2] > nb[1] ? ( nb[2] > nb[0] ? 2 : 0 )
71  : ( nb[1] > nb[0] ? 1 : 0 );
72 
73  box[ axis ][1] = box[ axis ][0] + unsigned( double(nb[axis]) * ( double(jup) / double(np) ));
74  box[ axis ][0] = box[ axis ][0] + unsigned( double(nb[axis]) * ( double(jip) / double(np) ));
75 
76  np = jup - jip ;
77  ip = ip + jip ;
78  }
79 }
80 
81 } /* namespace Example */
82 } /* namespace Kokkos */
83 
84 //----------------------------------------------------------------------------
85 
86 namespace Kokkos {
87 namespace Example {
88 
89 void BoxElemPart::local( const unsigned rank ,
90  unsigned uses_elem[][2] ,
91  unsigned owns_node[][2] ,
92  unsigned uses_node[][2] ) const
93 {
95 
97 
98  for ( unsigned i = 0 ; i < 3 ; ++i ) {
99  owns_node[i][0] = uses_elem[i][0] ;
100  owns_node[i][1] = uses_elem[i][1] + ( m_global_elem_box[i][1] == uses_elem[i][1] ? 1 : 0 );
101  }
102  }
103  else {
104 
105  const unsigned global_vert[3][2] =
106  { { 0 , m_global_elem_box[0][1] + 1 },
107  { 0 , m_global_elem_box[1][1] + 1 },
108  { 0 , m_global_elem_box[2][1] + 1 } };
109 
110  Kokkos::Example::box_partition( m_global_size , rank , global_vert , owns_node );
111 
112  for ( unsigned i = 0 ; i < 3 ; ++i ) {
113  uses_elem[i][0] = global_vert[i][0] == owns_node[i][0] ? owns_node[i][0] : owns_node[i][0] - 1 ;
114  uses_elem[i][1] = global_vert[i][1] == owns_node[i][1] ? owns_node[i][1] - 1 : owns_node[i][1] ;
115  }
116  }
117 
118  for ( unsigned i = 0 ; i < 3 ; ++i ) {
119  uses_node[i][0] = uses_elem[i][0] ;
120  uses_node[i][1] = uses_elem[i][1] + 1 ;
121  }
122 
124  for ( unsigned i = 0 ; i < 3 ; ++i ) {
125  owns_node[i][0] = 2 * owns_node[i][0] ;
126  uses_node[i][0] = 2 * uses_node[i][0] ;
127  owns_node[i][1] = 2 * owns_node[i][1] - 1 ;
128  uses_node[i][1] = 2 * uses_node[i][1] - 1 ;
129  }
130  }
131 }
132 
134  const BoxElemPart::ElemOrder elem_order ,
135  const BoxElemPart::Decompose decompose ,
136  const unsigned global_size ,
137  const unsigned global_rank ,
138  const unsigned elem_nx ,
139  const unsigned elem_ny ,
140  const unsigned elem_nz )
141 {
142  m_global_size = global_size ;
143  m_global_rank = global_rank ;
144  m_elem_order = elem_order ;
145  m_decompose = decompose ;
146 
147  m_global_elem_box[0][0] = 0 ; m_global_elem_box[0][1] = elem_nx ;
148  m_global_elem_box[1][0] = 0 ; m_global_elem_box[1][1] = elem_ny ;
149  m_global_elem_box[2][0] = 0 ; m_global_elem_box[2][1] = elem_nz ;
150 
151  m_global_node_box[0][0] = 0 ; m_global_node_box[0][1] = 0 ;
152  m_global_node_box[1][0] = 0 ; m_global_node_box[1][1] = 0 ;
153  m_global_node_box[2][0] = 0 ; m_global_node_box[2][1] = 0 ;
154 
155  if ( ElemLinear == elem_order ) {
156  m_global_node_box[0][1] = elem_nx + 1 ;
157  m_global_node_box[1][1] = elem_ny + 1 ;
158  m_global_node_box[2][1] = elem_nz + 1 ;
159  }
160  else if ( ElemQuadratic == elem_order ) {
161  m_global_node_box[0][1] = 2 * elem_nx + 1 ;
162  m_global_node_box[1][1] = 2 * elem_ny + 1 ;
163  m_global_node_box[2][1] = 2 * elem_nz + 1 ;
164  }
165 
166  //----------------------------------------
167 
169 
172 
173  //----------------------------------------
174 
175  size_t elem_count = Kokkos::Example::box_count( m_uses_elem_box );
176  size_t node_count = Kokkos::Example::box_count( m_owns_node_box[0] );
177 
178  m_owns_node[0][0] = global_rank ;
179  m_owns_node[0][1] = node_count ;
180  m_owns_node_count = 1 ;
181  m_send_node_count = 0 ;
182 
183  for ( unsigned rr = 1 ; rr < m_global_size ; ++rr ) {
184 
185  const unsigned rank = ( m_global_rank + rr ) % m_global_size ;
186 
187  unsigned elem_box[3][2] , o_node_box[3][2] , u_node_box[3][2] ;
188 
189  // Boxes for process 'rank'
190  local( rank , elem_box , o_node_box , u_node_box );
191 
192  // Box that this process uses but is owned by process 'rank'
194 
196 
197  if ( m_owns_node[ m_owns_node_count ][1] ) {
198  m_owns_node[ m_owns_node_count ][0] = rank ;
200  }
201 
202  // Box that this process owns and is used by process 'rank'
204 
206 
207  if ( m_send_node[ m_send_node_count ][1] ) {
208  m_send_node[ m_send_node_count ][0] = rank ;
210  }
211 
212  // Error checking:
213 
214  unsigned test_box[3][2] ;
215 
216  elem_count += Kokkos::Example::box_count( elem_box );
217  node_count += Kokkos::Example::box_count( o_node_box );
218 
219  {
220  Kokkos::Example::box_intersect( test_box , m_owns_node_box[0] , o_node_box );
221 
222  if ( Kokkos::Example::box_count( test_box ) ) {
223  std::cout << "owns_node[" << m_global_rank << "]{"
224  << " [" << m_owns_node_box[0][0][0] << "," << m_owns_node_box[0][0][1] << ")"
225  << " [" << m_owns_node_box[0][1][0] << "," << m_owns_node_box[0][1][1] << ")"
226  << " [" << m_owns_node_box[0][2][0] << "," << m_owns_node_box[0][2][1] << ")"
227  << "} intersects"
228  << " owns_node[" << rank << "]{"
229  << " [" << o_node_box[0][0] << "," << o_node_box[0][1] << ")"
230  << " [" << o_node_box[1][0] << "," << o_node_box[1][1] << ")"
231  << " [" << o_node_box[2][0] << "," << o_node_box[2][1] << ")"
232  << "}" << std::endl ;
233  }
234  }
235 
236  if ( DecomposeElem == decompose ) {
237 
238  Kokkos::Example::box_intersect( test_box , m_uses_elem_box , elem_box );
239 
240  if ( Kokkos::Example::box_count( test_box ) ) {
241 
242  std::cout << "ElemBox[" << m_global_rank << "]{"
243  << " [" << m_uses_elem_box[0][0] << "," << m_uses_elem_box[0][1] << ")"
244  << " [" << m_uses_elem_box[1][0] << "," << m_uses_elem_box[1][1] << ")"
245  << " [" << m_uses_elem_box[2][0] << "," << m_uses_elem_box[2][1] << ")"
246  << "} intersects"
247  << " ElemBox[" << rank << "]{"
248  << " [" << elem_box[0][0] << "," << elem_box[0][1] << ")"
249  << " [" << elem_box[1][0] << "," << elem_box[1][1] << ")"
250  << " [" << elem_box[2][0] << "," << elem_box[2][1] << ")"
251  << "}" << std::endl ;
252  }
253  }
254  }
255 
256  // Sentinal values at the end of the owns and send lists:
257 
258  m_owns_node[ m_owns_node_count ][0] = ~0u ;
259  m_owns_node[ m_owns_node_count ][1] = ~0u ;
260  m_owns_node_box[ m_owns_node_count ][0][0] = 0u ; m_owns_node_box[ m_owns_node_count ][0][0] = ~0u ;
261  m_owns_node_box[ m_owns_node_count ][1][0] = 0u ; m_owns_node_box[ m_owns_node_count ][1][0] = ~0u ;
262  m_owns_node_box[ m_owns_node_count ][2][0] = 0u ; m_owns_node_box[ m_owns_node_count ][2][0] = ~0u ;
263 
264  m_send_node[ m_send_node_count ][0] = ~0u ;
265  m_send_node[ m_send_node_count ][1] = ~0u ;
266  m_send_node_box[ m_send_node_count ][0][0] = 0u ; m_send_node_box[ m_send_node_count ][0][0] = ~0u ;
267  m_send_node_box[ m_send_node_count ][1][0] = 0u ; m_send_node_box[ m_send_node_count ][1][0] = ~0u ;
268  m_send_node_box[ m_send_node_count ][2][0] = 0u ; m_send_node_box[ m_send_node_count ][2][0] = ~0u ;
269 
270  {
271  size_t count = 0 ;
272  for ( unsigned i = 0 ; i < m_owns_node_count ; ++i ) {
273  count += m_owns_node[i][1] ;
274  }
275  if ( count != Kokkos::Example::box_count( m_uses_node_box ) ) {
276  std::cout << "Node uses count = " << Kokkos::Example::box_count( m_uses_node_box )
277  << " error count = " << count << std::endl ;
278  }
279  }
280 
281  if ( global_node_count != node_count ) {
282  std::cout << "Node count = " << global_node_count << " overlap error count = " << node_count << std::endl ;
283  }
284 
285  if ( DecomposeElem == decompose && global_elem_count != elem_count ) {
286  std::cout << "Elem count = " << global_elem_count << " overlap error count = " << elem_count << std::endl ;
287  }
288 }
289 
290 void BoxElemPart::print( std::ostream & s ) const
291 {
292  s << "BoxElemPart P[" << m_global_rank << ":" << m_global_size << "]"
293  << std::endl
294  << " elem_box {"
295  << " [" << m_uses_elem_box[0][0] << "," << m_uses_elem_box[0][1] << ")"
296  << " [" << m_uses_elem_box[1][0] << "," << m_uses_elem_box[1][1] << ")"
297  << " [" << m_uses_elem_box[2][0] << "," << m_uses_elem_box[2][1] << ")"
298  << " } / {"
299  << " [" << m_global_elem_box[0][0] << "," << m_global_elem_box[0][1] << ")"
300  << " [" << m_global_elem_box[1][0] << "," << m_global_elem_box[1][1] << ")"
301  << " [" << m_global_elem_box[2][0] << "," << m_global_elem_box[2][1] << ")"
302  << " }"
303  << std::endl
304  << " node_box {"
305  << " [" << m_owns_node_box[0][0][0] << "," << m_owns_node_box[0][0][1] << ")"
306  << " [" << m_owns_node_box[0][1][0] << "," << m_owns_node_box[0][1][1] << ")"
307  << " [" << m_owns_node_box[0][2][0] << "," << m_owns_node_box[0][2][1] << ")"
308  << " } / {"
309  << " [" << m_uses_node_box[0][0] << "," << m_uses_node_box[0][1] << ")"
310  << " [" << m_uses_node_box[1][0] << "," << m_uses_node_box[1][1] << ")"
311  << " [" << m_uses_node_box[2][0] << "," << m_uses_node_box[2][1] << ")"
312  << " } / {"
313  << " [" << m_global_node_box[0][0] << "," << m_global_node_box[0][1] << ")"
314  << " [" << m_global_node_box[1][0] << "," << m_global_node_box[1][1] << ")"
315  << " [" << m_global_node_box[2][0] << "," << m_global_node_box[2][1] << ")"
316  << " }"
317  << std::endl ;
318 
319  for ( unsigned i = 1 ; i < m_owns_node_count ; ++i ) {
320  s << " P[" << m_owns_node[i][0] << "]"
321  << " recv node_box {"
322  << " [" << m_owns_node_box[i][0][0] << "," << m_owns_node_box[i][0][1] << ")"
323  << " [" << m_owns_node_box[i][1][0] << "," << m_owns_node_box[i][1][1] << ")"
324  << " [" << m_owns_node_box[i][2][0] << "," << m_owns_node_box[i][2][1] << ")"
325  << " }"
326  << std::endl ;
327  }
328 
329  for ( unsigned i = 0 ; i < m_send_node_count ; ++i ) {
330  s << " P[" << m_send_node[i][0] << "]"
331  << " send node_box {"
332  << " [" << m_send_node_box[i][0][0] << "," << m_send_node_box[i][0][1] << ")"
333  << " [" << m_send_node_box[i][1][0] << "," << m_send_node_box[i][1][1] << ")"
334  << " [" << m_send_node_box[i][2][0] << "," << m_send_node_box[i][2][1] << ")"
335  << " }"
336  << std::endl ;
337  }
338 }
339 
340 } /* namespace Example */
341 } /* namespace Kokkos */
342 
343 //----------------------------------------------------------------------------
344 
345 
unsigned m_owns_node[PROC_NEIGH_MAX][2]
int * count
KOKKOS_INLINE_FUNCTION size_t global_elem_count() const
Definition: BoxElemPart.hpp:98
void print(std::ostream &s) const
BoxElemPart(const ElemOrder elem_order, const Decompose decompose, const unsigned global_size, const unsigned global_rank, const unsigned elem_nx, const unsigned elem_ny, const unsigned elem_nz)
KOKKOS_INLINE_FUNCTION size_t box_count(const unsigned box[][2])
Definition: BoxElemPart.hpp:42
unsigned m_send_node_box[PROC_NEIGH_MAX][3][2]
void box_partition(const unsigned global_size, const unsigned global_rank, const unsigned global_box[][2], unsigned box[][2])
Definition: BoxElemPart.cpp:29
KOKKOS_INLINE_FUNCTION void box_intersect(unsigned box[][2], const unsigned boxA[][2], const unsigned boxB[][2])
Definition: BoxElemPart.hpp:30
unsigned m_send_node[PROC_NEIGH_MAX][2]
unsigned m_owns_node_box[PROC_NEIGH_MAX][3][2]
unsigned m_global_elem_box[3][2]
unsigned m_global_node_box[3][2]
void local(const unsigned rank, unsigned uses_elem[][2], unsigned owns_node[][2], unsigned uses_node[][2]) const
Definition: BoxElemPart.cpp:89
KOKKOS_INLINE_FUNCTION size_t global_node_count() const