14 #ifndef _ZOLTAN2_PAMGENMESHADAPTER_HPP_
15 #define _ZOLTAN2_PAMGENMESHADAPTER_HPP_
19 #include <Teuchos_as.hpp>
23 #include <pamgen_im_exodusII.h>
24 #include <pamgen_im_ne_nemesisI.h>
54 template <
typename User>
100 (
MESH_FACE == etype && 2 == dimension_)) {
114 (
MESH_FACE == etype && 2 == dimension_)) {
115 Ids = element_num_map_;
128 (
MESH_FACE == etype && 2 == dimension_)) {
129 Types = elemTopology;
133 Types = nodeTopology;
140 int &stride,
int idx = 0)
const
149 int &stride,
int dim)
const {
151 (
MESH_FACE == etype && 2 == dimension_)) {
154 }
else if (dim == 1) {
155 coords = Acoords_ + num_elem_;
156 }
else if (dim == 2) {
157 coords = Acoords_ + 2 * num_elem_;
160 }
else if (
MESH_REGION == etype && 2 == dimension_) {
166 }
else if (dim == 1) {
167 coords = coords_ + num_nodes_;
168 }
else if (dim == 2) {
169 coords = coords_ + 2 * num_nodes_;
210 offsets = elemOffsets_;
211 adjacencyIds = elemToNode_;
214 offsets = nodeOffsets_;
215 adjacencyIds = nodeToElem_;
216 }
else if (
MESH_REGION == source && 2 == dimension_) {
227 #ifndef USE_MESH_ADAPTER
231 if (sourcetarget ==
MESH_REGION && dimension_ == 3)
return true;
232 if (sourcetarget ==
MESH_FACE && dimension_ == 2)
return true;
235 if (through ==
MESH_REGION && dimension_ == 3)
return true;
236 if (through ==
MESH_FACE && dimension_ == 2)
return true;
245 ((sourcetarget ==
MESH_REGION && dimension_ == 3) ||
246 (sourcetarget ==
MESH_FACE && dimension_ == 2))) {
252 (through ==
MESH_FACE && dimension_ == 2))) {
263 ((sourcetarget ==
MESH_REGION && dimension_ == 3) ||
264 (sourcetarget ==
MESH_FACE && dimension_ == 2))) {
266 adjacencyIds = eAdj_;
269 (through ==
MESH_FACE && dimension_ == 2))) {
271 adjacencyIds = nAdj_;
283 (
MESH_FACE == etype && 2 == dimension_) ||
285 return entityDegreeWeight_[idx];
292 int dimension_, num_nodes_global_, num_elems_global_, num_nodes_, num_elem_;
293 gno_t *element_num_map_, *node_num_map_;
299 int nWeightsPerEntity_;
300 bool *entityDegreeWeight_;
304 gno_t *eAdj_, *nAdj_;
305 size_t nEadj_, nNadj_;
315 template <
typename User>
317 std::string typestr,
int nEntWgts):
318 dimension_(0), nWeightsPerEntity_(nEntWgts), entityDegreeWeight_()
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);
330 if (typestr.compare(
"region") == 0) {
337 else if (typestr.compare(
"vertex") == 0) {
347 double *dcoords =
new double [num_nodes_ * dimension_];
348 coords_ =
new scalar_t [num_nodes_ * dimension_];
350 error += im_ex_get_coord(exoid, dcoords, dcoords + num_nodes_,
351 dcoords + 2 * num_nodes_);
353 size_t dlen = num_nodes_ * dimension_;
354 for (
size_t i = 0; i < dlen; i++) coords_[i] = as<scalar_t>(dcoords[i]);
357 element_num_map_ =
new gno_t[num_elem_];
358 std::vector<int> tmp;
359 tmp.resize(num_elem_);
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]);
369 tmp.resize(num_nodes_);
370 node_num_map_ =
new gno_t [num_nodes_];
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]);
380 for (
int i=0;i<num_nodes_;i++)
381 nodeTopology[i] =
POINT;
383 for (
int i=0;i<num_elem_;i++) {
390 int *elem_blk_ids =
new int [num_elem_blk];
391 error += im_ex_get_elem_blk_ids(exoid, elem_blk_ids);
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];
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];
412 Acoords_ =
new scalar_t [num_elem_ * dimension_];
414 std::vector<std::vector<gno_t> > sur_elem;
415 sur_elem.resize(num_nodes_);
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]);
421 for(
int i = 0; i < num_elem_this_blk[b]; i++) {
423 Acoords_[num_elem_ + a] = 0;
425 if (3 == dimension_) {
426 Acoords_[2 * num_elem_ + a] = 0;
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];
434 if(3 == dimension_) {
435 Acoords_[2 * num_elem_ + a] += coords_[2 * num_nodes_ + node];
444 if (sur_elem[node].empty() ||
445 element_num_map_[a] != sur_elem[node][sur_elem[node].size()-1]) {
447 sur_elem[node].push_back(element_num_map_[a]);
451 Acoords_[a] /= num_nodes_per_elem[b];
452 Acoords_[num_elem_ + a] /= num_nodes_per_elem[b];
454 if(3 == dimension_) {
455 Acoords_[2 * num_elem_ + a] /= num_nodes_per_elem[b];
463 delete[] elem_blk_ids;
465 int nnodes_per_elem = num_nodes_per_elem[0];
466 elemToNode_ =
new gno_t[num_elem_ * nnodes_per_elem];
468 elemOffsets_ =
new offset_t [num_elem_+1];
470 int **reconnect =
new int * [num_elem_];
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]];
478 for (
int j = 0; j < num_nodes_per_elem[b]; j++) {
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];
488 elemOffsets_[telct] = tnoct_;
490 delete[] num_nodes_per_elem;
491 num_nodes_per_elem = NULL;
492 delete[] num_elem_this_blk;
493 num_elem_this_blk = NULL;
495 for(
int b = 0; b < num_elem_blk; b++) {
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];
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;
512 for (
int i=0; i < max_side_nodes; i++) {
514 mirror_nodes[i]=-999;
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"
525 size_t nsur = sur_elem[ncnt].size();
531 nodeToElem_ =
new gno_t[num_nodes_ * max_nsur];
532 nodeOffsets_ =
new offset_t[num_nodes_+1];
535 for (
int ncnt = 0; ncnt < num_nodes_; ncnt++) {
536 nodeOffsets_[ncnt] = telct_;
537 nStart_[ncnt] = nNadj_;
540 for (
size_t i = 0; i < sur_elem[ncnt].size(); i++) {
541 nodeToElem_[telct_] = sur_elem[ncnt][i];
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]);
551 if (node_num_map_[ncnt] != elemToNode_[elemOffsets_[ecnt]+j] &&
552 iter == nAdjMap.end() ) {
553 nAdj.push_back(elemToNode_[elemOffsets_[ecnt]+j]);
555 nAdjMap.insert({elemToNode_[elemOffsets_[ecnt]+j],
556 elemToNode_[elemOffsets_[ecnt]+j]});
569 nodeOffsets_[num_nodes_] = telct_;
570 nStart_[num_nodes_] = nNadj_;
572 nAdj_ =
new gno_t [nNadj_];
574 for (
size_t i=0; i < nNadj_; i++) {
575 nAdj_[i] = as<gno_t>(nAdj[i]);
578 int nprocs = comm.getSize();
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);
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;
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);
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;
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);
612 delete[] node_cmap_ids;
613 node_cmap_ids = NULL;
614 int *sendCount =
new int [nprocs];
615 int *recvCount =
new int [nprocs];
618 RCP<CommRequest<int> >*requests=
new RCP<CommRequest<int> >[num_node_cmaps];
619 for (
int cnt = 0, i = 0; i < num_node_cmaps; i++) {
622 Teuchos::ireceive<int,int>(comm,
623 rcp(&(recvCount[node_proc_ids[i][0]]),
625 node_proc_ids[i][0]);
630 Teuchos::barrier<int>(comm);
631 size_t totalsend = 0;
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;
638 totalsend += sendCount[node_proc_ids[j][0]];
642 for (
int i = 0; i < num_node_cmaps; i++) {
644 Teuchos::readySend<int,int>(comm, sendCount[node_proc_ids[i][0]],
645 node_proc_ids[i][0]);
652 Teuchos::waitAll<int>(comm, arrayView(requests, num_node_cmaps));
659 size_t totalrecv = 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]];
666 if (recvCount[node_proc_ids[i][0]] > maxMsg)
667 maxMsg = recvCount[node_proc_ids[i][0]];
672 if (totalrecv) rbuf =
new gno_t[totalrecv];
674 requests =
new RCP<CommRequest<int> > [nrecvranks];
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;
691 if (OK[0] && OK[1]) {
693 for (
int i = 0; i < num_node_cmaps; i++) {
694 if (recvCount[node_proc_ids[i][0]]) {
698 ireceive<int,gno_t>(comm,
699 Teuchos::arcp(&rbuf[offset], 0,
700 recvCount[node_proc_ids[i][0]],
702 node_proc_ids[i][0]);
706 offset += recvCount[node_proc_ids[i][0]];
713 Teuchos::reduceAll<int>(comm, Teuchos::REDUCE_MIN, 2, OK, gOK);
714 if (!gOK[0] || !gOK[1]) {
718 throw std::runtime_error(
"Max single message length exceeded");
720 throw std::bad_alloc();
724 if (totalsend) sbuf =
new gno_t[totalsend];
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];
738 delete[] node_cmap_node_cnts;
739 node_cmap_node_cnts = NULL;
741 for(
int j = 0; j < num_node_cmaps; j++) {
742 delete[] node_ids[j];
747 ArrayRCP<gno_t> sendBuf;
750 sendBuf = ArrayRCP<gno_t>(sbuf, 0, totalsend,
true);
752 sendBuf = Teuchos::null;
756 for (
int i = 0; i < num_node_cmaps; i++) {
757 if (sendCount[node_proc_ids[i][0]]) {
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]);
766 offset += sendCount[node_proc_ids[i][0]];
769 for(
int j = 0; j < num_node_cmaps; j++) {
770 delete[] node_proc_ids[j];
773 delete[] node_proc_ids;
774 node_proc_ids = NULL;
779 Teuchos::waitAll<int>(comm, Teuchos::arrayView(requests, nrecvranks));
786 for (
int i = 0; i < num_node_cmaps; i++) {
787 int num_nodes_this_processor = rbuf[a++];
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++];
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++]);
808 #ifndef USE_MESH_ADAPTER
809 for(
int ecnt=0; ecnt < num_elem_; ecnt++) {
810 eStart_[ecnt] = nEadj_;
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);
819 if(element_num_map_[ecnt] != entry &&
820 iter == eAdjMap.end()) {
821 eAdj.push_back(entry);
823 eAdjMap.insert({entry, entry});
832 for(
int b = 0; b < num_elem_; b++) {
833 delete[] reconnect[b];
838 eStart_[num_elem_] = nEadj_;
840 eAdj_ =
new gno_t [nEadj_];
842 for (
size_t i=0; i < nEadj_; i++) {
843 eAdj_[i] = as<gno_t>(eAdj[i]);
848 delete[] mirror_nodes;
851 if (nWeightsPerEntity_ > 0) {
852 entityDegreeWeight_ =
new bool [nWeightsPerEntity_];
853 for (
int i=0; i < nWeightsPerEntity_; i++) {
854 entityDegreeWeight_[i] =
false;
860 template <
typename User>
863 if (idx >= 0 && idx < nWeightsPerEntity_)
864 entityDegreeWeight_[idx] =
true;
866 std::cout <<
"WARNING: invalid entity weight index, " << idx <<
", ignored"
870 template <
typename User>
873 std::string fn(
" PamgenMesh ");
874 std::cout << me << fn
875 <<
" dim = " << dimension_
876 <<
" nodes = " << num_nodes_
877 <<
" nelems = " << num_elem_
880 for (
int i = 0; i < num_elem_; i++) {
881 std::cout << me << fn << i
882 <<
" Elem " << element_num_map_[i]
884 for (
int j = 0; j < dimension_; j++)
885 std::cout << Acoords_[i + j * num_elem_] <<
" ";
886 std::cout << std::endl;
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]
894 for (
int j = eStart_[i]; j < eStart_[i+1]; j++)
895 std::cout << eAdj_[j] <<
" ";
896 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...
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.
Defines the MeshAdapter interface.
MeshAdapter defines the interface for mesh input.
map_t::global_ordinal_type gno_t
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
size_t getLocalNum2ndAdjs(MeshEntityType sourcetarget, MeshEntityType through) const
if avail2ndAdjs(), returns the number of second adjacencies on this process.
std::map< gno_t, gno_t > MapType
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
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.
bool availAdjs(MeshEntityType source, MeshEntityType target) const
Returns whether a first adjacency combination is available.
This file defines the StridedData class.