Zoltan2
Zoltan2_PamgenMeshAdapter.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Zoltan2: A package of combinatorial algorithms for scientific computing
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Karen Devine (kddevin@sandia.gov)
39 // Erik Boman (egboman@sandia.gov)
40 // Siva Rajamanickam (srajama@sandia.gov)
41 //
42 // ***********************************************************************
43 //
44 // @HEADER
45 
50 #ifndef _ZOLTAN2_PAMGENMESHADAPTER_HPP_
51 #define _ZOLTAN2_PAMGENMESHADAPTER_HPP_
52 
53 #include <Zoltan2_MeshAdapter.hpp>
54 #include <Zoltan2_StridedData.hpp>
55 #include <vector>
56 #include <string>
57 
58 #include <pamgen_im_exodusII.h>
59 #include "pamgen_im_ne_nemesisI.h"
60 
61 namespace Zoltan2 {
62 
89 template <typename User>
90  class PamgenMeshAdapter: public MeshAdapter<User> {
91 
92 public:
93 
95  typedef typename InputTraits<User>::lno_t lno_t;
96  typedef typename InputTraits<User>::gno_t gno_t;
100  typedef User user_t;
101  typedef std::map<int, int> MapType;
102 
110  PamgenMeshAdapter(const Comm<int> &comm, std::string typestr="region");
111 
112  void print(int);
113 
115  // The MeshAdapter interface.
116  // This is the interface that would be called by a model or a problem .
118 
119  bool areEntityIDsUnique(MeshEntityType etype) const {
120  return etype==MESH_REGION;
121  }
122 
123  size_t getLocalNumOf(MeshEntityType etype) const
124  {
125  if ((MESH_REGION == etype && 3 == dimension_) ||
126  (MESH_FACE == etype && 2 == dimension_)) {
127  return num_elem_;
128  }
129 
130  if (MESH_VERTEX == etype) {
131  return num_nodes_;
132  }
133 
134  return 0;
135  }
136 
137  void getIDsViewOf(MeshEntityType etype, const gno_t *&Ids) const
138  {
139  if ((MESH_REGION == etype && 3 == dimension_) ||
140  (MESH_FACE == etype && 2 == dimension_)) {
141  Ids = element_num_map_;
142  }
143 
144  else if (MESH_VERTEX == etype) {
145  Ids = node_num_map_;
146  }
147 
148  else Ids = NULL;
149  }
150 
152  enum EntityTopologyType const *&Types) const {
153  if ((MESH_REGION == etype && 3 == dimension_) ||
154  (MESH_FACE == etype && 2 == dimension_)) {
155  Types = elemTopology;
156  }
157 
158  else if (MESH_VERTEX == etype) {
159  Types = nodeTopology;
160  }
161 
162  else Types = NULL;
163  }
164 
165  void getWeightsViewOf(MeshEntityType etype, const scalar_t *&weights,
166  int &stride, int idx = 0) const
167  {
168  weights = NULL;
169  stride = 0;
170  }
171 
172  int getDimension() const { return dimension_; }
173 
174  void getCoordinatesViewOf(MeshEntityType etype, const scalar_t *&coords,
175  int &stride, int dim) const {
176  if ((MESH_REGION == etype && 3 == dimension_) ||
177  (MESH_FACE == etype && 2 == dimension_)) {
178  if (dim == 0) {
179  coords = Acoords_;
180  } else if (dim == 1) {
181  coords = Acoords_ + num_elem_;
182  } else if (dim == 2) {
183  coords = Acoords_ + 2 * num_elem_;
184  }
185  stride = 1;
186  } else if (MESH_REGION == etype && 2 == dimension_) {
187  coords = NULL;
188  stride = 0;
189  } else if (MESH_VERTEX == etype) {
190  if (dim == 0) {
191  coords = coords_;
192  } else if (dim == 1) {
193  coords = coords_ + num_nodes_;
194  } else if (dim == 2) {
195  coords = coords_ + 2 * num_nodes_;
196  }
197  stride = 1;
198  } else {
199  coords = NULL;
200  stride = 0;
202  }
203  }
204 
205  bool availAdjs(MeshEntityType source, MeshEntityType target) const {
206  if ((MESH_REGION == source && MESH_VERTEX == target && 3 == dimension_) ||
207  (MESH_FACE == source && MESH_VERTEX == target && 2 == dimension_) ||
208  (MESH_VERTEX == source && MESH_REGION == target && 3 == dimension_) ||
209  (MESH_VERTEX == source && MESH_FACE == target && 2 == dimension_)) {
210  return TRUE;
211  }
212 
213  return false;
214  }
215 
216  size_t getLocalNumAdjs(MeshEntityType source, MeshEntityType target) const
217  {
218  if ((MESH_REGION == source && MESH_VERTEX == target && 3 == dimension_) ||
219  (MESH_FACE == source && MESH_VERTEX == target && 2 == dimension_)) {
220  return tnoct_;
221  }
222 
223  if ((MESH_VERTEX == source && MESH_REGION == target && 3 == dimension_) ||
224  (MESH_VERTEX == source && MESH_FACE == target && 2 == dimension_)) {
225  return telct_;
226  }
227 
228  return 0;
229  }
230 
232  const lno_t *&offsets, const gno_t *& adjacencyIds) const
233  {
234  if ((MESH_REGION == source && MESH_VERTEX == target && 3 == dimension_) ||
235  (MESH_FACE == source && MESH_VERTEX == target && 2 == dimension_)) {
236  offsets = elemOffsets_;
237  adjacencyIds = (gno_t *)elemToNode_;
238  } else if ((MESH_REGION==target && MESH_VERTEX==source && 3==dimension_) ||
239  (MESH_FACE==target && MESH_VERTEX==source && 2==dimension_)) {
240  offsets = nodeOffsets_;
241  adjacencyIds = (gno_t *)nodeToElem_;
242  } else if (MESH_REGION == source && 2 == dimension_) {
243  offsets = NULL;
244  adjacencyIds = NULL;
245  } else {
246  offsets = NULL;
247  adjacencyIds = NULL;
249  }
250  }
251 
252  //#define USE_MESH_ADAPTER
253 #ifndef USE_MESH_ADAPTER
254  bool avail2ndAdjs(MeshEntityType sourcetarget, MeshEntityType through) const
255  {
256  if (through == MESH_VERTEX) {
257  if (sourcetarget == MESH_REGION && dimension_ == 3) return true;
258  if (sourcetarget == MESH_FACE && dimension_ == 2) return true;
259  }
260  if (sourcetarget == MESH_VERTEX) {
261  if (through == MESH_REGION && dimension_ == 3) return true;
262  if (through == MESH_FACE && dimension_ == 2) return true;
263  }
264  return false;
265  }
266 
267  size_t getLocalNum2ndAdjs(MeshEntityType sourcetarget,
268  MeshEntityType through) const
269  {
270  if (through == MESH_VERTEX &&
271  ((sourcetarget == MESH_REGION && dimension_ == 3) ||
272  (sourcetarget == MESH_FACE && dimension_ == 2))) {
273  return nEadj_;
274  }
275 
276  if (sourcetarget == MESH_VERTEX &&
277  ((through == MESH_REGION && dimension_ == 3) ||
278  (through == MESH_FACE && dimension_ == 2))) {
279  return nNadj_;
280  }
281 
282  return 0;
283 
284  }
285 
286  void get2ndAdjsView(MeshEntityType sourcetarget, MeshEntityType through,
287  const lno_t *&offsets, const gno_t *&adjacencyIds) const
288  {
289  if (through == MESH_VERTEX &&
290  ((sourcetarget == MESH_REGION && dimension_ == 3) ||
291  (sourcetarget == MESH_FACE && dimension_ == 2))) {
292  offsets = eStart_;
293  adjacencyIds = eAdj_;
294  } else if (sourcetarget == MESH_VERTEX &&
295  ((through == MESH_REGION && dimension_ == 3) ||
296  (through == MESH_FACE && dimension_ == 2))) {
297  offsets = nStart_;
298  adjacencyIds = nAdj_;
299  } else {
300  offsets = NULL;
301  adjacencyIds = NULL;
303  }
304  }
305 #endif
306 
307 private:
308  int dimension_, num_nodes_global_, num_elems_global_, num_nodes_, num_elem_;
309  gno_t *element_num_map_, *node_num_map_;
310  int *elemToNode_, tnoct_, *elemOffsets_;
311  int *nodeToElem_, telct_, *nodeOffsets_;
312  double *coords_, *Acoords_;
313  lno_t *eStart_, *nStart_;
314  gno_t *eAdj_, *nAdj_;
315  size_t nEadj_, nNadj_;
316  EntityTopologyType* nodeTopology;
317  EntityTopologyType* elemTopology;
318 
319 };
320 
322 // Definitions
324 
325 template <typename User>
327  std::string typestr):
328  dimension_(0)
329 {
330  int error = 0;
331  char title[100];
332  int exoid = 0;
333  int num_elem_blk, num_node_sets, num_side_sets;
334  error += im_ex_get_init(exoid, title, &dimension_,
335  &num_nodes_, &num_elem_, &num_elem_blk,
336  &num_node_sets, &num_side_sets);
337 
338  if (typestr.compare("region") == 0) {
339  if (dimension_ == 3)
340  this->setEntityTypes(typestr, "vertex", "vertex");
341  else
342  // automatically downgrade primary entity if problem is only 2D
343  this->setEntityTypes("face", "vertex", "vertex");
344  }
345  else if (typestr.compare("vertex") == 0) {
346  if (dimension_ == 3)
347  this->setEntityTypes(typestr, "region", "region");
348  else
349  this->setEntityTypes(typestr, "face", "face");
350  }
351  else {
353  }
354 
355  coords_ = new double [num_nodes_ * dimension_];
356 
357  error += im_ex_get_coord(exoid, coords_, coords_ + num_nodes_,
358  coords_ + 2 * num_nodes_);
359 
360  element_num_map_ = new gno_t [num_elem_];
361  std::vector<int> tmp;
362  tmp.resize(num_elem_);
363 
364  // BDD cast to int did not always work!
365  // error += im_ex_get_elem_num_map(exoid, (int *)element_num_map_)
366  // This may be a case of calling the wrong method
367  error += im_ex_get_elem_num_map(exoid, &tmp[0]);
368  for(size_t i = 0; i < tmp.size(); i++)
369  element_num_map_[i] = static_cast<gno_t>(tmp[i]);
370 
371  tmp.clear();
372  tmp.resize(num_nodes_);
373  node_num_map_ = new gno_t [num_nodes_];
374 
375  // BDD cast to int did not always work!
376  // error += im_ex_get_node_num_map(exoid, (int *)node_num_map_);
377  // This may be a case of calling the wrong method
378  error += im_ex_get_node_num_map(exoid, &tmp[0]);
379  for(size_t i = 0; i < tmp.size(); i++)
380  node_num_map_[i] = static_cast<gno_t>(tmp[i]);
381 
382  nodeTopology = new enum EntityTopologyType[num_nodes_];
383  for (int i=0;i<num_nodes_;i++)
384  nodeTopology[i] = POINT;
385  elemTopology = new enum EntityTopologyType[num_elem_];
386  for (int i=0;i<num_elem_;i++) {
387  if (dimension_==2)
388  elemTopology[i] = QUADRILATERAL;
389  else
390  elemTopology[i] = HEXAHEDRON;
391  }
392 
393  int *elem_blk_ids = new int [num_elem_blk];
394  error += im_ex_get_elem_blk_ids(exoid, elem_blk_ids);
395 
396  int *num_nodes_per_elem = new int [num_elem_blk];
397  int *num_attr = new int [num_elem_blk];
398  int *num_elem_this_blk = new int [num_elem_blk];
399  char **elem_type = new char * [num_elem_blk];
400  int **connect = new int * [num_elem_blk];
401 
402  for(int i = 0; i < num_elem_blk; i++){
403  elem_type[i] = new char [MAX_STR_LENGTH + 1];
404  error += im_ex_get_elem_block(exoid, elem_blk_ids[i], elem_type[i],
405  (int*)&(num_elem_this_blk[i]),
406  (int*)&(num_nodes_per_elem[i]),
407  (int*)&(num_attr[i]));
408  delete[] elem_type[i];
409  }
410 
411  delete[] elem_type;
412  elem_type = NULL;
413  delete[] num_attr;
414  num_attr = NULL;
415  Acoords_ = new double [num_elem_ * dimension_];
416  int a = 0;
417  std::vector<std::vector<int> > sur_elem;
418  sur_elem.resize(num_nodes_);
419 
420  for(int b = 0; b < num_elem_blk; b++) {
421  connect[b] = new int [num_nodes_per_elem[b]*num_elem_this_blk[b]];
422  error += im_ex_get_elem_conn(exoid, elem_blk_ids[b], connect[b]);
423 
424  for(int i = 0; i < num_elem_this_blk[b]; i++) {
425  Acoords_[a] = 0;
426  Acoords_[num_elem_ + a] = 0;
427 
428  if (3 == dimension_) {
429  Acoords_[2 * num_elem_ + a] = 0;
430  }
431 
432  for(int j = 0; j < num_nodes_per_elem[b]; j++) {
433  int node = connect[b][i * num_nodes_per_elem[b] + j] - 1;
434  Acoords_[a] += coords_[node];
435  Acoords_[num_elem_ + a] += coords_[num_nodes_ + node];
436 
437  if(3 == dimension_) {
438  Acoords_[2 * num_elem_ + a] += coords_[2 * num_nodes_ + node];
439  }
440 
441  /*
442  * in the case of degenerate elements, where a node can be
443  * entered into the connect table twice, need to check to
444  * make sure that this element is not already listed as
445  * surrounding this node
446  */
447  if (sur_elem[node].empty() ||
448  element_num_map_[a] != sur_elem[node][sur_elem[node].size()-1]) {
449  /* Add the element to the list */
450  sur_elem[node].push_back(element_num_map_[a]);
451  }
452  }
453 
454  Acoords_[a] /= num_nodes_per_elem[b];
455  Acoords_[num_elem_ + a] /= num_nodes_per_elem[b];
456 
457  if(3 == dimension_) {
458  Acoords_[2 * num_elem_ + a] /= num_nodes_per_elem[b];
459  }
460 
461  a++;
462  }
463 
464  }
465 
466  delete[] elem_blk_ids;
467  elem_blk_ids = NULL;
468  int nnodes_per_elem = num_nodes_per_elem[0];
469  elemToNode_ = new int [num_elem_ * nnodes_per_elem];
470  int telct = 0;
471  elemOffsets_ = new int [num_elem_+1];
472  tnoct_ = 0;
473  int **reconnect = new int * [num_elem_];
474  size_t max_nsur = 0;
475 
476  for (int b = 0; b < num_elem_blk; b++) {
477  for (int i = 0; i < num_elem_this_blk[b]; i++) {
478  elemOffsets_[telct] = tnoct_;
479  reconnect[telct] = new int [num_nodes_per_elem[b]];
480 
481  for (int j = 0; j < num_nodes_per_elem[b]; j++) {
482  elemToNode_[tnoct_]=
483  node_num_map_[connect[b][i*num_nodes_per_elem[b] + j]-1];
484  reconnect[telct][j] = connect[b][i*num_nodes_per_elem[b] + j];
485  ++tnoct_;
486  }
487 
488  ++telct;
489  }
490  }
491  elemOffsets_[telct] = tnoct_;
492 
493  delete[] num_nodes_per_elem;
494  num_nodes_per_elem = NULL;
495  delete[] num_elem_this_blk;
496  num_elem_this_blk = NULL;
497 
498  for(int b = 0; b < num_elem_blk; b++) {
499  delete[] connect[b];
500  }
501 
502  delete[] connect;
503  connect = NULL;
504 
505  int max_side_nodes = nnodes_per_elem;
506  int *side_nodes = new int [max_side_nodes];
507  int *mirror_nodes = new int [max_side_nodes];
508 
509  /* Allocate memory necessary for the adjacency */
510  eStart_ = new lno_t [num_elem_+1];
511  nStart_ = new lno_t [num_nodes_+1];
512  std::vector<int> eAdj;
513  std::vector<int> nAdj;
514 
515  for (int i=0; i < max_side_nodes; i++) {
516  side_nodes[i]=-999;
517  mirror_nodes[i]=-999;
518  }
519 
520  /* Find the adjacency for a nodal based decomposition */
521  nEadj_ = 0;
522  nNadj_ = 0;
523  for(int ncnt=0; ncnt < num_nodes_; ncnt++) {
524  if(sur_elem[ncnt].empty()) {
525  std::cout << "WARNING: Node = " << ncnt+1 << " has no elements"
526  << std::endl;
527  } else {
528  size_t nsur = sur_elem[ncnt].size();
529  if (nsur > max_nsur)
530  max_nsur = nsur;
531  }
532  }
533 
534  nodeToElem_ = new int [num_nodes_ * max_nsur];
535  nodeOffsets_ = new int [num_nodes_+1];
536  telct_ = 0;
537 
538  for (int ncnt = 0; ncnt < num_nodes_; ncnt++) {
539  nodeOffsets_[ncnt] = telct_;
540  nStart_[ncnt] = nNadj_;
541  MapType nAdjMap;
542 
543  for (size_t i = 0; i < sur_elem[ncnt].size(); i++) {
544  nodeToElem_[telct_] = sur_elem[ncnt][i];
545  ++telct_;
546 
547 #ifndef USE_MESH_ADAPTER
548  for(int ecnt = 0; ecnt < num_elem_; ecnt++) {
549  if (element_num_map_[ecnt] == sur_elem[ncnt][i]) {
550  for (int j = 0; j < nnodes_per_elem; j++) {
551  MapType::iterator iter =
552  nAdjMap.find(elemToNode_[elemOffsets_[ecnt]+j]);
553 
554  if (node_num_map_[ncnt] != elemToNode_[elemOffsets_[ecnt]+j] &&
555  iter == nAdjMap.end() ) {
556  nAdj.push_back(elemToNode_[elemOffsets_[ecnt]+j]);
557  nNadj_++;
558  nAdjMap.insert({elemToNode_[elemOffsets_[ecnt]+j],
559  elemToNode_[elemOffsets_[ecnt]+j]});
560  }
561  }
562 
563  break;
564  }
565  }
566 #endif
567  }
568 
569  nAdjMap.clear();
570  }
571 
572  nodeOffsets_[num_nodes_] = telct_;
573  nStart_[num_nodes_] = nNadj_;
574 
575  nAdj_ = new gno_t [nNadj_];
576 
577  for (size_t i=0; i < nNadj_; i++) {
578  nAdj_[i] = nAdj[i];
579  }
580 
581  int nprocs = comm.getSize();
582  //if (nprocs > 1) {
583  int neid=0,num_elem_blks_global,num_node_sets_global,num_side_sets_global;
584  error += im_ne_get_init_global(neid,&num_nodes_global_,&num_elems_global_,
585  &num_elem_blks_global,&num_node_sets_global,
586  &num_side_sets_global);
587 
588  int num_internal_nodes, num_border_nodes, num_external_nodes;
589  int num_internal_elems, num_border_elems, num_node_cmaps, num_elem_cmaps;
590  int proc = 0;
591  error += im_ne_get_loadbal_param(neid, &num_internal_nodes,
592  &num_border_nodes, &num_external_nodes,
593  &num_internal_elems, &num_border_elems,
594  &num_node_cmaps, &num_elem_cmaps, proc);
595 
596  int *node_cmap_ids = new int [num_node_cmaps];
597  int *node_cmap_node_cnts = new int [num_node_cmaps];
598  int *elem_cmap_ids = new int [num_elem_cmaps];
599  int *elem_cmap_elem_cnts = new int [num_elem_cmaps];
600  error += im_ne_get_cmap_params(neid, node_cmap_ids, node_cmap_node_cnts,
601  elem_cmap_ids, elem_cmap_elem_cnts, proc);
602  delete[] elem_cmap_ids;
603  elem_cmap_ids = NULL;
604  delete[] elem_cmap_elem_cnts;
605  elem_cmap_elem_cnts = NULL;
606 
607  int **node_ids = new int * [num_node_cmaps];
608  int **node_proc_ids = new int * [num_node_cmaps];
609  for(int j = 0; j < num_node_cmaps; j++) {
610  node_ids[j] = new int [node_cmap_node_cnts[j]];
611  node_proc_ids[j] = new int [node_cmap_node_cnts[j]];
612  error += im_ne_get_node_cmap(neid, node_cmap_ids[j], node_ids[j],
613  node_proc_ids[j], proc);
614  }
615  delete[] node_cmap_ids;
616  node_cmap_ids = NULL;
617  int *sendCount = new int [nprocs];
618  int *recvCount = new int [nprocs];
619 
620  // Post receives
621  RCP<CommRequest<int> >*requests=new RCP<CommRequest<int> >[num_node_cmaps];
622  for (int cnt = 0, i = 0; i < num_node_cmaps; i++) {
623  try {
624  requests[cnt++] =
625  Teuchos::ireceive<int,int>(comm,
626  rcp(&(recvCount[node_proc_ids[i][0]]),
627  false),
628  node_proc_ids[i][0]);
629  }
631  }
632 
633  Teuchos::barrier<int>(comm);
634  size_t totalsend = 0;
635 
636  for(int j = 0; j < num_node_cmaps; j++) {
637  sendCount[node_proc_ids[j][0]] = 1;
638  for(int i = 0; i < node_cmap_node_cnts[j]; i++) {
639  sendCount[node_proc_ids[j][i]] += sur_elem[node_ids[j][i]-1].size()+2;
640  }
641  totalsend += sendCount[node_proc_ids[j][0]];
642  }
643 
644  // Send data; can use readySend since receives are posted.
645  for (int i = 0; i < num_node_cmaps; i++) {
646  try {
647  Teuchos::readySend<int,int>(comm, sendCount[node_proc_ids[i][0]],
648  node_proc_ids[i][0]);
649  }
651  }
652 
653  // Wait for messages to return.
654  try {
655  Teuchos::waitAll<int>(comm, arrayView(requests, num_node_cmaps));
656  }
658 
659  delete [] requests;
660 
661  // Allocate the receive buffer.
662  size_t totalrecv = 0;
663  int maxMsg = 0;
664  int nrecvranks = 0;
665  for(int i = 0; i < num_node_cmaps; i++) {
666  if (recvCount[node_proc_ids[i][0]] > 0) {
667  totalrecv += recvCount[node_proc_ids[i][0]];
668  nrecvranks++;
669  if (recvCount[node_proc_ids[i][0]] > maxMsg)
670  maxMsg = recvCount[node_proc_ids[i][0]];
671  }
672  }
673 
674  int *rbuf = NULL;
675  if (totalrecv) rbuf = new int[totalrecv];
676 
677  requests = new RCP<CommRequest<int> > [nrecvranks];
678 
679  // Error checking for memory and message size.
680  int OK[2] = {1,1};
681  // OK[0] -- true/false indicating whether each message size fits in an int
682  // (for MPI).
683  // OK[1] -- true/false indicating whether memory allocs are OK
684  int gOK[2]; // For global reduce of OK.
685 
686  if (size_t(maxMsg) * sizeof(int) > INT_MAX) OK[0] = false;
687  if (totalrecv && !rbuf) OK[1] = 0;
688  if (!requests) OK[1] = 0;
689 
690  // Post receives
691 
692  size_t offset = 0;
693 
694  if (OK[0] && OK[1]) {
695  int rcnt = 0;
696  for (int i = 0; i < num_node_cmaps; i++) {
697  if (recvCount[node_proc_ids[i][0]]) {
698  try {
699  requests[rcnt++] =
700  Teuchos::
701  ireceive<int,int>(comm,
702  Teuchos::arcp(&rbuf[offset], 0,
703  recvCount[node_proc_ids[i][0]],
704  false),
705  node_proc_ids[i][0]);
706  }
708  }
709  offset += recvCount[node_proc_ids[i][0]];
710  }
711  }
712 
713  delete[] recvCount;
714 
715  // Use barrier for error checking
716  Teuchos::reduceAll<int>(comm, Teuchos::REDUCE_MIN, 2, OK, gOK);
717  if (!gOK[0] || !gOK[1]) {
718  delete [] rbuf;
719  delete [] requests;
720  if (!gOK[0])
721  throw std::runtime_error("Max single message length exceeded");
722  else
723  throw std::bad_alloc();
724  }
725 
726  int *sbuf = NULL;
727  if (totalsend) sbuf = new int[totalsend];
728  a = 0;
729 
730  for(int j = 0; j < num_node_cmaps; j++) {
731  sbuf[a++] = node_cmap_node_cnts[j];
732  for(int i = 0; i < node_cmap_node_cnts[j]; i++) {
733  sbuf[a++] = node_num_map_[node_ids[j][i]-1];
734  sbuf[a++] = sur_elem[node_ids[j][i]-1].size();
735  for(size_t ecnt=0; ecnt < sur_elem[node_ids[j][i]-1].size(); ecnt++) {
736  sbuf[a++] = sur_elem[node_ids[j][i]-1][ecnt];
737  }
738  }
739  }
740 
741  delete[] node_cmap_node_cnts;
742  node_cmap_node_cnts = NULL;
743 
744  for(int j = 0; j < num_node_cmaps; j++) {
745  delete[] node_ids[j];
746  }
747 
748  delete[] node_ids;
749  node_ids = NULL;
750  ArrayRCP<int> sendBuf;
751 
752  if (totalsend)
753  sendBuf = ArrayRCP<int>(sbuf, 0, totalsend, true);
754  else
755  sendBuf = Teuchos::null;
756 
757  // Send data; can use readySend since receives are posted.
758  offset = 0;
759  for (int i = 0; i < num_node_cmaps; i++) {
760  if (sendCount[node_proc_ids[i][0]]) {
761  try{
762  Teuchos::readySend<int,
763  int>(comm,
764  Teuchos::arrayView(&sendBuf[offset],
765  sendCount[node_proc_ids[i][0]]),
766  node_proc_ids[i][0]);
767  }
769  }
770  offset += sendCount[node_proc_ids[i][0]];
771  }
772 
773  for(int j = 0; j < num_node_cmaps; j++) {
774  delete[] node_proc_ids[j];
775  }
776 
777  delete[] node_proc_ids;
778  node_proc_ids = NULL;
779  delete[] sendCount;
780 
781  // Wait for messages to return.
782  try{
783  Teuchos::waitAll<int>(comm, Teuchos::arrayView(requests, nrecvranks));
784  }
786 
787  delete[] requests;
788  a = 0;
789 
790  for (int i = 0; i < num_node_cmaps; i++) {
791  int num_nodes_this_processor = rbuf[a++];
792 
793  for (int j = 0; j < num_nodes_this_processor; j++) {
794  int this_node = rbuf[a++];
795  int num_elem_this_node = rbuf[a++];
796 
797  for (int ncnt = 0; ncnt < num_nodes_; ncnt++) {
798  if (node_num_map_[ncnt] == this_node) {
799  for (int ecnt = 0; ecnt < num_elem_this_node; ecnt++) {
800  sur_elem[ncnt].push_back(rbuf[a++]);
801  }
802 
803  break;
804  }
805  }
806  }
807  }
808 
809  delete[] rbuf;
810  //}
811 
812 #ifndef USE_MESH_ADAPTER
813  for(int ecnt=0; ecnt < num_elem_; ecnt++) {
814  eStart_[ecnt] = nEadj_;
815  MapType eAdjMap;
816  int nnodes = nnodes_per_elem;
817  for(int ncnt=0; ncnt < nnodes; ncnt++) {
818  int node = reconnect[ecnt][ncnt]-1;
819  for(size_t i=0; i < sur_elem[node].size(); i++) {
820  int entry = sur_elem[node][i];
821  MapType::iterator iter = eAdjMap.find(entry);
822 
823  if(element_num_map_[ecnt] != entry &&
824  iter == eAdjMap.end()) {
825  eAdj.push_back(entry);
826  nEadj_++;
827  eAdjMap.insert({entry, entry});
828  }
829  }
830  }
831 
832  eAdjMap.clear();
833  }
834 #endif
835 
836  for(int b = 0; b < num_elem_; b++) {
837  delete[] reconnect[b];
838  }
839 
840  delete[] reconnect;
841  reconnect = NULL;
842  eStart_[num_elem_] = nEadj_;
843 
844  eAdj_ = new gno_t [nEadj_];
845 
846  for (size_t i=0; i < nEadj_; i++) {
847  eAdj_[i] = eAdj[i];
848  }
849 
850  delete[] side_nodes;
851  side_nodes = NULL;
852  delete[] mirror_nodes;
853  mirror_nodes = NULL;
854 }
855 
856 template <typename User>
858 {
859  std::string fn(" PamgenMesh ");
860  std::cout << me << fn
861  << " dim = " << dimension_
862  << " nodes = " << num_nodes_
863  << " nelems = " << num_elem_
864  << std::endl;
865 
866  for (int i = 0; i < num_elem_; i++) {
867  std::cout << me << fn << i
868  << " Elem " << element_num_map_[i]
869  << " Coords: ";
870  for (int j = 0; j < dimension_; j++)
871  std::cout << Acoords_[i + j * num_elem_] << " ";
872  std::cout << std::endl;
873  }
874 
875 #ifndef USE_MESH_ADAPTER
876  for (int i = 0; i < num_elem_; i++) {
877  std::cout << me << fn << i
878  << " Elem " << element_num_map_[i]
879  << " Graph: ";
880  for (int j = eStart_[i]; j < eStart_[i+1]; j++)
881  std::cout << eAdj_[j] << " ";
882  std::cout << std::endl;
883  }
884 #endif
885 }
886 
887 } //namespace Zoltan2
888 
889 #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...
int getDimension() const
Return dimension of the entity coordinates, if any.
Defines the MeshAdapter interface.
MeshAdapter defines the interface for mesh input.
default_part_t part_t
The data type to represent part numbers.
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&#39; optional entity weights.
void getIDsViewOf(MeshEntityType etype, const gno_t *&Ids) const
Provide a pointer to this process&#39; identifiers.
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
Provide a pointer to one dimension of entity coordinates.
#define Z2_THROW_NOT_IMPLEMENTED_IN_ADAPTER
InputTraits< User >::lno_t lno_t
MeshEntityType
Enumerate entity types for meshes: Regions, Faces, Edges, or Vertices.
void get2ndAdjsView(MeshEntityType sourcetarget, MeshEntityType through, const lno_t *&offsets, const gno_t *&adjacencyIds) const
void getAdjsView(MeshEntityType source, MeshEntityType target, const lno_t *&offsets, const gno_t *&adjacencyIds) const
This class represents a mesh.
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.
PamgenMeshAdapter(const Comm< int > &comm, std::string typestr="region")
Constructor for mesh with identifiers but no coordinates or edges.
This file defines the StridedData class.