Zoltan2
Loading...
Searching...
No Matches
Zoltan2_PamgenMeshAdapter.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Zoltan2: A package of combinatorial algorithms for scientific computing
4//
5// Copyright 2012 NTESS and the Zoltan2 contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
13
14#ifndef _ZOLTAN2_PAMGENMESHADAPTER_HPP_
15#define _ZOLTAN2_PAMGENMESHADAPTER_HPP_
16
19#include <Teuchos_as.hpp>
20#include <vector>
21#include <string>
22
23#include <pamgen_im_exodusII.h>
24#include <pamgen_im_ne_nemesisI.h>
25
26namespace Zoltan2 {
27
53
54template <typename User>
55 class PamgenMeshAdapter: public MeshAdapter<User> {
56
57public:
58
65 typedef User user_t;
66 typedef std::map<gno_t, gno_t> MapType;
67
74
75 PamgenMeshAdapter(const Comm<int> &comm, std::string typestr="region",
76 int nEntWgts=0);
77
83
84 void setWeightIsDegree(int idx);
85
86 void print(int);
87
89
91 // The MeshAdapter interface.
92 // This is the interface that would be called by a model or a problem .
94
96 return etype==MESH_REGION;
97 }
98
99 size_t getLocalNumOf(MeshEntityType etype) const
100 {
101 if ((MESH_REGION == etype && 3 == dimension_) ||
102 (MESH_FACE == etype && 2 == dimension_)) {
103 return num_elem_;
104 }
105
106 if (MESH_VERTEX == etype) {
107 return num_nodes_;
108 }
109
110 return 0;
111 }
112
113 void getIDsViewOf(MeshEntityType etype, const gno_t *&Ids) const
114 {
115 if ((MESH_REGION == etype && 3 == dimension_) ||
116 (MESH_FACE == etype && 2 == dimension_)) {
117 Ids = element_num_map_;
118 }
119
120 else if (MESH_VERTEX == etype) {
121 Ids = node_num_map_;
122 }
123
124 else Ids = NULL;
125 }
126
128 enum EntityTopologyType const *&Types) const {
129 if ((MESH_REGION == etype && 3 == dimension_) ||
130 (MESH_FACE == etype && 2 == dimension_)) {
131 Types = elemTopology;
132 }
133
134 else if (MESH_VERTEX == etype) {
135 Types = nodeTopology;
136 }
137
138 else Types = NULL;
139 }
140
142 int &stride, int idx = 0) const
143 {
144 weights = NULL;
145 stride = 0;
146 }
147
148 int getDimension() const { return dimension_; }
149
150 void getCoordinatesViewOf(MeshEntityType etype, const scalar_t *&coords,
151 int &stride, int dim) const {
152 if ((MESH_REGION == etype && 3 == dimension_) ||
153 (MESH_FACE == etype && 2 == dimension_)) {
154 if (dim == 0) {
155 coords = Acoords_;
156 } else if (dim == 1) {
157 coords = Acoords_ + num_elem_;
158 } else if (dim == 2) {
159 coords = Acoords_ + 2 * num_elem_;
160 }
161 stride = 1;
162 } else if (MESH_REGION == etype && 2 == dimension_) {
163 coords = NULL;
164 stride = 0;
165 } else if (MESH_VERTEX == etype) {
166 if (dim == 0) {
167 coords = coords_;
168 } else if (dim == 1) {
169 coords = coords_ + num_nodes_;
170 } else if (dim == 2) {
171 coords = coords_ + 2 * num_nodes_;
172 }
173 stride = 1;
174 } else {
175 coords = NULL;
176 stride = 0;
178 }
179 }
180
181 bool availAdjs(MeshEntityType source, MeshEntityType target) const {
182 if ((MESH_REGION == source && MESH_VERTEX == target && 3 == dimension_) ||
183 (MESH_FACE == source && MESH_VERTEX == target && 2 == dimension_) ||
184 (MESH_VERTEX == source && MESH_REGION == target && 3 == dimension_) ||
185 (MESH_VERTEX == source && MESH_FACE == target && 2 == dimension_)) {
186 return TRUE;
187 }
188
189 return false;
190 }
191
192 size_t getLocalNumAdjs(MeshEntityType source, MeshEntityType target) const
193 {
194 if ((MESH_REGION == source && MESH_VERTEX == target && 3 == dimension_) ||
195 (MESH_FACE == source && MESH_VERTEX == target && 2 == dimension_)) {
196 return tnoct_;
197 }
198
199 if ((MESH_VERTEX == source && MESH_REGION == target && 3 == dimension_) ||
200 (MESH_VERTEX == source && MESH_FACE == target && 2 == dimension_)) {
201 return telct_;
202 }
203
204 return 0;
205 }
206
208 const offset_t *&offsets, const gno_t *& adjacencyIds) const
209 {
210 if ((MESH_REGION == source && MESH_VERTEX == target && 3 == dimension_) ||
211 (MESH_FACE == source && MESH_VERTEX == target && 2 == dimension_)) {
212 offsets = elemOffsets_;
213 adjacencyIds = elemToNode_;
214 } else if ((MESH_REGION==target && MESH_VERTEX==source && 3==dimension_) ||
215 (MESH_FACE==target && MESH_VERTEX==source && 2==dimension_)) {
216 offsets = nodeOffsets_;
217 adjacencyIds = nodeToElem_;
218 } else if (MESH_REGION == source && 2 == dimension_) {
219 offsets = NULL;
220 adjacencyIds = NULL;
221 } else {
222 offsets = NULL;
223 adjacencyIds = NULL;
225 }
226 }
227
228 //#define USE_MESH_ADAPTER
229#ifndef USE_MESH_ADAPTER
230 bool avail2ndAdjs(MeshEntityType sourcetarget, MeshEntityType through) const
231 {
232 if (through == MESH_VERTEX) {
233 if (sourcetarget == MESH_REGION && dimension_ == 3) return true;
234 if (sourcetarget == MESH_FACE && dimension_ == 2) return true;
235 }
236 if (sourcetarget == MESH_VERTEX) {
237 if (through == MESH_REGION && dimension_ == 3) return true;
238 if (through == MESH_FACE && dimension_ == 2) return true;
239 }
240 return false;
241 }
242
243 size_t getLocalNum2ndAdjs(MeshEntityType sourcetarget,
244 MeshEntityType through) const
245 {
246 if (through == MESH_VERTEX &&
247 ((sourcetarget == MESH_REGION && dimension_ == 3) ||
248 (sourcetarget == MESH_FACE && dimension_ == 2))) {
249 return nEadj_;
250 }
251
252 if (sourcetarget == MESH_VERTEX &&
253 ((through == MESH_REGION && dimension_ == 3) ||
254 (through == MESH_FACE && dimension_ == 2))) {
255 return nNadj_;
256 }
257
258 return 0;
259 }
260
261 void get2ndAdjsView(MeshEntityType sourcetarget, MeshEntityType through,
262 const offset_t *&offsets, const gno_t *&adjacencyIds) const
263 {
264 if (through == MESH_VERTEX &&
265 ((sourcetarget == MESH_REGION && dimension_ == 3) ||
266 (sourcetarget == MESH_FACE && dimension_ == 2))) {
267 offsets = eStart_;
268 adjacencyIds = eAdj_;
269 } else if (sourcetarget == MESH_VERTEX &&
270 ((through == MESH_REGION && dimension_ == 3) ||
271 (through == MESH_FACE && dimension_ == 2))) {
272 offsets = nStart_;
273 adjacencyIds = nAdj_;
274 } else {
275 offsets = NULL;
276 adjacencyIds = NULL;
278 }
279 }
280#endif
281
282 bool useDegreeAsWeightOf(MeshEntityType etype, int idx) const
283 {
284 if ((MESH_REGION == etype && 3 == dimension_) ||
285 (MESH_FACE == etype && 2 == dimension_) ||
286 (MESH_VERTEX == etype)) {
287 return entityDegreeWeight_[idx];
288 }
289
290 return false;
291 }
292
293private:
294 int dimension_, num_nodes_global_, num_elems_global_, num_nodes_, num_elem_;
295 gno_t *element_num_map_, *node_num_map_;
296 gno_t *elemToNode_;
297 offset_t tnoct_, *elemOffsets_;
298 gno_t *nodeToElem_;
299 offset_t telct_, *nodeOffsets_;
300
301 int nWeightsPerEntity_;
302 bool *entityDegreeWeight_;
303
304 scalar_t *coords_, *Acoords_;
305 offset_t *eStart_, *nStart_;
306 gno_t *eAdj_, *nAdj_;
307 size_t nEadj_, nNadj_;
308 EntityTopologyType* nodeTopology;
309 EntityTopologyType* elemTopology;
310
311};
312
314// Definitions
316
317template <typename User>
319 std::string typestr, int nEntWgts):
320 dimension_(0), num_nodes_global_(0), num_elems_global_(0), num_nodes_(0), num_elem_(0),
321 element_num_map_(nullptr), node_num_map_(nullptr), elemToNode_(nullptr), elemOffsets_(nullptr),
322 nodeToElem_(nullptr), nodeOffsets_(nullptr), nWeightsPerEntity_(nEntWgts), entityDegreeWeight_(nullptr),
323 coords_(nullptr), Acoords_(nullptr), eStart_(nullptr), nStart_(nullptr), eAdj_(nullptr), nAdj_(nullptr),
324 nodeTopology(nullptr), elemTopology(nullptr)
325{
326 using Teuchos::as;
327
328 int error = 0;
329 char title[100];
330 int exoid = 0;
331 int num_elem_blk, num_node_sets, num_side_sets;
332 error += im_ex_get_init(exoid, title, &dimension_,
333 &num_nodes_, &num_elem_, &num_elem_blk,
334 &num_node_sets, &num_side_sets);
335
336 if (typestr.compare("region") == 0) {
337 if (dimension_ == 3)
338 this->setEntityTypes(typestr, "vertex", "vertex");
339 else
340 // automatically downgrade primary entity if problem is only 2D
341 this->setEntityTypes("face", "vertex", "vertex");
342 }
343 else if (typestr.compare("vertex") == 0) {
344 if (dimension_ == 3)
345 this->setEntityTypes(typestr, "region", "region");
346 else
347 this->setEntityTypes(typestr, "face", "face");
348 }
349 else {
351 }
352
353 double *dcoords = new double [num_nodes_ * dimension_];
354 coords_ = new scalar_t [num_nodes_ * dimension_];
355
356 error += im_ex_get_coord(exoid, dcoords, dcoords + num_nodes_,
357 dcoords + 2 * num_nodes_);
358
359 size_t dlen = num_nodes_ * dimension_;
360 for (size_t i = 0; i < dlen; i++) coords_[i] = as<scalar_t>(dcoords[i]);
361 delete [] dcoords;
362
363 element_num_map_ = new gno_t[num_elem_];
364 std::vector<int> tmp;
365 tmp.resize(num_elem_);
366
367 // BDD cast to int did not always work!
368 // error += im_ex_get_elem_num_map(exoid, (int *)element_num_map_)
369 // This may be a case of calling the wrong method
370 error += im_ex_get_elem_num_map(exoid, &tmp[0]);
371 for(size_t i = 0; i < tmp.size(); i++)
372 element_num_map_[i] = static_cast<gno_t>(tmp[i]);
373
374 tmp.clear();
375 tmp.resize(num_nodes_);
376 node_num_map_ = new gno_t [num_nodes_];
377
378 // BDD cast to int did not always work!
379 // error += im_ex_get_node_num_map(exoid, (int *)node_num_map_);
380 // This may be a case of calling the wrong method
381 error += im_ex_get_node_num_map(exoid, &tmp[0]);
382 for(size_t i = 0; i < tmp.size(); i++)
383 node_num_map_[i] = static_cast<gno_t>(tmp[i]);
384
385 nodeTopology = new enum EntityTopologyType[num_nodes_];
386 for (int i=0;i<num_nodes_;i++)
387 nodeTopology[i] = POINT;
388 elemTopology = new enum EntityTopologyType[num_elem_];
389 for (int i=0;i<num_elem_;i++) {
390 if (dimension_==2)
391 elemTopology[i] = QUADRILATERAL;
392 else
393 elemTopology[i] = HEXAHEDRON;
394 }
395
396 int *elem_blk_ids = new int [num_elem_blk];
397 error += im_ex_get_elem_blk_ids(exoid, elem_blk_ids);
398
399 int *num_nodes_per_elem = new int [num_elem_blk];
400 int *num_attr = new int [num_elem_blk];
401 int *num_elem_this_blk = new int [num_elem_blk];
402 char **elem_type = new char * [num_elem_blk];
403 int **connect = new int * [num_elem_blk];
404
405 for(int i = 0; i < num_elem_blk; i++){
406 elem_type[i] = new char [MAX_STR_LENGTH + 1];
407 error += im_ex_get_elem_block(exoid, elem_blk_ids[i], elem_type[i],
408 (int*)&(num_elem_this_blk[i]),
409 (int*)&(num_nodes_per_elem[i]),
410 (int*)&(num_attr[i]));
411 delete[] elem_type[i];
412 }
413
414 delete[] elem_type;
415 elem_type = NULL;
416 delete[] num_attr;
417 num_attr = NULL;
418 Acoords_ = new scalar_t [num_elem_ * dimension_];
419 int a = 0;
420 std::vector<std::vector<gno_t> > sur_elem;
421 sur_elem.resize(num_nodes_);
422
423 for(int b = 0; b < num_elem_blk; b++) {
424 connect[b] = new int [num_nodes_per_elem[b]*num_elem_this_blk[b]];
425 error += im_ex_get_elem_conn(exoid, elem_blk_ids[b], connect[b]);
426
427 for(int i = 0; i < num_elem_this_blk[b]; i++) {
428 Acoords_[a] = 0;
429 Acoords_[num_elem_ + a] = 0;
430
431 if (3 == dimension_) {
432 Acoords_[2 * num_elem_ + a] = 0;
433 }
434
435 for(int j = 0; j < num_nodes_per_elem[b]; j++) {
436 int node = connect[b][i * num_nodes_per_elem[b] + j] - 1;
437 Acoords_[a] += coords_[node];
438 Acoords_[num_elem_ + a] += coords_[num_nodes_ + node];
439
440 if(3 == dimension_) {
441 Acoords_[2 * num_elem_ + a] += coords_[2 * num_nodes_ + node];
442 }
443
444 /*
445 * in the case of degenerate elements, where a node can be
446 * entered into the connect table twice, need to check to
447 * make sure that this element is not already listed as
448 * surrounding this node
449 */
450 if (sur_elem[node].empty() ||
451 element_num_map_[a] != sur_elem[node][sur_elem[node].size()-1]) {
452 /* Add the element to the list */
453 sur_elem[node].push_back(element_num_map_[a]);
454 }
455 }
456
457 Acoords_[a] /= num_nodes_per_elem[b];
458 Acoords_[num_elem_ + a] /= num_nodes_per_elem[b];
459
460 if(3 == dimension_) {
461 Acoords_[2 * num_elem_ + a] /= num_nodes_per_elem[b];
462 }
463
464 a++;
465 }
466
467 }
468
469 delete[] elem_blk_ids;
470 elem_blk_ids = NULL;
471 int nnodes_per_elem = num_nodes_per_elem[0];
472 elemToNode_ = new gno_t[num_elem_ * nnodes_per_elem];
473 int telct = 0;
474 elemOffsets_ = new offset_t [num_elem_+1];
475 tnoct_ = 0;
476 int **reconnect = new int * [num_elem_];
477 size_t max_nsur = 0;
478
479 for (int b = 0; b < num_elem_blk; b++) {
480 for (int i = 0; i < num_elem_this_blk[b]; i++) {
481 elemOffsets_[telct] = tnoct_;
482 reconnect[telct] = new int [num_nodes_per_elem[b]];
483
484 for (int j = 0; j < num_nodes_per_elem[b]; j++) {
485 elemToNode_[tnoct_]=
486 as<gno_t>(node_num_map_[connect[b][i*num_nodes_per_elem[b] + j]-1]);
487 reconnect[telct][j] = connect[b][i*num_nodes_per_elem[b] + j];
488 ++tnoct_;
489 }
490
491 ++telct;
492 }
493 }
494 elemOffsets_[telct] = tnoct_;
495
496 delete[] num_nodes_per_elem;
497 num_nodes_per_elem = NULL;
498 delete[] num_elem_this_blk;
499 num_elem_this_blk = NULL;
500
501 for(int b = 0; b < num_elem_blk; b++) {
502 delete[] connect[b];
503 }
504
505 delete[] connect;
506 connect = NULL;
507
508 int max_side_nodes = nnodes_per_elem;
509 int *side_nodes = new int [max_side_nodes];
510 int *mirror_nodes = new int [max_side_nodes];
511
512 /* Allocate memory necessary for the adjacency */
513 eStart_ = new lno_t [num_elem_+1];
514 nStart_ = new lno_t [num_nodes_+1];
515 std::vector<int> eAdj;
516 std::vector<int> nAdj;
517
518 for (int i=0; i < max_side_nodes; i++) {
519 side_nodes[i]=-999;
520 mirror_nodes[i]=-999;
521 }
522
523 /* Find the adjacency for a nodal based decomposition */
524 nEadj_ = 0;
525 nNadj_ = 0;
526 for(int ncnt=0; ncnt < num_nodes_; ncnt++) {
527 if(sur_elem[ncnt].empty()) {
528 std::cout << "WARNING: Node = " << ncnt+1 << " has no elements"
529 << std::endl;
530 } else {
531 size_t nsur = sur_elem[ncnt].size();
532 if (nsur > max_nsur)
533 max_nsur = nsur;
534 }
535 }
536
537 nodeToElem_ = new gno_t[num_nodes_ * max_nsur];
538 nodeOffsets_ = new offset_t[num_nodes_+1];
539 telct_ = 0;
540
541 for (int ncnt = 0; ncnt < num_nodes_; ncnt++) {
542 nodeOffsets_[ncnt] = telct_;
543 nStart_[ncnt] = nNadj_;
544 MapType nAdjMap;
545
546 for (size_t i = 0; i < sur_elem[ncnt].size(); i++) {
547 nodeToElem_[telct_] = sur_elem[ncnt][i];
548 ++telct_;
549
550#ifndef USE_MESH_ADAPTER
551 for(int ecnt = 0; ecnt < num_elem_; ecnt++) {
552 if (element_num_map_[ecnt] == sur_elem[ncnt][i]) {
553 for (int j = 0; j < nnodes_per_elem; j++) {
554 typename MapType::iterator iter =
555 nAdjMap.find(elemToNode_[elemOffsets_[ecnt]+j]);
556
557 if (node_num_map_[ncnt] != elemToNode_[elemOffsets_[ecnt]+j] &&
558 iter == nAdjMap.end() ) {
559 nAdj.push_back(elemToNode_[elemOffsets_[ecnt]+j]);
560 nNadj_++;
561 nAdjMap.insert({elemToNode_[elemOffsets_[ecnt]+j],
562 elemToNode_[elemOffsets_[ecnt]+j]});
563 }
564 }
565
566 break;
567 }
568 }
569#endif
570 }
571
572 nAdjMap.clear();
573 }
574
575 nodeOffsets_[num_nodes_] = telct_;
576 nStart_[num_nodes_] = nNadj_;
577
578 nAdj_ = new gno_t [nNadj_];
579
580 for (size_t i=0; i < nNadj_; i++) {
581 nAdj_[i] = as<gno_t>(nAdj[i]);
582 }
583
584 int nprocs = comm.getSize();
585 //if (nprocs > 1) {
586 int neid=0,num_elem_blks_global,num_node_sets_global,num_side_sets_global;
587 error += im_ne_get_init_global(neid,&num_nodes_global_,&num_elems_global_,
588 &num_elem_blks_global,&num_node_sets_global,
589 &num_side_sets_global);
590
591 int num_internal_nodes, num_border_nodes, num_external_nodes;
592 int num_internal_elems, num_border_elems, num_node_cmaps, num_elem_cmaps;
593 int proc = 0;
594 error += im_ne_get_loadbal_param(neid, &num_internal_nodes,
595 &num_border_nodes, &num_external_nodes,
596 &num_internal_elems, &num_border_elems,
597 &num_node_cmaps, &num_elem_cmaps, proc);
598
599 int *node_cmap_ids = new int [num_node_cmaps];
600 int *node_cmap_node_cnts = new int [num_node_cmaps];
601 int *elem_cmap_ids = new int [num_elem_cmaps];
602 int *elem_cmap_elem_cnts = new int [num_elem_cmaps];
603 error += im_ne_get_cmap_params(neid, node_cmap_ids, node_cmap_node_cnts,
604 elem_cmap_ids, elem_cmap_elem_cnts, proc);
605 delete[] elem_cmap_ids;
606 elem_cmap_ids = NULL;
607 delete[] elem_cmap_elem_cnts;
608 elem_cmap_elem_cnts = NULL;
609
610 int **node_ids = new int * [num_node_cmaps];
611 int **node_proc_ids = new int * [num_node_cmaps];
612 for(int j = 0; j < num_node_cmaps; j++) {
613 node_ids[j] = new int [node_cmap_node_cnts[j]];
614 node_proc_ids[j] = new int [node_cmap_node_cnts[j]];
615 error += im_ne_get_node_cmap(neid, node_cmap_ids[j], node_ids[j],
616 node_proc_ids[j], proc);
617 }
618 delete[] node_cmap_ids;
619 node_cmap_ids = NULL;
620 int *sendCount = new int [nprocs];
621 int *recvCount = new int [nprocs];
622
623 // Post receives
624 RCP<CommRequest<int> >*requests=new RCP<CommRequest<int> >[num_node_cmaps];
625 for (int cnt = 0, i = 0; i < num_node_cmaps; i++) {
626 try {
627 requests[cnt++] =
628 Teuchos::ireceive<int,int>(comm,
629 rcp(&(recvCount[node_proc_ids[i][0]]),
630 false),
631 node_proc_ids[i][0]);
632 }
634 }
635
636 Teuchos::barrier<int>(comm);
637 size_t totalsend = 0;
638
639 for(int j = 0; j < num_node_cmaps; j++) {
640 sendCount[node_proc_ids[j][0]] = 1;
641 for(int i = 0; i < node_cmap_node_cnts[j]; i++) {
642 sendCount[node_proc_ids[j][i]] += sur_elem[node_ids[j][i]-1].size()+2;
643 }
644 totalsend += sendCount[node_proc_ids[j][0]];
645 }
646
647 // Send data; can use readySend since receives are posted.
648 for (int i = 0; i < num_node_cmaps; i++) {
649 try {
650 Teuchos::readySend<int,int>(comm, sendCount[node_proc_ids[i][0]],
651 node_proc_ids[i][0]);
652 }
654 }
655
656 // Wait for messages to return.
657 try {
658 Teuchos::waitAll<int>(comm, arrayView(requests, num_node_cmaps));
659 }
661
662 delete [] requests;
663
664 // Allocate the receive buffer.
665 size_t totalrecv = 0;
666 int maxMsg = 0;
667 int nrecvranks = 0;
668 for(int i = 0; i < num_node_cmaps; i++) {
669 if (recvCount[node_proc_ids[i][0]] > 0) {
670 totalrecv += recvCount[node_proc_ids[i][0]];
671 nrecvranks++;
672 if (recvCount[node_proc_ids[i][0]] > maxMsg)
673 maxMsg = recvCount[node_proc_ids[i][0]];
674 }
675 }
676
677 gno_t *rbuf = NULL;
678 if (totalrecv) rbuf = new gno_t[totalrecv];
679
680 requests = new RCP<CommRequest<int> > [nrecvranks];
681
682 // Error checking for memory and message size.
683 int OK[2] = {1,1};
684 // OK[0] -- true/false indicating whether each message size fits in an int
685 // (for MPI).
686 // OK[1] -- true/false indicating whether memory allocs are OK
687 int gOK[2]; // For global reduce of OK.
688
689 if (size_t(maxMsg) * sizeof(int) > INT_MAX) OK[0] = false;
690 if (totalrecv && !rbuf) OK[1] = 0;
691 if (!requests) OK[1] = 0;
692
693 // Post receives
694
695 size_t offset = 0;
696
697 if (OK[0] && OK[1]) {
698 int rcnt = 0;
699 for (int i = 0; i < num_node_cmaps; i++) {
700 if (recvCount[node_proc_ids[i][0]]) {
701 try {
702 requests[rcnt++] =
703 Teuchos::
704 ireceive<int,gno_t>(comm,
705 Teuchos::arcp(&rbuf[offset], 0,
706 recvCount[node_proc_ids[i][0]],
707 false),
708 node_proc_ids[i][0]);
709 }
711 }
712 offset += recvCount[node_proc_ids[i][0]];
713 }
714 }
715
716 delete[] recvCount;
717
718 // Use barrier for error checking
719 Teuchos::reduceAll<int>(comm, Teuchos::REDUCE_MIN, 2, OK, gOK);
720 if (!gOK[0] || !gOK[1]) {
721 delete [] rbuf;
722 delete [] requests;
723 if (!gOK[0])
724 throw std::runtime_error("Max single message length exceeded");
725 else
726 throw std::bad_alloc();
727 }
728
729 gno_t *sbuf = NULL;
730 if (totalsend) sbuf = new gno_t[totalsend];
731 a = 0;
732
733 for(int j = 0; j < num_node_cmaps; j++) {
734 sbuf[a++] = node_cmap_node_cnts[j];
735 for(int i = 0; i < node_cmap_node_cnts[j]; i++) {
736 sbuf[a++] = node_num_map_[node_ids[j][i]-1];
737 sbuf[a++] = sur_elem[node_ids[j][i]-1].size();
738 for(size_t ecnt=0; ecnt < sur_elem[node_ids[j][i]-1].size(); ecnt++) {
739 sbuf[a++] = sur_elem[node_ids[j][i]-1][ecnt];
740 }
741 }
742 }
743
744 delete[] node_cmap_node_cnts;
745 node_cmap_node_cnts = NULL;
746
747 for(int j = 0; j < num_node_cmaps; j++) {
748 delete[] node_ids[j];
749 }
750
751 delete[] node_ids;
752 node_ids = NULL;
753 ArrayRCP<gno_t> sendBuf;
754
755 if (totalsend)
756 sendBuf = ArrayRCP<gno_t>(sbuf, 0, totalsend, true);
757 else
758 sendBuf = Teuchos::null;
759
760 // Send data; can use readySend since receives are posted.
761 offset = 0;
762 for (int i = 0; i < num_node_cmaps; i++) {
763 if (sendCount[node_proc_ids[i][0]]) {
764 try{
765 Teuchos::readySend<int, gno_t>(comm,
766 Teuchos::arrayView(&sendBuf[offset],
767 sendCount[node_proc_ids[i][0]]),
768 node_proc_ids[i][0]);
769 }
771 }
772 offset += sendCount[node_proc_ids[i][0]];
773 }
774
775 for(int j = 0; j < num_node_cmaps; j++) {
776 delete[] node_proc_ids[j];
777 }
778
779 delete[] node_proc_ids;
780 node_proc_ids = NULL;
781 delete[] sendCount;
782
783 // Wait for messages to return.
784 try{
785 Teuchos::waitAll<int>(comm, Teuchos::arrayView(requests, nrecvranks));
786 }
788
789 delete[] requests;
790 a = 0;
791
792 for (int i = 0; i < num_node_cmaps; i++) {
793 int num_nodes_this_processor = rbuf[a++];
794
795 for (int j = 0; j < num_nodes_this_processor; j++) {
796 int this_node = rbuf[a++];
797 int num_elem_this_node = rbuf[a++];
798
799 for (int ncnt = 0; ncnt < num_nodes_; ncnt++) {
800 if (node_num_map_[ncnt] == this_node) {
801 for (int ecnt = 0; ecnt < num_elem_this_node; ecnt++) {
802 sur_elem[ncnt].push_back(rbuf[a++]);
803 }
804
805 break;
806 }
807 }
808 }
809 }
810
811 delete[] rbuf;
812 //}
813
814#ifndef USE_MESH_ADAPTER
815 for(int ecnt=0; ecnt < num_elem_; ecnt++) {
816 eStart_[ecnt] = nEadj_;
817 MapType eAdjMap;
818 int nnodes = nnodes_per_elem;
819 for(int ncnt=0; ncnt < nnodes; ncnt++) {
820 int node = reconnect[ecnt][ncnt]-1;
821 for(size_t i=0; i < sur_elem[node].size(); i++) {
822 int entry = sur_elem[node][i];
823 typename MapType::iterator iter = eAdjMap.find(entry);
824
825 if(element_num_map_[ecnt] != entry &&
826 iter == eAdjMap.end()) {
827 eAdj.push_back(entry);
828 nEadj_++;
829 eAdjMap.insert({entry, entry});
830 }
831 }
832 }
833
834 eAdjMap.clear();
835 }
836#endif
837
838 for(int b = 0; b < num_elem_; b++) {
839 delete[] reconnect[b];
840 }
841
842 delete[] reconnect;
843 reconnect = NULL;
844 eStart_[num_elem_] = nEadj_;
845
846 eAdj_ = new gno_t [nEadj_];
847
848 for (size_t i=0; i < nEadj_; i++) {
849 eAdj_[i] = as<gno_t>(eAdj[i]);
850 }
851
852 delete[] side_nodes;
853 side_nodes = NULL;
854 delete[] mirror_nodes;
855 mirror_nodes = NULL;
856
857 if (nWeightsPerEntity_ > 0) {
858 entityDegreeWeight_ = new bool [nWeightsPerEntity_];
859 for (int i=0; i < nWeightsPerEntity_; i++) {
860 entityDegreeWeight_[i] = false;
861 }
862 }
863}
864
865template <typename User>
867{
868 delete[] element_num_map_;
869 delete[] node_num_map_;
870 delete[] elemToNode_;
871 delete[] elemOffsets_;
872 delete[] nodeToElem_;
873 delete[] nodeOffsets_;
874 delete[] coords_;
875 delete[] Acoords_;
876 delete[] eStart_;
877 delete[] nStart_;
878 delete[] eAdj_;
879 delete[] nAdj_;
880 delete[] nodeTopology;
881 delete[] elemTopology;
882 delete[] entityDegreeWeight_;
883}
884
886template <typename User>
888{
889 if (idx >= 0 && idx < nWeightsPerEntity_)
890 entityDegreeWeight_[idx] = true;
891 else
892 std::cout << "WARNING: invalid entity weight index, " << idx << ", ignored"
893 << std::endl;
894}
895
896template <typename User>
898{
899 std::string fn(" PamgenMesh ");
900 std::cout << me << fn
901 << " dim = " << dimension_
902 << " nodes = " << num_nodes_
903 << " nelems = " << num_elem_
904 << std::endl;
905
906 for (int i = 0; i < num_elem_; i++) {
907 std::cout << me << fn << i
908 << " Elem " << element_num_map_[i]
909 << " Coords: ";
910 for (int j = 0; j < dimension_; j++)
911 std::cout << Acoords_[i + j * num_elem_] << " ";
912 std::cout << std::endl;
913 }
914
915#ifndef USE_MESH_ADAPTER
916 for (int i = 0; i < num_elem_; i++) {
917 std::cout << me << fn << i
918 << " Elem " << element_num_map_[i]
919 << " Graph: ";
920 for (int j = eStart_[i]; j < eStart_[i+1]; j++)
921 std::cout << eAdj_[j] << " ";
922 std::cout << std::endl;
923 }
924#endif
925}
926
927} //namespace Zoltan2
928
929#endif
#define Z2_THROW_NOT_IMPLEMENTED
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
Defines the MeshAdapter interface.
This file defines the StridedData class.
void setEntityTypes(std::string ptypestr, std::string atypestr, std::string satypestr)
Sets the primary, adjacency, and second adjacency entity types. Called by algorithm based on paramete...
InputTraits< User >::node_t node_t
PamgenMeshAdapter(const Comm< int > &comm, std::string typestr="region", int nEntWgts=0)
Constructor for mesh with identifiers but no coordinates or edges.
size_t getLocalNumAdjs(MeshEntityType source, MeshEntityType target) const
Returns the number of first adjacencies on this process.
void getWeightsViewOf(MeshEntityType etype, const scalar_t *&weights, int &stride, int idx=0) const
Provide a pointer to one of the number of this process' optional entity weights.
InputTraits< User >::scalar_t scalar_t
size_t getLocalNum2ndAdjs(MeshEntityType sourcetarget, MeshEntityType through) const
if avail2ndAdjs(), returns the number of second adjacencies on this process.
bool areEntityIDsUnique(MeshEntityType etype) const
Provide a pointer to the entity topology types.
size_t getLocalNumOf(MeshEntityType etype) const
Returns the global number of mesh entities of MeshEntityType.
void setWeightIsDegree(int idx)
Specify an index for which the weight should be the degree of the entity \paran idx Zoltan2 will use ...
bool useDegreeAsWeightOf(MeshEntityType etype, int idx) const
Optional method allowing the idx-th weight of entity type etype to be set as the number of neighbors ...
void getTopologyViewOf(MeshEntityType etype, enum EntityTopologyType const *&Types) const
Provide a pointer to the entity topology types.
InputTraits< User >::offset_t offset_t
void getCoordinatesViewOf(MeshEntityType etype, const scalar_t *&coords, int &stride, int dim) const
Provide a pointer to one dimension of entity coordinates.
bool availAdjs(MeshEntityType source, MeshEntityType target) const
Returns whether a first adjacency combination is available.
void getIDsViewOf(MeshEntityType etype, const gno_t *&Ids) const
Provide a pointer to this process' identifiers.
void get2ndAdjsView(MeshEntityType sourcetarget, MeshEntityType through, const offset_t *&offsets, const gno_t *&adjacencyIds) const
if avail2ndAdjs(), set pointers to this process' second adjacencies
InputTraits< User >::part_t part_t
bool avail2ndAdjs(MeshEntityType sourcetarget, MeshEntityType through) const
Returns whether a second adjacency combination is available. If combination is not available in the M...
void getAdjsView(MeshEntityType source, MeshEntityType target, const offset_t *&offsets, const gno_t *&adjacencyIds) const
Sets pointers to this process' mesh first adjacencies.
int getDimension() const
Return dimension of the entity coordinates, if any.
Created by mbenlioglu on Aug 31, 2020.
EntityTopologyType
Enumerate entity topology types for meshes: points,lines,polygons,triangles,quadrilaterals,...
MeshEntityType
Enumerate entity types for meshes: Regions, Faces, Edges, or Vertices.
static ArrayRCP< ArrayRCP< zscalar_t > > weights
default_offset_t offset_t
The data type to represent offsets.
default_gno_t gno_t
The ordinal type (e.g., int, long, int64_t) that can represent global counts and identifiers.
default_node_t node_t
The Kokkos node type. This is only meaningful for users of Tpetra objects.
default_lno_t lno_t
The ordinal type (e.g., int, long, int64_t) that represents local counts and local indices.
default_part_t part_t
The data type to represent part numbers.
default_scalar_t scalar_t
The data type for weights and coordinates.