Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FadMPAssembly/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_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]