50 #ifndef _ZOLTAN2_PAMGENMESHADAPTER_HPP_ 51 #define _ZOLTAN2_PAMGENMESHADAPTER_HPP_ 58 #include <pamgen_im_exodusII.h> 59 #include "pamgen_im_ne_nemesisI.h" 89 template <
typename User>
126 (
MESH_FACE == etype && 2 == dimension_)) {
140 (
MESH_FACE == etype && 2 == dimension_)) {
141 Ids = element_num_map_;
154 (
MESH_FACE == etype && 2 == dimension_)) {
155 Types = elemTopology;
159 Types = nodeTopology;
166 int &stride,
int idx = 0)
const 175 int &stride,
int dim)
const {
177 (
MESH_FACE == etype && 2 == dimension_)) {
180 }
else if (dim == 1) {
181 coords = Acoords_ + num_elem_;
182 }
else if (dim == 2) {
183 coords = Acoords_ + 2 * num_elem_;
186 }
else if (
MESH_REGION == etype && 2 == dimension_) {
192 }
else if (dim == 1) {
193 coords = coords_ + num_nodes_;
194 }
else if (dim == 2) {
195 coords = coords_ + 2 * num_nodes_;
232 const lno_t *&offsets,
const gno_t *& adjacencyIds)
const 236 offsets = elemOffsets_;
237 adjacencyIds = (gno_t *)elemToNode_;
240 offsets = nodeOffsets_;
241 adjacencyIds = (gno_t *)nodeToElem_;
242 }
else if (
MESH_REGION == source && 2 == dimension_) {
253 #ifndef USE_MESH_ADAPTER 257 if (sourcetarget ==
MESH_REGION && dimension_ == 3)
return true;
258 if (sourcetarget ==
MESH_FACE && dimension_ == 2)
return true;
261 if (through ==
MESH_REGION && dimension_ == 3)
return true;
262 if (through ==
MESH_FACE && dimension_ == 2)
return true;
271 ((sourcetarget ==
MESH_REGION && dimension_ == 3) ||
272 (sourcetarget ==
MESH_FACE && dimension_ == 2))) {
278 (through ==
MESH_FACE && dimension_ == 2))) {
287 const lno_t *&offsets,
const gno_t *&adjacencyIds)
const 290 ((sourcetarget ==
MESH_REGION && dimension_ == 3) ||
291 (sourcetarget ==
MESH_FACE && dimension_ == 2))) {
293 adjacencyIds = eAdj_;
296 (through ==
MESH_FACE && dimension_ == 2))) {
298 adjacencyIds = nAdj_;
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_;
325 template <
typename User>
327 std::string typestr):
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);
338 if (typestr.compare(
"region") == 0) {
345 else if (typestr.compare(
"vertex") == 0) {
355 coords_ =
new double [num_nodes_ * dimension_];
357 error += im_ex_get_coord(exoid, coords_, coords_ + num_nodes_,
358 coords_ + 2 * num_nodes_);
360 element_num_map_ =
new gno_t [num_elem_];
361 std::vector<int> tmp;
362 tmp.resize(num_elem_);
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]);
372 tmp.resize(num_nodes_);
373 node_num_map_ =
new gno_t [num_nodes_];
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]);
383 for (
int i=0;i<num_nodes_;i++)
384 nodeTopology[i] =
POINT;
386 for (
int i=0;i<num_elem_;i++) {
393 int *elem_blk_ids =
new int [num_elem_blk];
394 error += im_ex_get_elem_blk_ids(exoid, elem_blk_ids);
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];
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];
415 Acoords_ =
new double [num_elem_ * dimension_];
417 std::vector<std::vector<int> > sur_elem;
418 sur_elem.resize(num_nodes_);
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]);
424 for(
int i = 0; i < num_elem_this_blk[b]; i++) {
426 Acoords_[num_elem_ + a] = 0;
428 if (3 == dimension_) {
429 Acoords_[2 * num_elem_ + a] = 0;
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];
437 if(3 == dimension_) {
438 Acoords_[2 * num_elem_ + a] += coords_[2 * num_nodes_ + node];
447 if (sur_elem[node].empty() ||
448 element_num_map_[a] != sur_elem[node][sur_elem[node].size()-1]) {
450 sur_elem[node].push_back(element_num_map_[a]);
454 Acoords_[a] /= num_nodes_per_elem[b];
455 Acoords_[num_elem_ + a] /= num_nodes_per_elem[b];
457 if(3 == dimension_) {
458 Acoords_[2 * num_elem_ + a] /= num_nodes_per_elem[b];
466 delete[] elem_blk_ids;
468 int nnodes_per_elem = num_nodes_per_elem[0];
469 elemToNode_ =
new int [num_elem_ * nnodes_per_elem];
471 elemOffsets_ =
new int [num_elem_+1];
473 int **reconnect =
new int * [num_elem_];
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]];
481 for (
int j = 0; j < num_nodes_per_elem[b]; j++) {
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];
491 elemOffsets_[telct] = tnoct_;
493 delete[] num_nodes_per_elem;
494 num_nodes_per_elem = NULL;
495 delete[] num_elem_this_blk;
496 num_elem_this_blk = NULL;
498 for(
int b = 0; b < num_elem_blk; b++) {
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];
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;
515 for (
int i=0; i < max_side_nodes; i++) {
517 mirror_nodes[i]=-999;
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" 528 size_t nsur = sur_elem[ncnt].size();
534 nodeToElem_ =
new int [num_nodes_ * max_nsur];
535 nodeOffsets_ =
new int [num_nodes_+1];
538 for (
int ncnt = 0; ncnt < num_nodes_; ncnt++) {
539 nodeOffsets_[ncnt] = telct_;
540 nStart_[ncnt] = nNadj_;
543 for (
size_t i = 0; i < sur_elem[ncnt].size(); i++) {
544 nodeToElem_[telct_] = sur_elem[ncnt][i];
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]);
554 if (node_num_map_[ncnt] != elemToNode_[elemOffsets_[ecnt]+j] &&
555 iter == nAdjMap.end() ) {
556 nAdj.push_back(elemToNode_[elemOffsets_[ecnt]+j]);
558 nAdjMap.insert({elemToNode_[elemOffsets_[ecnt]+j],
559 elemToNode_[elemOffsets_[ecnt]+j]});
572 nodeOffsets_[num_nodes_] = telct_;
573 nStart_[num_nodes_] = nNadj_;
575 nAdj_ =
new gno_t [nNadj_];
577 for (
size_t i=0; i < nNadj_; i++) {
581 int nprocs = comm.getSize();
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);
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;
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);
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;
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);
615 delete[] node_cmap_ids;
616 node_cmap_ids = NULL;
617 int *sendCount =
new int [nprocs];
618 int *recvCount =
new int [nprocs];
621 RCP<CommRequest<int> >*requests=
new RCP<CommRequest<int> >[num_node_cmaps];
622 for (
int cnt = 0, i = 0; i < num_node_cmaps; i++) {
625 Teuchos::ireceive<int,int>(comm,
626 rcp(&(recvCount[node_proc_ids[i][0]]),
628 node_proc_ids[i][0]);
633 Teuchos::barrier<int>(comm);
634 size_t totalsend = 0;
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;
641 totalsend += sendCount[node_proc_ids[j][0]];
645 for (
int i = 0; i < num_node_cmaps; i++) {
647 Teuchos::readySend<int,int>(comm, sendCount[node_proc_ids[i][0]],
648 node_proc_ids[i][0]);
655 Teuchos::waitAll<int>(comm, arrayView(requests, num_node_cmaps));
662 size_t totalrecv = 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]];
669 if (recvCount[node_proc_ids[i][0]] > maxMsg)
670 maxMsg = recvCount[node_proc_ids[i][0]];
675 if (totalrecv) rbuf =
new int[totalrecv];
677 requests =
new RCP<CommRequest<int> > [nrecvranks];
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;
694 if (OK[0] && OK[1]) {
696 for (
int i = 0; i < num_node_cmaps; i++) {
697 if (recvCount[node_proc_ids[i][0]]) {
701 ireceive<int,int>(comm,
702 Teuchos::arcp(&rbuf[offset], 0,
703 recvCount[node_proc_ids[i][0]],
705 node_proc_ids[i][0]);
709 offset += recvCount[node_proc_ids[i][0]];
716 Teuchos::reduceAll<int>(comm, Teuchos::REDUCE_MIN, 2, OK, gOK);
717 if (!gOK[0] || !gOK[1]) {
721 throw std::runtime_error(
"Max single message length exceeded");
723 throw std::bad_alloc();
727 if (totalsend) sbuf =
new int[totalsend];
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];
741 delete[] node_cmap_node_cnts;
742 node_cmap_node_cnts = NULL;
744 for(
int j = 0; j < num_node_cmaps; j++) {
745 delete[] node_ids[j];
750 ArrayRCP<int> sendBuf;
753 sendBuf = ArrayRCP<int>(sbuf, 0, totalsend,
true);
755 sendBuf = Teuchos::null;
759 for (
int i = 0; i < num_node_cmaps; i++) {
760 if (sendCount[node_proc_ids[i][0]]) {
762 Teuchos::readySend<int,
764 Teuchos::arrayView(&sendBuf[offset],
765 sendCount[node_proc_ids[i][0]]),
766 node_proc_ids[i][0]);
770 offset += sendCount[node_proc_ids[i][0]];
773 for(
int j = 0; j < num_node_cmaps; j++) {
774 delete[] node_proc_ids[j];
777 delete[] node_proc_ids;
778 node_proc_ids = NULL;
783 Teuchos::waitAll<int>(comm, Teuchos::arrayView(requests, nrecvranks));
790 for (
int i = 0; i < num_node_cmaps; i++) {
791 int num_nodes_this_processor = rbuf[a++];
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++];
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++]);
812 #ifndef USE_MESH_ADAPTER 813 for(
int ecnt=0; ecnt < num_elem_; ecnt++) {
814 eStart_[ecnt] = nEadj_;
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);
823 if(element_num_map_[ecnt] != entry &&
824 iter == eAdjMap.end()) {
825 eAdj.push_back(entry);
827 eAdjMap.insert({entry, entry});
836 for(
int b = 0; b < num_elem_; b++) {
837 delete[] reconnect[b];
842 eStart_[num_elem_] = nEadj_;
844 eAdj_ =
new gno_t [nEadj_];
846 for (
size_t i=0; i < nEadj_; i++) {
852 delete[] mirror_nodes;
856 template <
typename User>
859 std::string fn(
" PamgenMesh ");
860 std::cout << me << fn
861 <<
" dim = " << dimension_
862 <<
" nodes = " << num_nodes_
863 <<
" nelems = " << num_elem_
866 for (
int i = 0; i < num_elem_; i++) {
867 std::cout << me << fn << i
868 <<
" Elem " << element_num_map_[i]
870 for (
int j = 0; j < dimension_; j++)
871 std::cout << Acoords_[i + j * num_elem_] <<
" ";
872 std::cout << std::endl;
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]
880 for (
int j = eStart_[i]; j < eStart_[i+1]; j++)
881 std::cout << eAdj_[j] <<
" ";
882 std::cout << std::endl;
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.
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.
void getIDsViewOf(MeshEntityType etype, const gno_t *&Ids) const
Provide a pointer to this process' 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
MeshAdapter< User > base_adapter_t
std::map< int, int > MapType
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.
InputTraits< User >::node_t node_t
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.
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.