Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 
17 #include <Zoltan2_MeshAdapter.hpp>
18 #include <Zoltan2_StridedData.hpp>
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 
26 namespace Zoltan2 {
27 
54 template <typename User>
55  class PamgenMeshAdapter: public MeshAdapter<User> {
56 
57 public:
58 
60  typedef typename InputTraits<User>::lno_t lno_t;
61  typedef typename InputTraits<User>::gno_t gno_t;
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 
93  bool areEntityIDsUnique(MeshEntityType etype) const {
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 
291 private:
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 
315 template <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 
860 template <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 
870 template <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
bool avail2ndAdjs(MeshEntityType sourcetarget, MeshEntityType through) const
Returns whether a second adjacency combination is available. If combination is not available in the M...
InputTraits< User >::part_t part_t
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
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 >::offset_t offset_t
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 ...
int getDimension() const
Return dimension of the entity coordinates, if any.
static ArrayRCP< ArrayRCP< zscalar_t > > weights
Defines the MeshAdapter interface.
MeshAdapter defines the interface for mesh input.
default_part_t part_t
The data type to represent part numbers.
default_offset_t offset_t
The data type to represent offsets.
map_t::global_ordinal_type gno_t
Definition: mapRemotes.cpp:27
void getWeightsViewOf(MeshEntityType etype, const scalar_t *&weights, int &stride, int idx=0) const
void getIDsViewOf(MeshEntityType etype, const gno_t *&Ids) const
#define Z2_THROW_NOT_IMPLEMENTED
void getAdjsView(MeshEntityType source, MeshEntityType target, const offset_t *&offsets, const gno_t *&adjacencyIds) const
InputTraits< User >::gno_t gno_t
bool areEntityIDsUnique(MeshEntityType etype) const
Provide a pointer to the entity topology types.
size_t getLocalNumAdjs(MeshEntityType source, MeshEntityType target) const
Returns the number of first adjacencies on this process.
InputTraits< User >::scalar_t scalar_t
default_lno_t lno_t
The ordinal type (e.g., int, long, int64_t) that represents local counts and local indices...
size_t getLocalNum2ndAdjs(MeshEntityType sourcetarget, MeshEntityType through) const
if avail2ndAdjs(), returns the number of second adjacencies on this process.
EntityTopologyType
Enumerate entity topology types for meshes: points,lines,polygons,triangles,quadrilaterals, polyhedrons, tetrahedrons, hexhedrons, prisms, or pyramids.
default_gno_t gno_t
The ordinal type (e.g., int, long, int64_t) that can represent global counts and identifiers.
InputTraits< User >::node_t node_t
default_node_t node_t
The Kokkos node type. This is only meaningful for users of Tpetra objects.
void getTopologyViewOf(MeshEntityType etype, enum EntityTopologyType const *&Types) const
Provide a pointer to the entity topology types.
void getCoordinatesViewOf(MeshEntityType etype, const scalar_t *&coords, int &stride, int dim) const
InputTraits< User >::lno_t lno_t
MeshEntityType
Enumerate entity types for meshes: Regions, Faces, Edges, or Vertices.
void get2ndAdjsView(MeshEntityType sourcetarget, MeshEntityType through, const offset_t *&offsets, const gno_t *&adjacencyIds) const
PamgenMeshAdapter(const Comm< int > &comm, std::string typestr="region", int nEntWgts=0)
Constructor for mesh with identifiers but no coordinates or edges.
void setWeightIsDegree(int idx)
Specify an index for which the weight should be the degree of the entity idx Zoltan2 will use the en...
This class represents a mesh.
typename InputTraits< User >::lno_t lno_t
size_t getLocalNumOf(MeshEntityType etype) const
Returns the global number of mesh entities of MeshEntityType.
default_scalar_t scalar_t
The data type for weights and coordinates.
bool availAdjs(MeshEntityType source, MeshEntityType target) const
Returns whether a first adjacency combination is available.
This file defines the StridedData class.