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