Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MPAssembly/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 size_t global_size ,
30  const size_t global_rank ,
31  const size_t global_box[][2] ,
32  size_t 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  size_t ip = 0 ;
39  size_t np = global_size ;
40 
41  while ( 1 < np ) {
42 
43  // P = [ ip + j * portion , ip + ( j + 1 ) * portion )
44 
45  size_t jip , jup ;
46 
47  {
48  const size_t part = ( 0 == ( np % 5 ) ) ? 5 : (
49  ( 0 == ( np % 3 ) ) ? 3 : 2 );
50 
51  const size_t 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 size_t 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 int 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] + size_t( double(nb[axis]) * ( double(jup) / double(np) ));
74  box[ axis ][0] = box[ axis ][0] + size_t( 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 size_t rank ,
90  size_t uses_elem[][2] ,
91  size_t owns_node[][2] ,
92  size_t uses_node[][2] ) const
93 {
95 
97 
98  for ( int 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 size_t 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 ( int 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 ( int 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 ( int 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 size_t global_size ,
137  const size_t global_rank ,
138  const size_t elem_nx ,
139  const size_t elem_ny ,
140  const size_t elem_nz )
141 {
142  m_global_size = global_size ;
143  m_global_rank = global_rank ;
144  m_decompose = decompose ;
145  m_elem_order = elem_order ;
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  m_owns_node_count = 0 ;
156  m_send_node_count = 0 ;
157 
158  m_ok = true ;
159 
160  //----------------------------------------
161 
162  if ( ElemLinear == elem_order ) {
163  m_global_node_box[0][1] = elem_nx + 1 ;
164  m_global_node_box[1][1] = elem_ny + 1 ;
165  m_global_node_box[2][1] = elem_nz + 1 ;
166  }
167  else if ( ElemQuadratic == elem_order ) {
168  m_global_node_box[0][1] = 2 * elem_nx + 1 ;
169  m_global_node_box[1][1] = 2 * elem_ny + 1 ;
170  m_global_node_box[2][1] = 2 * elem_nz + 1 ;
171  }
172 
173  //----------------------------------------
174 
176 
179 
180  //----------------------------------------
181 
182  size_t elem_count = Kokkos::Example::box_count( m_uses_elem_box );
183  size_t node_count = Kokkos::Example::box_count( m_owns_node_box[0] );
184 
185  m_owns_node[0][0] = global_rank ;
186  m_owns_node[0][1] = node_count ;
187  m_owns_node_count = 1 ;
188  m_send_node_count = 0 ;
189 
190  for ( size_t rr = 1 ; rr < m_global_size && m_ok ; ++rr ) {
191 
192  const size_t rank = ( m_global_rank + rr ) % m_global_size ;
193 
194  size_t elem_box[3][2] , o_node_box[3][2] , u_node_box[3][2] ;
195 
196  // Boxes for process 'rank'
197  local( rank , elem_box , o_node_box , u_node_box );
198 
199  // Box that this process uses but is owned by process 'rank'
201 
203 
204  if ( m_owns_node[ m_owns_node_count ][1] ) {
205 
206  if ( ( PROC_NEIGH_MAX - 1 ) <= m_owns_node_count ) {
207  std::cout << "BoxElemPart exceeded maximum neighbor count" << std::endl ;
208  m_ok = false ;
209  break ;
210  }
211 
212  m_owns_node[ m_owns_node_count ][0] = rank ;
213 
215  }
216 
217  // Box that this process owns and is used by process 'rank'
219 
221 
222  if ( m_send_node[ m_send_node_count ][1] ) {
223 
224  if ( ( PROC_NEIGH_MAX - 1 ) <= m_send_node_count ) {
225  std::cout << "BoxElemPart exceeded maximum neighbor count" << std::endl ;
226  m_ok = false ;
227  break ;
228  }
229 
230  m_send_node[ m_send_node_count ][0] = rank ;
232  }
233 
234  // Error checking:
235 
236  size_t test_box[3][2] ;
237 
238  elem_count += Kokkos::Example::box_count( elem_box );
239  node_count += Kokkos::Example::box_count( o_node_box );
240 
241  {
242  Kokkos::Example::box_intersect( test_box , m_owns_node_box[0] , o_node_box );
243 
244  if ( Kokkos::Example::box_count( test_box ) ) {
245  std::cout << "Box partitioning error" << std::endl ;
246  std::cout << "owns_node[" << m_global_rank << "]{"
247  << " [" << m_owns_node_box[0][0][0] << "," << m_owns_node_box[0][0][1] << ")"
248  << " [" << m_owns_node_box[0][1][0] << "," << m_owns_node_box[0][1][1] << ")"
249  << " [" << m_owns_node_box[0][2][0] << "," << m_owns_node_box[0][2][1] << ")"
250  << "} intersects"
251  << " owns_node[" << rank << "]{"
252  << " [" << o_node_box[0][0] << "," << o_node_box[0][1] << ")"
253  << " [" << o_node_box[1][0] << "," << o_node_box[1][1] << ")"
254  << " [" << o_node_box[2][0] << "," << o_node_box[2][1] << ")"
255  << "}" << std::endl ;
256  m_ok = false ;
257  break ;
258  }
259  }
260 
261  if ( DecomposeElem == decompose ) {
262 
263  Kokkos::Example::box_intersect( test_box , m_uses_elem_box , elem_box );
264 
265  if ( Kokkos::Example::box_count( test_box ) ) {
266  std::cout << "Box partitioning error" << std::endl ;
267  std::cout << "ElemBox[" << m_global_rank << "]{"
268  << " [" << m_uses_elem_box[0][0] << "," << m_uses_elem_box[0][1] << ")"
269  << " [" << m_uses_elem_box[1][0] << "," << m_uses_elem_box[1][1] << ")"
270  << " [" << m_uses_elem_box[2][0] << "," << m_uses_elem_box[2][1] << ")"
271  << "} intersects"
272  << " ElemBox[" << rank << "]{"
273  << " [" << elem_box[0][0] << "," << elem_box[0][1] << ")"
274  << " [" << elem_box[1][0] << "," << elem_box[1][1] << ")"
275  << " [" << elem_box[2][0] << "," << elem_box[2][1] << ")"
276  << "}" << std::endl ;
277  m_ok = false ;
278  break ;
279  }
280  }
281  }
282 
283  // Sentinal values at the end of the owns and send lists:
284 
285  m_owns_node[ m_owns_node_count ][0] = ~0u ;
286  m_owns_node[ m_owns_node_count ][1] = ~0u ;
287  m_owns_node_box[ m_owns_node_count ][0][0] = 0u ; m_owns_node_box[ m_owns_node_count ][0][0] = ~0u ;
288  m_owns_node_box[ m_owns_node_count ][1][0] = 0u ; m_owns_node_box[ m_owns_node_count ][1][0] = ~0u ;
289  m_owns_node_box[ m_owns_node_count ][2][0] = 0u ; m_owns_node_box[ m_owns_node_count ][2][0] = ~0u ;
290 
291  m_send_node[ m_send_node_count ][0] = ~0u ;
292  m_send_node[ m_send_node_count ][1] = ~0u ;
293  m_send_node_box[ m_send_node_count ][0][0] = 0u ; m_send_node_box[ m_send_node_count ][0][0] = ~0u ;
294  m_send_node_box[ m_send_node_count ][1][0] = 0u ; m_send_node_box[ m_send_node_count ][1][0] = ~0u ;
295  m_send_node_box[ m_send_node_count ][2][0] = 0u ; m_send_node_box[ m_send_node_count ][2][0] = ~0u ;
296 
297  {
298  size_t count = 0 ;
299  for ( size_t i = 0 ; i < m_owns_node_count ; ++i ) {
300  count += m_owns_node[i][1] ;
301  }
302  if ( count != Kokkos::Example::box_count( m_uses_node_box ) ) {
303  std::cout << "Node uses count = " << Kokkos::Example::box_count( m_uses_node_box )
304  << " error count = " << count << std::endl ;
305  m_ok = false ;
306  }
307  }
308 
309  if ( global_node_count != node_count ) {
310  std::cout << "Node count = " << global_node_count << " overlap error count = " << node_count << std::endl ;
311  m_ok = false ;
312  }
313 
314  if ( DecomposeElem == decompose && global_elem_count != elem_count ) {
315  std::cout << "Elem count = " << global_elem_count << " overlap error count = " << elem_count << std::endl ;
316  m_ok = false ;
317  }
318 
319  if ( ! m_ok ) {
320  for ( int i = 0 ; i < 3 ; ++i ) { for ( int j = 0 ; j < 2 ; ++j ) {
321  m_global_elem_box[i][j] = 0 ;
322  m_global_node_box[i][j] = 0 ;
323  m_uses_elem_box[i][j] = 0 ;
324  m_uses_node_box[i][j] = 0 ;
325  }}
326  m_owns_node_count = 0 ;
327  m_send_node_count = 0 ;
328  }
329 }
330 
331 void BoxElemPart::print( std::ostream & s ) const
332 {
333  s << "BoxElemPart P[" << m_global_rank << ":" << m_global_size << "]"
334  << std::endl
335  << " elem_box {"
336  << " [" << m_uses_elem_box[0][0] << "," << m_uses_elem_box[0][1] << ")"
337  << " [" << m_uses_elem_box[1][0] << "," << m_uses_elem_box[1][1] << ")"
338  << " [" << m_uses_elem_box[2][0] << "," << m_uses_elem_box[2][1] << ")"
339  << " } / {"
340  << " [" << m_global_elem_box[0][0] << "," << m_global_elem_box[0][1] << ")"
341  << " [" << m_global_elem_box[1][0] << "," << m_global_elem_box[1][1] << ")"
342  << " [" << m_global_elem_box[2][0] << "," << m_global_elem_box[2][1] << ")"
343  << " }"
344  << std::endl
345  << " node_box {"
346  << " [" << m_owns_node_box[0][0][0] << "," << m_owns_node_box[0][0][1] << ")"
347  << " [" << m_owns_node_box[0][1][0] << "," << m_owns_node_box[0][1][1] << ")"
348  << " [" << m_owns_node_box[0][2][0] << "," << m_owns_node_box[0][2][1] << ")"
349  << " } / {"
350  << " [" << m_uses_node_box[0][0] << "," << m_uses_node_box[0][1] << ")"
351  << " [" << m_uses_node_box[1][0] << "," << m_uses_node_box[1][1] << ")"
352  << " [" << m_uses_node_box[2][0] << "," << m_uses_node_box[2][1] << ")"
353  << " } / {"
354  << " [" << m_global_node_box[0][0] << "," << m_global_node_box[0][1] << ")"
355  << " [" << m_global_node_box[1][0] << "," << m_global_node_box[1][1] << ")"
356  << " [" << m_global_node_box[2][0] << "," << m_global_node_box[2][1] << ")"
357  << " }"
358  << std::endl ;
359 
360  for ( size_t i = 1 ; i < m_owns_node_count ; ++i ) {
361  s << " P[" << m_owns_node[i][0] << "]"
362  << " recv node_box {"
363  << " [" << m_owns_node_box[i][0][0] << "," << m_owns_node_box[i][0][1] << ")"
364  << " [" << m_owns_node_box[i][1][0] << "," << m_owns_node_box[i][1][1] << ")"
365  << " [" << m_owns_node_box[i][2][0] << "," << m_owns_node_box[i][2][1] << ")"
366  << " }"
367  << std::endl ;
368  }
369 
370  for ( size_t i = 0 ; i < m_send_node_count ; ++i ) {
371  s << " P[" << m_send_node[i][0] << "]"
372  << " send node_box {"
373  << " [" << m_send_node_box[i][0][0] << "," << m_send_node_box[i][0][1] << ")"
374  << " [" << m_send_node_box[i][1][0] << "," << m_send_node_box[i][1][1] << ")"
375  << " [" << m_send_node_box[i][2][0] << "," << m_send_node_box[i][2][1] << ")"
376  << " }"
377  << std::endl ;
378  }
379 }
380 
381 } /* namespace Example */
382 } /* namespace Kokkos */
383 
384 //----------------------------------------------------------------------------
385 
386 
unsigned m_send_node_box[PROC_NEIGH_MAX][3][2]
KOKKOS_INLINE_FUNCTION size_t global_elem_count() const
unsigned m_owns_node[PROC_NEIGH_MAX][2]
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])
void box_partition(const unsigned global_size, const unsigned global_rank, const unsigned global_box[][2], unsigned box[][2])
KOKKOS_INLINE_FUNCTION void box_intersect(unsigned box[][2], const unsigned boxA[][2], const unsigned boxB[][2])
unsigned m_owns_node_box[PROC_NEIGH_MAX][3][2]
void local(const unsigned rank, unsigned uses_elem[][2], unsigned owns_node[][2], unsigned uses_node[][2]) const
KOKKOS_INLINE_FUNCTION size_t global_node_count() const
unsigned m_send_node[PROC_NEIGH_MAX][2]