Branch data Line data Source code
1 : : /* compile-time settings:
2 : :
3 : : FORTRAN naming convention
4 : : default cpgs_setup, etc.
5 : : -DUPCASE CPGS_SETUP, etc.
6 : : -DUNDERSCORE cpgs_setup_, etc.
7 : :
8 : : -DMPI parallel version (sequential otherwise)
9 : : -DCRYSTAL_STATIC avoid some message exchange at the risk of
10 : : crashing b/c of insufficient buffer size
11 : :
12 : : -DINITIAL_BUFFER_SIZE=expression
13 : : ignored unless CRYSTAL_STATIC is defined.
14 : : arithmetic expression controlling the initial buffer size for the crystal
15 : : router; this needs to be large enough to hold the intermediate messages
16 : : during all stages of the crystal router
17 : :
18 : : variables that can be used in expression include
19 : : num - the number of processors
20 : : n - the length of the global index array
21 : :
22 : : */
23 : :
24 : : /* default for INITIAL_BUFFER_SIZE */
25 : : #ifdef CRYSTAL_STATIC
26 : : #ifndef INITIAL_BUFFER_SIZE
27 : : #define INITIAL_BUFFER_SIZE 2 * ( 3 * num + n * 9 )
28 : : #endif
29 : : #endif
30 : :
31 : : /* FORTRAN usage:
32 : :
33 : : integer hc, np
34 : : call crystal_new(hc,comm,np) ! get a crystal router handle (see fcrystal.c)
35 : :
36 : : integer hgs
37 : : integer n, max_vec_dim
38 : : integer*? global_index_array(1:n) ! type corresponding to slong in "types.h"
39 : :
40 : : call cpgs_setup(hgs,hc,global_index_array,n,max_vec_dim)
41 : : sets hgs to new handle
42 : :
43 : : !ok to call crystal_done(hc) here, or any later time
44 : :
45 : : call cpgs_op(hgs, u, op)
46 : : integer handle, op : 1-add, 2-multiply, 3-min, 4-max
47 : : real u(1:n) - same layout as global_index_array provided to cpgs_setup
48 : :
49 : : call cpgs_op_vec(hgs, u, d, op)
50 : : integer op : 1-add, 2-multiply, 3-min, 4-max
51 : : integer d <= max_vec_dim
52 : : real u(1:d, 1:n) - vector components for each node stored together
53 : :
54 : : call cpgs_op_many(hgs, u1, u2, u3, u4, u5, u6, d, op)
55 : : integer op : 1-add, 2-multiply, 3-min, 4-max
56 : : integer d : in {1,2,3,4,5,6}, <= max_vec_dim
57 : : real u1(1:n), u2(1:n), u3(1:n), etc.
58 : :
59 : : same effect as: call cpgs_op(hgs, u1, op)
60 : : if(d.gt.1) call cpgs_op(hgs, u2, op)
61 : : if(d.gt.2) call cpgs_op(hgs, u3, op)
62 : : etc.
63 : : with possibly some savings as fewer messages are exchanged
64 : :
65 : : call cpgs_free(hgs)
66 : : */
67 : :
68 : : #include <stdio.h>
69 : : #include <stdlib.h>
70 : : #include <stdarg.h>
71 : : #include <string.h>
72 : : #include <math.h>
73 : : #include "moab/gs.hpp"
74 : : #ifdef MOAB_HAVE_MPI
75 : : #include "moab_mpi.h"
76 : : #endif
77 : :
78 : : #ifdef MOAB_HAVE_MPI
79 : :
80 : : #ifdef MOAB_HAVE_VALGRIND
81 : : #include <valgrind/memcheck.h>
82 : : #elif !defined( VALGRIND_CHECK_MEM_IS_DEFINED )
83 : : #define VALGRIND_CHECK_MEM_IS_DEFINED( a, b ) ( (void)0 )
84 : : #endif
85 : :
86 : : #endif
87 : :
88 : : namespace moab
89 : : {
90 : :
91 : : /*--------------------------------------------------------------------------
92 : : Local Execution Phases
93 : : --------------------------------------------------------------------------*/
94 : :
95 : : #define DO_SET( a, b ) b = a
96 : : #define DO_ADD( a, b ) a += b
97 : : #define DO_MUL( a, b ) a *= b
98 : : #define DO_MIN( a, b ) \
99 : : if( b < a ) a = b
100 : : #define DO_MAX( a, b ) \
101 : : if( b > a ) a = b
102 : : #define DO_BPR( a, b ) \
103 : : do \
104 : : { \
105 : : uint a_ = a; \
106 : : uint b_ = b; \
107 : : for( ;; ) \
108 : : { \
109 : : if( a_ < b_ ) \
110 : : b_ >>= 1; \
111 : : else if( b_ < a_ ) \
112 : : a_ >>= 1; \
113 : : else \
114 : : break; \
115 : : } \
116 : : a = a_; \
117 : : } while( 0 )
118 : :
119 : : #define LOOP( op ) \
120 : : do \
121 : : { \
122 : : sint i, j; \
123 : : while( ( i = *cm++ ) != -1 ) \
124 : : while( ( j = *cm++ ) != -1 ) \
125 : : op( u[i], u[j] ); \
126 : : } while( 0 )
127 : :
128 : 0 : static void local_condense( realType* u, int op, const sint* cm )
129 : : {
130 [ # # # # : 0 : switch( op )
# # ]
131 : : {
132 : : case GS_OP_ADD:
133 [ # # ][ # # ]: 0 : LOOP( DO_ADD );
134 : 0 : break;
135 : : case GS_OP_MUL:
136 [ # # ][ # # ]: 0 : LOOP( DO_MUL );
137 : 0 : break;
138 : : case GS_OP_MIN:
139 [ # # ][ # # ]: 0 : LOOP( DO_MIN );
[ # # ]
140 : 0 : break;
141 : : case GS_OP_MAX:
142 [ # # ][ # # ]: 0 : LOOP( DO_MAX );
[ # # ]
143 : 0 : break;
144 : : case GS_OP_BPR:
145 [ # # ][ # # ]: 0 : LOOP( DO_BPR );
[ # # ][ # # ]
146 : 0 : break;
147 : : }
148 : 0 : }
149 : :
150 : 0 : static void local_uncondense( realType* u, const sint* cm )
151 : : {
152 [ # # ][ # # ]: 0 : LOOP( DO_SET );
153 : 0 : }
154 : :
155 : : #undef LOOP
156 : :
157 : : #define LOOP( op ) \
158 : : do \
159 : : { \
160 : : sint i, j, k; \
161 : : while( ( i = *cm++ ) != -1 ) \
162 : : { \
163 : : realType* pi = u + n * i; \
164 : : while( ( j = *cm++ ) != -1 ) \
165 : : { \
166 : : realType* pj = u + n * j; \
167 : : for( k = n; k; --k ) \
168 : : { \
169 : : op( *pi, *pj ); \
170 : : ++pi; \
171 : : ++pj; \
172 : : } \
173 : : } \
174 : : } \
175 : : } while( 0 )
176 : :
177 : 0 : static void local_condense_vec( realType* u, uint n, int op, const sint* cm )
178 : : {
179 [ # # # # : 0 : switch( op )
# # ]
180 : : {
181 : : case GS_OP_ADD:
182 [ # # ][ # # ]: 0 : LOOP( DO_ADD );
[ # # ]
183 : 0 : break;
184 : : case GS_OP_MUL:
185 [ # # ][ # # ]: 0 : LOOP( DO_MUL );
[ # # ]
186 : 0 : break;
187 : : case GS_OP_MIN:
188 [ # # ][ # # ]: 0 : LOOP( DO_MIN );
[ # # ][ # # ]
189 : 0 : break;
190 : : case GS_OP_MAX:
191 [ # # ][ # # ]: 0 : LOOP( DO_MAX );
[ # # ][ # # ]
192 : 0 : break;
193 : : case GS_OP_BPR:
194 [ # # ][ # # ]: 0 : LOOP( DO_BPR );
[ # # ][ # # ]
[ # # ]
195 : 0 : break;
196 : : }
197 : 0 : }
198 : :
199 : 0 : static void local_uncondense_vec( realType* u, uint n, const sint* cm )
200 : : {
201 [ # # ][ # # ]: 0 : LOOP( DO_SET );
[ # # ]
202 : 0 : }
203 : :
204 : : #undef LOOP
205 : :
206 : : /*--------------------------------------------------------------------------
207 : : Non-local Execution Phases
208 : : --------------------------------------------------------------------------*/
209 : :
210 : : #ifdef MOAB_HAVE_MPI
211 : :
212 : 0 : void gs_data::nonlocal_info::initialize( uint np, uint count, uint nlabels, uint nulabels, uint maxv )
213 : : {
214 : 0 : _target = NULL;
215 : 0 : _nshared = NULL;
216 : 0 : _sh_ind = NULL;
217 : 0 : _slabels = NULL;
218 : 0 : _ulabels = NULL;
219 : 0 : _reqs = NULL;
220 : 0 : _buf = NULL;
221 : 0 : _np = np;
222 : 0 : _target = (uint*)malloc( ( 2 * np + count ) * sizeof( uint ) );
223 : 0 : _nshared = _target + np;
224 : 0 : _sh_ind = _nshared + np;
225 [ # # ]: 0 : if( 1 < nlabels )
226 : 0 : _slabels = (slong*)malloc( ( ( nlabels - 1 ) * count ) * sizeof( slong ) );
227 : : else
228 : 0 : _slabels = NULL;
229 : 0 : _ulabels = (Ulong*)malloc( ( nulabels * count ) * sizeof( Ulong ) );
230 : 0 : _reqs = (MPI_Request*)malloc( 2 * np * sizeof( MPI_Request ) );
231 : 0 : _buf = (realType*)malloc( ( 2 * count * maxv ) * sizeof( realType ) );
232 : 0 : _maxv = maxv;
233 : 0 : }
234 : :
235 : 0 : void gs_data::nonlocal_info::nlinfo_free()
236 : : {
237 : : // Free the ptrs
238 : 0 : free( _buf );
239 : 0 : free( _reqs );
240 : 0 : free( _target );
241 : 0 : free( _slabels );
242 : 0 : free( _ulabels );
243 : : // Set to null
244 : 0 : _ulabels = NULL;
245 : 0 : _buf = NULL;
246 : 0 : _reqs = NULL;
247 : 0 : _target = NULL;
248 : 0 : _slabels = NULL;
249 : 0 : _nshared = NULL;
250 : 0 : _sh_ind = NULL;
251 : 0 : }
252 : :
253 : 0 : void gs_data::nonlocal_info::nonlocal( realType* u, int op, MPI_Comm comm )
254 : : {
255 : : MPI_Status status;
256 : 0 : uint np = this->_np;
257 : 0 : MPI_Request* reqs = this->_reqs;
258 : 0 : uint* targ = this->_target;
259 : 0 : uint* nshared = this->_nshared;
260 : 0 : uint* sh_ind = this->_sh_ind;
261 : : uint id;
262 : 0 : realType *buf = this->_buf, *start;
263 : : unsigned int i;
264 : : {
265 [ # # ]: 0 : MPI_Comm_rank( comm, (int*)&i );
266 : 0 : id = i;
267 : : }
268 [ # # ]: 0 : for( i = 0; i < np; ++i )
269 : : {
270 : 0 : uint c = nshared[i];
271 : 0 : start = buf;
272 [ # # ]: 0 : for( ; c; --c )
273 : 0 : *buf++ = u[*sh_ind++];
274 [ # # ]: 0 : MPI_Isend( (void*)start, nshared[i] * sizeof( realType ), MPI_UNSIGNED_CHAR, targ[i], id, comm, reqs++ );
275 : : }
276 : 0 : start = buf;
277 [ # # ]: 0 : for( i = 0; i < np; ++i )
278 : : {
279 [ # # ]: 0 : MPI_Irecv( (void*)start, nshared[i] * sizeof( realType ), MPI_UNSIGNED_CHAR, targ[i], targ[i], comm, reqs++ );
280 : 0 : start += nshared[i];
281 : : }
282 [ # # ]: 0 : for( reqs = this->_reqs, i = np * 2; i; --i )
283 [ # # ]: 0 : MPI_Wait( reqs++, &status );
284 : 0 : sh_ind = this->_sh_ind;
285 : : #define LOOP( OP ) \
286 : : do \
287 : : { \
288 : : for( i = 0; i < np; ++i ) \
289 : : { \
290 : : uint c; \
291 : : for( c = nshared[i]; c; --c ) \
292 : : { \
293 : : OP( u[*sh_ind], *buf ); \
294 : : ++sh_ind, ++buf; \
295 : : } \
296 : : } \
297 : : } while( 0 )
298 [ # # # # : 0 : switch( op )
# # ]
299 : : {
300 : : case GS_OP_ADD:
301 [ # # ][ # # ]: 0 : LOOP( DO_ADD );
302 : 0 : break;
303 : : case GS_OP_MUL:
304 [ # # ][ # # ]: 0 : LOOP( DO_MUL );
305 : 0 : break;
306 : : case GS_OP_MIN:
307 [ # # ][ # # ]: 0 : LOOP( DO_MIN );
[ # # ]
308 : 0 : break;
309 : : case GS_OP_MAX:
310 [ # # ][ # # ]: 0 : LOOP( DO_MAX );
[ # # ]
311 : 0 : break;
312 : : case GS_OP_BPR:
313 [ # # ][ # # ]: 0 : LOOP( DO_BPR );
[ # # ][ # # ]
314 : 0 : break;
315 : : }
316 : : #undef LOOP
317 : 0 : }
318 : :
319 : 0 : void gs_data::nonlocal_info::nonlocal_vec( realType* u, uint n, int op, MPI_Comm comm )
320 : : {
321 : : MPI_Status status;
322 : 0 : uint np = this->_np;
323 : 0 : MPI_Request* reqs = this->_reqs;
324 : 0 : uint* targ = this->_target;
325 : 0 : uint* nshared = this->_nshared;
326 : 0 : uint* sh_ind = this->_sh_ind;
327 : : uint id;
328 : 0 : realType *buf = this->_buf, *start;
329 : 0 : uint size = n * sizeof( realType );
330 : : unsigned int i;
331 : : {
332 [ # # ]: 0 : MPI_Comm_rank( comm, (int*)&i );
333 : 0 : id = i;
334 : : }
335 [ # # ]: 0 : for( i = 0; i < np; ++i )
336 : : {
337 : 0 : uint ns = nshared[i], c = ns;
338 : 0 : start = buf;
339 [ # # ]: 0 : for( ; c; --c )
340 : : {
341 : 0 : memcpy( buf, u + n * ( *sh_ind++ ), size );
342 : 0 : buf += n;
343 : : }
344 [ # # ]: 0 : MPI_Isend( (void*)start, ns * size, MPI_UNSIGNED_CHAR, targ[i], id, comm, reqs++ );
345 : : }
346 : 0 : start = buf;
347 [ # # ]: 0 : for( i = 0; i < np; ++i )
348 : : {
349 : 0 : int nsn = n * nshared[i];
350 [ # # ]: 0 : MPI_Irecv( (void*)start, nsn * size, MPI_UNSIGNED_CHAR, targ[i], targ[i], comm, reqs++ );
351 : 0 : start += nsn;
352 : : }
353 [ # # ]: 0 : for( reqs = this->_reqs, i = np * 2; i; --i )
354 [ # # ]: 0 : MPI_Wait( reqs++, &status );
355 : 0 : sh_ind = this->_sh_ind;
356 : : #define LOOP( OP ) \
357 : : do \
358 : : { \
359 : : for( i = 0; i < np; ++i ) \
360 : : { \
361 : : uint c, j; \
362 : : for( c = nshared[i]; c; --c ) \
363 : : { \
364 : : realType* uu = u + n * ( *sh_ind++ ); \
365 : : for( j = n; j; --j ) \
366 : : { \
367 : : OP( *uu, *buf ); \
368 : : ++uu; \
369 : : ++buf; \
370 : : } \
371 : : } \
372 : : } \
373 : : } while( 0 )
374 [ # # # # : 0 : switch( op )
# # ]
375 : : {
376 : : case GS_OP_ADD:
377 [ # # ][ # # ]: 0 : LOOP( DO_ADD );
[ # # ]
378 : 0 : break;
379 : : case GS_OP_MUL:
380 [ # # ][ # # ]: 0 : LOOP( DO_MUL );
[ # # ]
381 : 0 : break;
382 : : case GS_OP_MIN:
383 [ # # ][ # # ]: 0 : LOOP( DO_MIN );
[ # # ][ # # ]
384 : 0 : break;
385 : : case GS_OP_MAX:
386 [ # # ][ # # ]: 0 : LOOP( DO_MAX );
[ # # ][ # # ]
387 : 0 : break;
388 : : case GS_OP_BPR:
389 [ # # ][ # # ]: 0 : LOOP( DO_BPR );
[ # # ][ # # ]
[ # # ]
390 : 0 : break;
391 : : }
392 : : #undef LOOP
393 : 0 : }
394 : :
395 : 0 : void gs_data::nonlocal_info::nonlocal_many( realType** u, uint n, int op, MPI_Comm comm )
396 : : {
397 : : MPI_Status status;
398 : 0 : uint np = this->_np;
399 : 0 : MPI_Request* reqs = this->_reqs;
400 : 0 : uint* targ = this->_target;
401 : 0 : uint* nshared = this->_nshared;
402 : 0 : uint* sh_ind = this->_sh_ind;
403 : : uint id;
404 : 0 : realType *buf = this->_buf, *start;
405 : : unsigned int i;
406 : : {
407 [ # # ]: 0 : MPI_Comm_rank( comm, (int*)&i );
408 : 0 : id = i;
409 : : }
410 [ # # ]: 0 : for( i = 0; i < np; ++i )
411 : : {
412 : 0 : uint c, j, ns = nshared[i];
413 : 0 : start = buf;
414 [ # # ]: 0 : for( j = 0; j < n; ++j )
415 : : {
416 : 0 : realType* uu = u[j];
417 [ # # ]: 0 : for( c = 0; c < ns; ++c )
418 : 0 : *buf++ = uu[sh_ind[c]];
419 : : }
420 : 0 : sh_ind += ns;
421 [ # # ]: 0 : MPI_Isend( (void*)start, n * ns * sizeof( realType ), MPI_UNSIGNED_CHAR, targ[i], id, comm, reqs++ );
422 : : }
423 : 0 : start = buf;
424 [ # # ]: 0 : for( i = 0; i < np; ++i )
425 : : {
426 : 0 : int nsn = n * nshared[i];
427 [ # # ]: 0 : MPI_Irecv( (void*)start, nsn * sizeof( realType ), MPI_UNSIGNED_CHAR, targ[i], targ[i], comm, reqs++ );
428 : 0 : start += nsn;
429 : : }
430 [ # # ]: 0 : for( reqs = this->_reqs, i = np * 2; i; --i )
431 [ # # ]: 0 : MPI_Wait( reqs++, &status );
432 : 0 : sh_ind = this->_sh_ind;
433 : : #define LOOP( OP ) \
434 : : do \
435 : : { \
436 : : for( i = 0; i < np; ++i ) \
437 : : { \
438 : : uint c, j, ns = nshared[i]; \
439 : : for( j = 0; j < n; ++j ) \
440 : : { \
441 : : realType* uu = u[j]; \
442 : : for( c = 0; c < ns; ++c ) \
443 : : { \
444 : : OP( uu[sh_ind[c]], *buf ); \
445 : : ++buf; \
446 : : } \
447 : : } \
448 : : sh_ind += ns; \
449 : : } \
450 : : } while( 0 )
451 [ # # # # : 0 : switch( op )
# # ]
452 : : {
453 : : case GS_OP_ADD:
454 [ # # ][ # # ]: 0 : LOOP( DO_ADD );
[ # # ]
455 : 0 : break;
456 : : case GS_OP_MUL:
457 [ # # ][ # # ]: 0 : LOOP( DO_MUL );
[ # # ]
458 : 0 : break;
459 : : case GS_OP_MIN:
460 [ # # ][ # # ]: 0 : LOOP( DO_MIN );
[ # # ][ # # ]
461 : 0 : break;
462 : : case GS_OP_MAX:
463 [ # # ][ # # ]: 0 : LOOP( DO_MAX );
[ # # ][ # # ]
464 : 0 : break;
465 : : case GS_OP_BPR:
466 [ # # ][ # # ]: 0 : LOOP( DO_BPR );
[ # # ][ # # ]
[ # # ]
467 : 0 : break;
468 : : }
469 : : #undef LOOP
470 : 0 : }
471 : :
472 : : /*---------------------------------------------------------------------------
473 : : MOAB Crystal Router
474 : : ---------------------------------------------------------------------------*/
475 [ # # ][ # # ]: 0 : gs_data::crystal_data::crystal_data() {}
[ # # # # ]
476 : :
477 : 0 : void gs_data::crystal_data::initialize( MPI_Comm comm )
478 : : {
479 : : int num, id;
480 [ # # ]: 0 : buffers[0].buf.buffer_init( 1024 );
481 [ # # ]: 0 : buffers[1].buf.buffer_init( 1024 );
482 [ # # ]: 0 : buffers[2].buf.buffer_init( 1024 );
483 : 0 : all = &buffers[0];
484 : 0 : keep = &buffers[1];
485 : 0 : send = &buffers[2];
486 : 0 : memcpy( &( this->_comm ), &comm, sizeof( MPI_Comm ) );
487 [ # # ]: 0 : MPI_Comm_rank( comm, &id );
488 : 0 : this->_id = id;
489 [ # # ]: 0 : MPI_Comm_size( comm, &num );
490 : 0 : this->_num = num;
491 : 0 : }
492 : :
493 : 0 : void gs_data::crystal_data::reset()
494 : : {
495 : 0 : buffers[0].buf.reset();
496 : 0 : buffers[1].buf.reset();
497 : 0 : buffers[2].buf.reset();
498 : 0 : keep = NULL;
499 : 0 : all = NULL;
500 : 0 : send = NULL;
501 : 0 : }
502 : :
503 : : // Partition data before sending
504 : 0 : void gs_data::crystal_data::partition( uint cutoff, crystal_buf* lo, crystal_buf* hi )
505 : : {
506 : 0 : const uint* src = (uint*)all->buf.ptr;
507 : 0 : const uint* end = (uint*)src + all->n;
508 : : uint *target, *lop, *hip;
509 : 0 : lo->n = hi->n = 0;
510 : 0 : lo->buf.buffer_reserve( all->n * sizeof( uint ) );
511 : 0 : hi->buf.buffer_reserve( all->n * sizeof( uint ) );
512 : 0 : lop = (uint*)lo->buf.ptr;
513 : 0 : hip = (uint*)hi->buf.ptr;
514 [ # # ]: 0 : while( src != end )
515 : : {
516 : 0 : uint chunk_len = 3 + src[2];
517 [ # # ]: 0 : if( src[0] < cutoff )
518 : : {
519 : 0 : target = lop;
520 : 0 : lo->n += chunk_len;
521 : 0 : lop += chunk_len;
522 : : }
523 : : else
524 : : {
525 : 0 : target = hip;
526 : 0 : hi->n += chunk_len;
527 : 0 : hip += chunk_len;
528 : : }
529 : 0 : memcpy( target, src, chunk_len * sizeof( uint ) );
530 : 0 : src += chunk_len;
531 : : }
532 : 0 : }
533 : :
534 : : // Send message to target process
535 : 0 : void gs_data::crystal_data::send_( uint target, int recvn )
536 : : {
537 : 0 : MPI_Request req[3] = { MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL };
538 : : MPI_Status status[3];
539 : 0 : uint count[2] = { 0, 0 }, sum, *recv[2];
540 : : crystal_buf* t;
541 : : int i;
542 : :
543 : : (void)VALGRIND_CHECK_MEM_IS_DEFINED( &send->n, sizeof( uint ) );
544 [ # # ]: 0 : MPI_Isend( (void*)&send->n, sizeof( uint ), MPI_UNSIGNED_CHAR, target, _id, _comm, &req[0] );
545 [ # # ]: 0 : for( i = 0; i < recvn; ++i )
546 [ # # ]: 0 : MPI_Irecv( (void*)&count[i], sizeof( uint ), MPI_UNSIGNED_CHAR, target + i, target + i, _comm, &req[i + 1] );
547 [ # # ]: 0 : MPI_Waitall( recvn + 1, req, status );
548 : 0 : sum = keep->n;
549 [ # # ]: 0 : for( i = 0; i < recvn; ++i )
550 : 0 : sum += count[i];
551 [ # # ]: 0 : keep->buf.buffer_reserve( sum * sizeof( uint ) );
552 : 0 : recv[0] = (uint*)keep->buf.ptr;
553 : 0 : recv[0] += keep->n;
554 : 0 : recv[1] = recv[0] + count[0];
555 : 0 : keep->n = sum;
556 : :
557 : : (void)VALGRIND_CHECK_MEM_IS_DEFINED( send->buf.ptr, send->n * sizeof( uint ) );
558 [ # # ]: 0 : MPI_Isend( (void*)send->buf.ptr, send->n * sizeof( uint ), MPI_UNSIGNED_CHAR, target, _id, _comm, &req[0] );
559 [ # # ]: 0 : if( recvn )
560 : : {
561 [ # # ]: 0 : MPI_Irecv( (void*)recv[0], count[0] * sizeof( uint ), MPI_UNSIGNED_CHAR, target, target, _comm, &req[1] );
562 [ # # ]: 0 : if( recvn == 2 )
563 : 0 : MPI_Irecv( (void*)recv[1], count[1] * sizeof( uint ), MPI_UNSIGNED_CHAR, target + 1, target + 1, _comm,
564 [ # # ]: 0 : &req[2] );
565 : : }
566 [ # # ]: 0 : MPI_Waitall( recvn + 1, req, status );
567 : :
568 : 0 : t = all;
569 : 0 : all = keep;
570 : 0 : keep = t;
571 : 0 : }
572 : :
573 : 0 : void gs_data::crystal_data::crystal_router()
574 : : {
575 : 0 : uint bl = 0, bh, n = _num, nl, target;
576 : : int recvn;
577 : : crystal_buf *lo, *hi;
578 [ # # ]: 0 : while( n > 1 )
579 : : {
580 : 0 : nl = n / 2, bh = bl + nl;
581 [ # # ]: 0 : if( _id < bh )
582 : : {
583 : 0 : target = _id + nl;
584 [ # # ][ # # ]: 0 : recvn = ( n & 1 && _id == bh - 1 ) ? 2 : 1;
585 : 0 : lo = keep;
586 : 0 : hi = send;
587 : : }
588 : : else
589 : : {
590 : 0 : target = _id - nl;
591 [ # # ]: 0 : recvn = ( target == bh ) ? ( --target, 0 ) : 1;
592 : 0 : hi = keep;
593 : 0 : lo = send;
594 : : }
595 : 0 : partition( bh, lo, hi );
596 : 0 : send_( target, recvn );
597 [ # # ]: 0 : if( _id < bh )
598 : 0 : n = nl;
599 : : else
600 : : {
601 : 0 : n -= nl;
602 : 0 : bl = bh;
603 : : }
604 : : }
605 : 0 : }
606 : :
607 : : #define UINT_PER_X( X ) ( ( sizeof( X ) + sizeof( uint ) - 1 ) / sizeof( uint ) )
608 : : #define UINT_PER_REAL UINT_PER_X( realType )
609 : : #define UINT_PER_LONG UINT_PER_X( slong )
610 : : #define UINT_PER_ULONG UINT_PER_X( Ulong )
611 : :
612 : : /*-------------------------------------------------------------------------
613 : : Transfer
614 : : -------------------------------------------------------------------------*/
615 : 0 : ErrorCode gs_data::crystal_data::gs_transfer( int dynamic, moab::TupleList& tl, unsigned pf )
616 : : {
617 : :
618 : : unsigned mi, ml, mul, mr;
619 [ # # ]: 0 : tl.getTupleSize( mi, ml, mul, mr );
620 : :
621 : 0 : const unsigned tsize = ( mi - 1 ) + ml * UINT_PER_LONG + mul * UINT_PER_ULONG + mr * UINT_PER_REAL;
622 : 0 : sint p, lp = -1;
623 : : sint* ri;
624 : : slong* rl;
625 : : Ulong* rul;
626 : : realType* rr;
627 : 0 : uint i, j, *buf, *len = 0, *buf_end;
628 : :
629 : : /* sort to group by target proc */
630 [ # # ]: 0 : if( pf >= mi ) return moab::MB_MEMORY_ALLOCATION_FAILED;
631 : : // fail("pf expected to be in vi array (%d, %d)", pf, mi);
632 [ # # ]: 0 : tl.sort( pf, &all->buf );
633 : :
634 : : /* pack into buffer for crystal router */
635 [ # # ][ # # ]: 0 : all->buf.buffer_reserve( ( tl.get_n() * ( 3 + tsize ) ) * sizeof( uint ) );
636 : 0 : all->n = 0;
637 : 0 : buf = (uint*)all->buf.ptr;
638 : :
639 [ # # ]: 0 : bool canWrite = tl.get_writeEnabled();
640 [ # # ][ # # ]: 0 : if( !canWrite ) tl.enableWriteAccess();
641 : :
642 : 0 : ri = tl.vi_wr;
643 : 0 : rl = tl.vl_wr;
644 : 0 : rul = tl.vul_wr;
645 : 0 : rr = tl.vr_wr;
646 : :
647 [ # # ][ # # ]: 0 : for( i = tl.get_n(); i; --i )
648 : : {
649 : 0 : p = ri[pf];
650 [ # # ]: 0 : if( p != lp )
651 : : {
652 : 0 : lp = p;
653 : 0 : *buf++ = p; /* target */
654 : 0 : *buf++ = _id; /* source */
655 : 0 : len = buf++;
656 : 0 : *len = 0; /* length */
657 : 0 : all->n += 3;
658 : : }
659 [ # # ]: 0 : for( j = 0; j < mi; ++j, ++ri )
660 [ # # ]: 0 : if( j != pf ) *buf++ = *ri;
661 [ # # ]: 0 : for( j = ml; j; --j, ++rl )
662 : : {
663 : 0 : memcpy( buf, rl, sizeof( slong ) );
664 : 0 : buf += UINT_PER_LONG;
665 : : }
666 [ # # ]: 0 : for( j = mul; j; --j, ++rul )
667 : : {
668 : 0 : memcpy( buf, rul, sizeof( Ulong ) );
669 : 0 : buf += UINT_PER_ULONG;
670 : : }
671 [ # # ]: 0 : for( j = mr; j; --j, ++rr )
672 : : {
673 : 0 : memcpy( buf, rr, sizeof( realType ) );
674 : 0 : buf += UINT_PER_REAL;
675 : : }
676 : 0 : *len += tsize, all->n += tsize;
677 : : }
678 : :
679 [ # # ]: 0 : crystal_router();
680 : :
681 : : /* unpack */
682 : 0 : buf = (uint*)all->buf.ptr;
683 : 0 : buf_end = buf + all->n;
684 [ # # ]: 0 : tl.set_n( 0 );
685 : 0 : ri = tl.vi_wr;
686 : 0 : rl = tl.vl_wr;
687 : 0 : rul = tl.vul_wr;
688 : 0 : rr = tl.vr_wr;
689 : :
690 [ # # ]: 0 : while( buf != buf_end )
691 : : {
692 : : sint llen;
693 : 0 : buf++; /* target ( == this proc ) */
694 : 0 : p = *buf++; /* source */
695 : 0 : llen = *buf++; /* length */
696 [ # # ]: 0 : while( llen > 0 )
697 : : {
698 [ # # ][ # # ]: 0 : if( tl.get_n() == tl.get_max() )
[ # # ]
699 : : {
700 [ # # ]: 0 : if( !dynamic )
701 : : {
702 [ # # ][ # # ]: 0 : tl.set_n( tl.get_max() + 1 );
703 [ # # ][ # # ]: 0 : if( !canWrite ) tl.disableWriteAccess();
704 : 0 : return moab::MB_SUCCESS;
705 : : }
706 [ # # ][ # # ]: 0 : ErrorCode rval = tl.resize( tl.get_max() + ( 1 + tl.get_max() ) / 2 + 1 );
[ # # ]
707 [ # # ]: 0 : if( rval != moab::MB_SUCCESS )
708 : : {
709 [ # # ][ # # ]: 0 : if( !canWrite ) tl.disableWriteAccess();
710 : 0 : return rval;
711 : : }
712 [ # # ]: 0 : ri = tl.vi_wr + mi * tl.get_n();
713 [ # # ]: 0 : rl = tl.vl_wr + ml * tl.get_n();
714 [ # # ]: 0 : rul = tl.vul_wr + mul * tl.get_n();
715 [ # # ]: 0 : rr = tl.vr_wr + mr * tl.get_n();
716 : : }
717 [ # # ]: 0 : tl.inc_n();
718 [ # # ]: 0 : for( j = 0; j < mi; ++j )
719 [ # # ]: 0 : if( j != pf )
720 : 0 : *ri++ = *buf++;
721 : : else
722 : 0 : *ri++ = p;
723 [ # # ]: 0 : for( j = ml; j; --j )
724 : : {
725 : 0 : memcpy( rl++, buf, sizeof( slong ) );
726 : 0 : buf += UINT_PER_LONG;
727 : : }
728 [ # # ]: 0 : for( j = mul; j; --j )
729 : : {
730 : 0 : memcpy( rul++, buf, sizeof( Ulong ) );
731 : 0 : buf += UINT_PER_ULONG;
732 : : }
733 [ # # ]: 0 : for( j = mr; j; --j )
734 : : {
735 : 0 : memcpy( rr++, buf, sizeof( realType ) );
736 : 0 : buf += UINT_PER_REAL;
737 : : }
738 : 0 : llen -= tsize;
739 : : }
740 : : }
741 : :
742 [ # # ][ # # ]: 0 : if( !canWrite ) tl.disableWriteAccess();
743 : 0 : return moab::MB_SUCCESS;
744 : : }
745 : : #endif
746 : :
747 : : /*--------------------------------------------------------------------------
748 : : Combined Execution
749 : : --------------------------------------------------------------------------*/
750 : :
751 : 0 : void gs_data::gs_data_op( realType* u, int op )
752 : : {
753 : 0 : local_condense( u, op, this->local_cm );
754 : : #ifdef MOAB_HAVE_MPI
755 : 0 : this->nlinfo->nonlocal( u, op, _comm );
756 : : #endif
757 : 0 : local_uncondense( u, local_cm );
758 : 0 : }
759 : :
760 : 0 : void gs_data::gs_data_op_vec( realType* u, uint n, int op )
761 : : {
762 : : #ifdef MOAB_HAVE_MPI
763 [ # # ]: 0 : if( n > nlinfo->_maxv )
764 : : moab::fail( "%s: initialized with max vec size = %d,"
765 : : " but called with vec size = %d\n",
766 : 0 : __FILE__, nlinfo->_maxv, n );
767 : : #endif
768 : 0 : local_condense_vec( u, n, op, local_cm );
769 : : #ifdef MOAB_HAVE_MPI
770 : 0 : this->nlinfo->nonlocal_vec( u, n, op, _comm );
771 : : #endif
772 : 0 : local_uncondense_vec( u, n, local_cm );
773 : 0 : }
774 : :
775 : 0 : void gs_data::gs_data_op_many( realType** u, uint n, int op )
776 : : {
777 : : uint i;
778 : : #ifdef MOAB_HAVE_MPI
779 [ # # ]: 0 : if( n > nlinfo->_maxv )
780 : : moab::fail( "%s: initialized with max vec size = %d,"
781 : : " but called with vec size = %d\n",
782 : 0 : __FILE__, nlinfo->_maxv, n );
783 : : #endif
784 [ # # ]: 0 : for( i = 0; i < n; ++i )
785 : 0 : local_condense( u[i], op, local_cm );
786 : :
787 : : moab::fail( "%s: initialized with max vec size = %d,"
788 : : " but called with vec size = %d\n",
789 : 0 : __FILE__, 6, n );
790 : :
791 : : #ifdef MOAB_HAVE_MPI
792 : 0 : this->nlinfo->nonlocal_many( u, n, op, _comm );
793 : : #endif
794 [ # # ]: 0 : for( i = 0; i < n; ++i )
795 : 0 : local_uncondense( u[i], local_cm );
796 : 0 : }
797 : :
798 : : /*--------------------------------------------------------------------------
799 : : Setup
800 : : --------------------------------------------------------------------------*/
801 : :
802 : 0 : ErrorCode gs_data::initialize( uint n, const long* label, const Ulong* ulabel, uint maxv, const unsigned int nlabels,
803 : : const unsigned int nulabels, crystal_data* crystal )
804 : : {
805 : 0 : nlinfo = NULL;
806 : : unsigned int j;
807 [ # # ][ # # ]: 0 : TupleList nonzero, primary;
808 : : ErrorCode rval;
809 : : #ifdef MOAB_HAVE_MPI
810 [ # # ]: 0 : TupleList shared;
811 : : #else
812 : : moab::TupleList::buffer buf;
813 : : #endif
814 : : (void)VALGRIND_CHECK_MEM_IS_DEFINED( label, nlabels * sizeof( long ) );
815 : : (void)VALGRIND_CHECK_MEM_IS_DEFINED( ulabel, nlabels * sizeof( Ulong ) );
816 : : #ifdef MOAB_HAVE_MPI
817 [ # # ]: 0 : MPI_Comm_dup( crystal->_comm, &this->_comm );
818 : : #else
819 : : buf.buffer_init( 1024 );
820 : : #endif
821 : :
822 : : /* construct list of nonzeros: (index ^, label) */
823 [ # # ]: 0 : nonzero.initialize( 1, nlabels, nulabels, 0, n );
824 [ # # ]: 0 : nonzero.enableWriteAccess();
825 : : {
826 : : uint i;
827 : : sint* nzi;
828 : : long* nzl;
829 : : Ulong* nzul;
830 : 0 : nzi = nonzero.vi_wr;
831 : 0 : nzl = nonzero.vl_wr;
832 : 0 : nzul = nonzero.vul_wr;
833 [ # # ]: 0 : for( i = 0; i < n; ++i )
834 [ # # ]: 0 : if( label[nlabels * i] != 0 )
835 : : {
836 : 0 : nzi[0] = i;
837 [ # # ]: 0 : for( j = 0; j < nlabels; j++ )
838 : 0 : nzl[j] = label[nlabels * i + j];
839 [ # # ]: 0 : for( j = 0; j < nulabels; j++ )
840 : 0 : nzul[j] = ulabel[nulabels * i + j];
841 : 0 : nzi++;
842 : 0 : nzl += nlabels;
843 : 0 : nzul += nulabels;
844 [ # # ]: 0 : nonzero.inc_n();
845 : : }
846 : : }
847 : :
848 : : /* sort nonzeros by label: (index ^2, label ^1) */
849 : : #ifndef MOAB_HAVE_MPI
850 : : nonzero.sort( 1, &buf );
851 : : #else
852 [ # # ]: 0 : nonzero.sort( 1, &crystal->all->buf );
853 : : #endif
854 : :
855 : : /* build list of unique labels w/ lowest associated index:
856 : : (index in nonzero ^, primary (lowest) index in label, count, label(s),
857 : : ulabel(s)) */
858 [ # # ][ # # ]: 0 : primary.initialize( 3, nlabels, nulabels, 0, nonzero.get_n() );
859 [ # # ]: 0 : primary.enableWriteAccess();
860 : : {
861 : : uint i;
862 : 0 : sint *nzi = nonzero.vi_wr, *pi = primary.vi_wr;
863 : 0 : slong *nzl = nonzero.vl_wr, *pl = primary.vl_wr;
864 : 0 : Ulong *nzul = nonzero.vul_wr, *pul = primary.vul_wr;
865 : 0 : slong last = -1;
866 [ # # ][ # # ]: 0 : for( i = 0; i < nonzero.get_n(); ++i, nzi += 1, nzl += nlabels, nzul += nulabels )
867 : : {
868 [ # # ]: 0 : if( nzl[0] == last )
869 : : {
870 : 0 : ++pi[-1];
871 : 0 : continue;
872 : : }
873 : 0 : last = nzl[0];
874 : 0 : pi[0] = i;
875 : 0 : pi[1] = nzi[0];
876 [ # # ]: 0 : for( j = 0; j < nlabels; j++ )
877 : 0 : pl[j] = nzl[j];
878 [ # # ]: 0 : for( j = 0; j < nulabels; j++ )
879 : 0 : pul[j] = nzul[j];
880 : 0 : pi[2] = 1;
881 : 0 : pi += 3, pl += nlabels;
882 : 0 : pul += nulabels;
883 [ # # ]: 0 : primary.inc_n();
884 : : }
885 : : }
886 : :
887 : : /* calculate size of local condense map */
888 : : {
889 : 0 : uint i, count = 1;
890 : 0 : sint* pi = primary.vi_wr;
891 [ # # ][ # # ]: 0 : for( i = primary.get_n(); i; --i, pi += 3 )
892 [ # # ]: 0 : if( pi[2] > 1 ) count += pi[2] + 1;
893 : 0 : this->local_cm = (sint*)malloc( count * sizeof( sint ) );
894 : : }
895 : :
896 : : /* sort unique labels by primary index:
897 : : (nonzero index ^2, primary index ^1, count, label ^2) */
898 : : #ifndef MOAB_HAVE_MPI
899 : : primary.sort( 0, &buf );
900 : : buf.reset();
901 : : // buffer_free(&buf);
902 : : #else
903 [ # # ]: 0 : primary.sort( 0, &crystal->all->buf );
904 : : #endif
905 : :
906 : : /* construct local condense map */
907 : : {
908 : : uint i, ln;
909 : 0 : sint* pi = primary.vi_wr;
910 : 0 : sint* cm = this->local_cm;
911 [ # # ][ # # ]: 0 : for( i = primary.get_n(); i > 0; --i, pi += 3 )
912 [ # # ]: 0 : if( ( ln = pi[2] ) > 1 )
913 : : {
914 : 0 : sint* nzi = nonzero.vi_wr + 1 * pi[0];
915 [ # # ]: 0 : for( j = ln; j > 0; --j, nzi += 1 )
916 : 0 : *cm++ = nzi[0];
917 : 0 : *cm++ = -1;
918 : : }
919 : 0 : *cm++ = -1;
920 : : }
921 [ # # ]: 0 : nonzero.reset();
922 : : #ifndef MOAB_HAVE_MPI
923 : : primary.reset();
924 : : #else
925 : : /* assign work proc by label modulo np */
926 : : {
927 : : uint i;
928 : 0 : sint* pi = primary.vi_wr;
929 : 0 : slong* pl = primary.vl_wr;
930 [ # # ][ # # ]: 0 : for( i = primary.get_n(); i; --i, pi += 3, pl += nlabels )
931 : 0 : pi[0] = pl[0] % crystal->_num;
932 : : }
933 [ # # ]: 0 : rval = crystal->gs_transfer( 1, primary, 0 ); /* transfer to work procs */
934 [ # # ]: 0 : if( rval != MB_SUCCESS ) return rval;
935 : : /* primary: (source proc, index on src, useless, label) */
936 : : /* sort by label */
937 [ # # ]: 0 : primary.sort( 3, &crystal->all->buf );
938 : : /* add sentinel to primary list */
939 [ # # ][ # # ]: 0 : if( primary.get_n() == primary.get_max() )
[ # # ]
940 [ # # ][ # # ]: 0 : primary.resize( ( primary.get_max() ? primary.get_max() + ( primary.get_max() + 1 ) / 2 + 1 : 2 ) );
[ # # ][ # # ]
[ # # ]
941 [ # # ]: 0 : primary.vl_wr[nlabels * primary.get_n()] = -1;
942 : : /* construct shared list: (proc1, proc2, index1, label) */
943 : : #ifdef MOAB_HAVE_MPI
944 [ # # ][ # # ]: 0 : shared.initialize( 3, nlabels, nulabels, 0, primary.get_n() );
945 [ # # ]: 0 : shared.enableWriteAccess();
946 : : #endif
947 : : {
948 : 0 : sint *pi1 = primary.vi_wr, *si = shared.vi_wr;
949 : 0 : slong lbl, *pl1 = primary.vl_wr, *sl = shared.vl_wr;
950 : 0 : Ulong *pul1 = primary.vul_wr, *sul = shared.vul_wr;
951 [ # # ]: 0 : for( ; ( lbl = pl1[0] ) != -1; pi1 += 3, pl1 += nlabels, pul1 += nulabels )
952 : : {
953 : 0 : sint* pi2 = pi1 + 3;
954 : 0 : slong* pl2 = pl1 + nlabels;
955 : 0 : Ulong* pul2 = pul1 + nulabels;
956 [ # # ]: 0 : for( ; pl2[0] == lbl; pi2 += 3, pl2 += nlabels, pul2 += nulabels )
957 : : {
958 [ # # ][ # # ]: 0 : if( shared.get_n() + 2 > shared.get_max() )
[ # # ]
959 [ # # ][ # # ]: 0 : shared.resize( ( shared.get_max() ? shared.get_max() + ( shared.get_max() + 1 ) / 2 + 1 : 2 ) ),
[ # # ][ # # ]
960 [ # # ][ # # ]: 0 : si = shared.vi_wr + shared.get_n() * 3;
961 [ # # ]: 0 : sl = shared.vl_wr + shared.get_n() * nlabels;
962 [ # # ]: 0 : sul = shared.vul_wr + shared.get_n() * nulabels;
963 : 0 : si[0] = pi1[0];
964 : 0 : si[1] = pi2[0];
965 : 0 : si[2] = pi1[1];
966 [ # # ]: 0 : for( j = 0; j < nlabels; j++ )
967 : 0 : sl[j] = pl2[j];
968 [ # # ]: 0 : for( j = 0; j < nulabels; j++ )
969 : 0 : sul[j] = pul2[j];
970 : 0 : si += 3;
971 : 0 : sl += nlabels;
972 : 0 : sul += nulabels;
973 [ # # ]: 0 : shared.inc_n();
974 : 0 : si[0] = pi2[0];
975 : 0 : si[1] = pi1[0];
976 : 0 : si[2] = pi2[1];
977 [ # # ]: 0 : for( j = 0; j < nlabels; j++ )
978 : 0 : sl[j] = pl1[j];
979 [ # # ]: 0 : for( j = 0; j < nulabels; j++ )
980 : 0 : sul[j] = pul1[j];
981 : 0 : si += 3;
982 : 0 : sl += nlabels;
983 : 0 : sul += nulabels;
984 [ # # ]: 0 : shared.inc_n();
985 : : }
986 : : }
987 : : }
988 [ # # ]: 0 : primary.reset();
989 [ # # ]: 0 : rval = crystal->gs_transfer( 1, shared, 0 ); /* segfaulting transfer to dest procs */
990 [ # # ]: 0 : if( rval != MB_SUCCESS ) return rval;
991 : : /* shared list: (useless, proc2, index, label) */
992 : : /* sort by label */
993 [ # # ]: 0 : shared.sort( 3, &crystal->all->buf );
994 : : /* sort by partner proc */
995 [ # # ]: 0 : shared.sort( 1, &crystal->all->buf );
996 : : /* count partner procs */
997 : : {
998 : 0 : uint i, count = 0;
999 : 0 : sint proc = -1, *si = shared.vi_wr;
1000 [ # # ][ # # ]: 0 : for( i = shared.get_n(); i; --i, si += 3 )
1001 [ # # ]: 0 : if( si[1] != proc )
1002 : : {
1003 : 0 : ++count;
1004 : 0 : proc = si[1];
1005 : : }
1006 : : // this->nlinfo = new nonlocal_info();
1007 : : // this->nlinfo->initialize(count,shared.get_n(),
1008 : : // nlabels, nulabels, maxv);
1009 [ # # ][ # # ]: 0 : this->nlinfo = new nonlocal_info( count, shared.get_n(), nlabels, nulabels, maxv );
[ # # ]
1010 : : }
1011 : : /* construct non-local info */
1012 : : {
1013 : : uint i;
1014 : 0 : sint proc = -1, *si = shared.vi_wr;
1015 : 0 : slong* sl = shared.vl_wr;
1016 : 0 : Ulong* ul = shared.vul_wr;
1017 : 0 : uint* target = this->nlinfo->_target;
1018 : 0 : uint* nshared = this->nlinfo->_nshared;
1019 : 0 : uint* sh_ind = this->nlinfo->_sh_ind;
1020 : 0 : slong* slabels = this->nlinfo->_slabels;
1021 : 0 : Ulong* ulabels = this->nlinfo->_ulabels;
1022 [ # # ][ # # ]: 0 : for( i = shared.get_n(); i; --i, si += 3 )
1023 : : {
1024 [ # # ]: 0 : if( si[1] != proc )
1025 : : {
1026 : 0 : proc = si[1];
1027 : 0 : *target++ = proc;
1028 : 0 : *nshared++ = 0;
1029 : : }
1030 : 0 : ++nshared[-1];
1031 : 0 : *sh_ind++ = si[2];
1032 : : // don't store 1st slabel
1033 : 0 : sl++;
1034 [ # # ]: 0 : for( j = 0; j < nlabels - 1; j++ )
1035 : 0 : slabels[j] = sl[j];
1036 [ # # ]: 0 : for( j = 0; j < nulabels; j++ )
1037 : 0 : ulabels[j] = ul[j];
1038 : 0 : slabels += nlabels - 1;
1039 : 0 : ulabels += nulabels;
1040 : 0 : sl += nlabels - 1;
1041 : 0 : ul += nulabels;
1042 : : }
1043 : : }
1044 [ # # ]: 0 : shared.reset();
1045 : : #endif
1046 : 0 : return MB_SUCCESS;
1047 : : }
1048 : :
1049 : 0 : void gs_data::reset()
1050 : : {
1051 : 0 : free( local_cm );
1052 : 0 : local_cm = NULL;
1053 : : #ifdef MOAB_HAVE_MPI
1054 [ # # ]: 0 : if( nlinfo != NULL )
1055 : : {
1056 : 0 : nlinfo->nlinfo_free();
1057 [ # # ]: 0 : delete this->nlinfo;
1058 : 0 : MPI_Comm_free( &_comm );
1059 : 0 : nlinfo = NULL;
1060 : : }
1061 : : #endif
1062 : 0 : }
1063 : :
1064 : : } // namespace moab
|