Zoltan2
Zoltan2_PamgenMeshAdapter.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 //
00003 // ***********************************************************************
00004 //
00005 //   Zoltan2: A package of combinatorial algorithms for scientific computing
00006 //                  Copyright 2012 Sandia Corporation
00007 //
00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Karen Devine      (kddevin@sandia.gov)
00039 //                    Erik Boman        (egboman@sandia.gov)
00040 //                    Siva Rajamanickam (srajama@sandia.gov)
00041 //
00042 // ***********************************************************************
00043 //
00044 // @HEADER
00045 
00050 #ifndef _ZOLTAN2_PAMGENMESHADAPTER_HPP_
00051 #define _ZOLTAN2_PAMGENMESHADAPTER_HPP_
00052 
00053 #include <Zoltan2_MeshAdapter.hpp>
00054 #include <Zoltan2_StridedData.hpp>
00055 #include <vector>
00056 
00057 #include <pamgen_im_exodusII.h>
00058 #include "pamgen_im_ne_nemesisI.h"
00059 
00060 namespace Zoltan2 {
00061 
00088 template <typename User>
00089   class PamgenMeshAdapter: public MeshAdapter<User> {
00090 
00091 public:
00092 
00093   typedef typename InputTraits<User>::scalar_t    scalar_t;
00094   typedef typename InputTraits<User>::lno_t    lno_t;
00095   typedef typename InputTraits<User>::gno_t    gno_t;
00096   typedef typename InputTraits<User>::zgid_t    zgid_t;
00097   typedef typename InputTraits<User>::part_t   part_t;
00098   typedef typename InputTraits<User>::node_t   node_t;
00099   typedef MeshAdapter<User>       base_adapter_t;
00100   typedef User user_t;
00101 
00109   PamgenMeshAdapter(const Comm<int> &comm, std::string typestr="region");
00110 
00111   void print(int);
00112 
00114   // The MeshAdapter interface.
00115   // This is the interface that would be called by a model or a problem .
00117 
00118   size_t getLocalNumOf(MeshEntityType etype) const
00119   {
00120     if ((MESH_REGION == etype && 3 == dimension_) ||
00121   (MESH_FACE == etype && 2 == dimension_)) {
00122       return num_elem_;
00123     }
00124 
00125     if (MESH_VERTEX == etype) {
00126       return num_nodes_;
00127     }
00128 
00129     return 0;
00130   }
00131    
00132   void getIDsViewOf(MeshEntityType etype, const zgid_t *&Ids) const
00133   {
00134     if ((MESH_REGION == etype && 3 == dimension_) ||
00135   (MESH_FACE == etype && 2 == dimension_)) {
00136       Ids = element_num_map_;
00137     }
00138 
00139     else if (MESH_VERTEX == etype) {
00140       Ids = node_num_map_;
00141     }
00142 
00143     else Ids = NULL;
00144   }
00145 
00146   void getWeightsViewOf(MeshEntityType etype, const scalar_t *&weights,
00147       int &stride, int idx = 0) const
00148   {
00149     weights = NULL;
00150     stride = 0;
00151   }
00152 
00153   int getDimension() const { return dimension_; }
00154 
00155   void getCoordinatesViewOf(MeshEntityType etype, const scalar_t *&coords,
00156           int &stride, int dim) const {
00157     if ((MESH_REGION == etype && 3 == dimension_) ||
00158          (MESH_FACE == etype && 2 == dimension_)) {
00159       if (dim == 0) {
00160   coords = Acoords_;
00161       } else if (dim == 1) {
00162   coords = Acoords_ + num_elem_;
00163       } else if (dim == 2) {
00164   coords = Acoords_ + 2 * num_elem_;
00165       }
00166       stride = 1;
00167     } else if (MESH_REGION == etype && 2 == dimension_) {
00168       coords = NULL;
00169       stride = 0;
00170     } else if (MESH_VERTEX == etype) {
00171       if (dim == 0) {
00172   coords = coords_;
00173       } else if (dim == 1) {
00174   coords = coords_ + num_nodes_;
00175       } else if (dim == 2) {
00176   coords = coords_ + 2 * num_nodes_;
00177       }
00178       stride = 1;
00179     } else {
00180       coords = NULL;
00181       stride = 0;
00182       Z2_THROW_NOT_IMPLEMENTED_IN_ADAPTER
00183     }
00184   }
00185 
00186   bool availAdjs(MeshEntityType source, MeshEntityType target) const {
00187     if ((MESH_REGION == source && MESH_VERTEX == target && 3 == dimension_) ||
00188   (MESH_FACE == source && MESH_VERTEX == target && 2 == dimension_)) {
00189       return TRUE;
00190     }
00191 
00192     return false;
00193   }
00194 
00195   size_t getLocalNumAdjs(MeshEntityType source, MeshEntityType target) const
00196   {
00197     if (availAdjs(source, target)) {
00198       return tnoct_;
00199     }
00200     
00201     return 0;
00202   }
00203 
00204   void getAdjsView(MeshEntityType source, MeshEntityType target,
00205        const lno_t *&offsets, const zgid_t *& adjacencyIds) const
00206   {
00207     if ((MESH_REGION == source && MESH_VERTEX == target && 3 == dimension_) ||
00208   (MESH_FACE == source && MESH_VERTEX == target && 2 == dimension_)) {
00209       offsets = elemOffsets_;
00210       adjacencyIds = elemToNode_;
00211     } else if (MESH_REGION == source && 2 == dimension_) {
00212       offsets = NULL;
00213       adjacencyIds = NULL;
00214     } else {
00215       offsets = NULL;
00216       adjacencyIds = NULL;
00217       Z2_THROW_NOT_IMPLEMENTED_IN_ADAPTER
00218     }
00219   }
00220 
00221   bool avail2ndAdjs(MeshEntityType sourcetarget, MeshEntityType through) const
00222   {
00223     if (through == MESH_VERTEX) {
00224       if (sourcetarget == MESH_REGION && dimension_ == 3) return true;
00225       if (sourcetarget == MESH_FACE && dimension_ == 2) return true;
00226     }
00227     return false;
00228   }
00229 
00230   size_t getLocalNum2ndAdjs(MeshEntityType sourcetarget, 
00231           MeshEntityType through) const
00232   {
00233     if (avail2ndAdjs(sourcetarget, through)) {
00234       return nadj_;
00235     }
00236 
00237     return 0;
00238   }
00239 
00240   void get2ndAdjsView(MeshEntityType sourcetarget, MeshEntityType through, 
00241           const lno_t *&offsets, const zgid_t *& adjacencyIds) const
00242   {
00243     if (avail2ndAdjs(sourcetarget, through)) {
00244       offsets = start_;
00245       adjacencyIds = adj_;
00246     } else {
00247       offsets = NULL;
00248       adjacencyIds = NULL;
00249       Z2_THROW_NOT_IMPLEMENTED_IN_ADAPTER
00250     }
00251   }
00252 
00253 private:
00254   int dimension_, num_nodes_, num_elem_;
00255   zgid_t *element_num_map_, *node_num_map_;
00256   int *elemToNode_, tnoct_, *elemOffsets_;
00257   double *coords_, *Acoords_;
00258   lno_t *start_;
00259   zgid_t *adj_;
00260   size_t nadj_;
00261 };
00262 
00264 // Definitions
00266 
00267 static
00268 ssize_t in_list(const int value, size_t count, int *vector)
00269 {
00270   for(size_t i=0; i < count; i++) {
00271     if(vector[i] == value)
00272       return i;
00273   }
00274   return -1;
00275 }
00276 
00277 template <typename User>
00278 PamgenMeshAdapter<User>::PamgenMeshAdapter(const Comm<int> &comm,
00279              std::string typestr):
00280   dimension_(0)
00281 {
00282   this->setEntityTypes(typestr, "vertex", "vertex");
00283 
00284   int error = 0;
00285   char title[100];
00286   int exoid = 0;
00287   int num_elem_blk, num_node_sets, num_side_sets;
00288   error += im_ex_get_init(exoid, title, &dimension_,
00289         &num_nodes_, &num_elem_, &num_elem_blk,
00290         &num_node_sets, &num_side_sets);
00291 
00292   coords_ = new double [num_nodes_ * dimension_];
00293 
00294   error += im_ex_get_coord(exoid, coords_, coords_ + num_nodes_,
00295          coords_ + 2 * num_nodes_);
00296 
00297   element_num_map_ = new int [num_elem_];
00298   error += im_ex_get_elem_num_map(exoid, element_num_map_);
00299 
00300   node_num_map_ = new int [num_nodes_];
00301   error += im_ex_get_node_num_map(exoid, node_num_map_);
00302 
00303   int *elem_blk_ids       = new int [num_elem_blk];
00304   error += im_ex_get_elem_blk_ids(exoid, elem_blk_ids);
00305 
00306   int *num_nodes_per_elem = new int [num_elem_blk];
00307   int *num_attr           = new int [num_elem_blk];
00308   int *num_elem_this_blk  = new int [num_elem_blk];
00309   char **elem_type        = new char * [num_elem_blk];
00310   int **connect           = new int * [num_elem_blk];
00311 
00312   for(int i = 0; i < num_elem_blk; i++){
00313     elem_type[i] = new char [MAX_STR_LENGTH + 1];
00314     error += im_ex_get_elem_block(exoid, elem_blk_ids[i], elem_type[i],
00315           (int*)&(num_elem_this_blk[i]),
00316           (int*)&(num_nodes_per_elem[i]),
00317           (int*)&(num_attr[i]));
00318     delete[] elem_type[i];
00319   }
00320 
00321   delete[] elem_type;
00322   elem_type = NULL;
00323   delete[] num_attr;
00324   num_attr = NULL;
00325   Acoords_ = new double [num_elem_ * dimension_];
00326   int a = 0;
00327   std::vector<std::vector<int> > sur_elem;
00328   sur_elem.resize(num_nodes_);
00329 
00330   for(int b = 0; b < num_elem_blk; b++) {
00331     connect[b] = new int [num_nodes_per_elem[b]*num_elem_this_blk[b]];
00332     error += im_ex_get_elem_conn(exoid, elem_blk_ids[b], connect[b]);
00333 
00334     for(int i = 0; i < num_elem_this_blk[b]; i++) {
00335       Acoords_[a] = 0;
00336       Acoords_[num_elem_ + a] = 0;
00337 
00338       if (3 == dimension_) {
00339   Acoords_[2 * num_elem_ + a] = 0;
00340       }
00341 
00342       for(int j = 0; j < num_nodes_per_elem[b]; j++) {
00343   int node = connect[b][i * num_nodes_per_elem[b] + j] - 1;
00344   Acoords_[a] += coords_[node];
00345   Acoords_[num_elem_ + a] += coords_[num_nodes_ + node];
00346 
00347   if(3 == dimension_) {
00348     Acoords_[2 * num_elem_ + a] += coords_[2 * num_nodes_ + node];
00349   }
00350 
00351   /*
00352    * in the case of degenerate elements, where a node can be
00353    * entered into the connect table twice, need to check to
00354    * make sure that this element is not already listed as
00355    * surrounding this node
00356    */
00357   if (sur_elem[node].empty() ||
00358       element_num_map_[a] != sur_elem[node][sur_elem[node].size()-1]) {
00359     /* Add the element to the list */
00360     sur_elem[node].push_back(element_num_map_[a]);
00361   }
00362       }
00363 
00364       Acoords_[a] /= num_nodes_per_elem[b];
00365       Acoords_[num_elem_ + a] /= num_nodes_per_elem[b];
00366 
00367       if(3 == dimension_) {
00368   Acoords_[2 * num_elem_ + a] /= num_nodes_per_elem[b];
00369       }
00370 
00371       a++;
00372     }
00373 
00374   }
00375 
00376   delete[] elem_blk_ids;
00377   elem_blk_ids = NULL;
00378   int nnodes_per_elem = num_nodes_per_elem[0];
00379   elemToNode_ = new int [num_elem_ * nnodes_per_elem];
00380   int telct = 0;
00381   elemOffsets_ = new int [num_elem_];
00382   tnoct_ = 0;
00383   int **reconnect = new int * [num_elem_];
00384   size_t max_nsur = 0;
00385 
00386   for (int b = 0; b < num_elem_blk; b++) {
00387     for (int i = 0; i < num_elem_this_blk[b]; i++) {
00388       elemOffsets_[telct] = tnoct_;
00389       reconnect[telct] = new int [num_nodes_per_elem[b]];
00390 
00391       for (int j = 0; j < num_nodes_per_elem[b]; j++) {
00392   elemToNode_[tnoct_]=
00393     node_num_map_[connect[b][i*num_nodes_per_elem[b] + j]-1];
00394   reconnect[telct][j] = connect[b][i*num_nodes_per_elem[b] + j];
00395   ++tnoct_;
00396       }
00397 
00398       ++telct;
00399     }
00400   }
00401 
00402   delete[] num_nodes_per_elem;
00403   num_nodes_per_elem = NULL;
00404   delete[] num_elem_this_blk;
00405   num_elem_this_blk = NULL;
00406 
00407   for(int b = 0; b < num_elem_blk; b++) {
00408     delete[] connect[b];
00409   }
00410 
00411   delete[] connect;
00412   connect = NULL;
00413 
00414   int max_side_nodes = nnodes_per_elem;
00415   int *side_nodes = new int [max_side_nodes];
00416   int *mirror_nodes = new int [max_side_nodes];
00417 
00418   /* Allocate memory necessary for the adjacency */
00419   start_ = new lno_t [num_elem_+1];
00420   std::vector<int> adj;
00421 
00422   for (int i=0; i < max_side_nodes; i++) {
00423     side_nodes[i]=-999;
00424     mirror_nodes[i]=-999;
00425   }
00426 
00427   /* Find the adjacency for a nodal based decomposition */
00428   nadj_ = 0;
00429   for(int ncnt=0; ncnt < num_nodes_; ncnt++) {
00430     if(sur_elem[ncnt].empty()) {
00431       printf("WARNING: Node = %d has no elements\n", ncnt+1);
00432     } else {
00433       size_t nsur = sur_elem[ncnt].size();
00434       if (nsur > max_nsur)
00435   max_nsur = nsur;
00436     }
00437   }
00438 
00439   int nprocs = comm.getSize();
00440 
00441   if (nprocs > 1) {
00442     int neid = 0, num_internal_nodes, num_border_nodes, num_external_nodes;
00443     int num_internal_elems, num_border_elems, num_node_cmaps, num_elem_cmaps;
00444     int proc = 0;
00445     error += im_ne_get_loadbal_param(neid, &num_internal_nodes,
00446              &num_border_nodes, &num_external_nodes,
00447              &num_internal_elems, &num_border_elems,
00448              &num_node_cmaps, &num_elem_cmaps, proc);
00449 
00450     int *node_cmap_ids = new int [num_node_cmaps];
00451     int *node_cmap_node_cnts = new int [num_node_cmaps];
00452     int *elem_cmap_ids = new int [num_elem_cmaps];
00453     int *elem_cmap_elem_cnts = new int [num_elem_cmaps];
00454     error += im_ne_get_cmap_params(neid, node_cmap_ids, node_cmap_node_cnts,
00455            elem_cmap_ids, elem_cmap_elem_cnts, proc);
00456     delete[] elem_cmap_ids;
00457     elem_cmap_ids = NULL;
00458     delete[] elem_cmap_elem_cnts;
00459     elem_cmap_elem_cnts = NULL;
00460 
00461     int **node_ids = new int * [num_node_cmaps];
00462     int **node_proc_ids = new int * [num_node_cmaps];
00463     for(int j = 0; j < num_node_cmaps; j++) {
00464       node_ids[j] = new int [node_cmap_node_cnts[j]];
00465       node_proc_ids[j] = new int [node_cmap_node_cnts[j]];
00466       error += im_ne_get_node_cmap(neid, node_cmap_ids[j], node_ids[j],
00467            node_proc_ids[j], proc);
00468     }
00469     delete[] node_cmap_ids;
00470     node_cmap_ids = NULL;
00471     int *sendCount = new int [nprocs];
00472     int *recvCount = new int [nprocs];
00473 
00474     // Post receives
00475     RCP<CommRequest<int> >*requests=new RCP<CommRequest<int> >[num_node_cmaps];
00476     for (int cnt = 0, i = 0; i < num_node_cmaps; i++) {
00477       try {
00478   requests[cnt++] =
00479     Teuchos::ireceive<int,int>(comm,
00480              rcp(&(recvCount[node_proc_ids[i][0]]),
00481            false),
00482              node_proc_ids[i][0]);
00483       }
00484       Z2_FORWARD_EXCEPTIONS;
00485     }
00486 
00487     Teuchos::barrier<int>(comm);
00488     size_t totalsend = 0;
00489 
00490     for(int j = 0; j < num_node_cmaps; j++) {
00491       sendCount[node_proc_ids[j][0]] = 1;
00492       for(int i = 0; i < node_cmap_node_cnts[j]; i++) {
00493   sendCount[node_proc_ids[j][i]] += sur_elem[node_ids[j][i]-1].size()+2;
00494       }
00495       totalsend += sendCount[node_proc_ids[j][0]];
00496     }
00497 
00498     // Send data; can use readySend since receives are posted.
00499     for (int i = 0; i < num_node_cmaps; i++) {
00500       try {
00501   Teuchos::readySend<int,int>(comm, sendCount[node_proc_ids[i][0]],
00502             node_proc_ids[i][0]);
00503       }
00504       Z2_FORWARD_EXCEPTIONS;
00505     }
00506 
00507     // Wait for messages to return.
00508     try {
00509       Teuchos::waitAll<int>(comm, arrayView(requests, num_node_cmaps));
00510     }
00511     Z2_FORWARD_EXCEPTIONS;
00512 
00513     delete [] requests;
00514 
00515     // Allocate the receive buffer.
00516     size_t totalrecv = 0;
00517     int maxMsg = 0;
00518     int nrecvranks = 0;
00519     for(int i = 0; i < num_node_cmaps; i++) {
00520       if (recvCount[node_proc_ids[i][0]] > 0) {
00521   totalrecv += recvCount[node_proc_ids[i][0]];
00522   nrecvranks++;
00523   if (recvCount[node_proc_ids[i][0]] > maxMsg)
00524     maxMsg = recvCount[node_proc_ids[i][0]];
00525       }
00526     }
00527 
00528     int *rbuf = NULL;
00529     if (totalrecv) rbuf = new int[totalrecv];
00530 
00531     requests = new RCP<CommRequest<int> > [nrecvranks];
00532 
00533     // Error checking for memory and message size.
00534     int OK[2] = {1,1};
00535     // OK[0] -- true/false indicating whether each message size fits in an int
00536     //          (for MPI).
00537     // OK[1] -- true/false indicating whether memory allocs are OK
00538     int gOK[2]; // For global reduce of OK.
00539 
00540     if (size_t(maxMsg) * sizeof(int) > INT_MAX) OK[0] = false;
00541     if (totalrecv && !rbuf) OK[1] = 0;
00542     if (!requests) OK[1] = 0;
00543 
00544     // Post receives
00545 
00546     size_t offset = 0;
00547 
00548     if (OK[0] && OK[1]) {
00549       int rcnt = 0;
00550       for (int i = 0; i < num_node_cmaps; i++) {
00551   if (recvCount[node_proc_ids[i][0]]) {
00552     try {
00553       requests[rcnt++] =
00554         Teuchos::
00555         ireceive<int,int>(comm,
00556         Teuchos::arcp(&rbuf[offset], 0,
00557                 recvCount[node_proc_ids[i][0]],
00558                 false),
00559         node_proc_ids[i][0]);
00560     }
00561     Z2_FORWARD_EXCEPTIONS;
00562   }
00563   offset += recvCount[node_proc_ids[i][0]];
00564       }
00565     }
00566 
00567     delete[] recvCount;
00568 
00569     // Use barrier for error checking
00570     Teuchos::reduceAll<int>(comm, Teuchos::REDUCE_MIN, 2, OK, gOK);
00571     if (!gOK[0] || !gOK[1]) {
00572       delete [] rbuf;
00573       delete [] requests;
00574       if (!gOK[0])
00575   throw std::runtime_error("Max single message length exceeded");
00576       else
00577   throw std::bad_alloc();
00578     }
00579 
00580     int *sbuf = NULL;
00581     if (totalsend) sbuf = new int[totalsend];
00582     a = 0;
00583 
00584     for(int j = 0; j < num_node_cmaps; j++) {
00585       sbuf[a++] = node_cmap_node_cnts[j];
00586       for(int i = 0; i < node_cmap_node_cnts[j]; i++) {
00587   sbuf[a++] = node_num_map_[node_ids[j][i]-1];
00588   sbuf[a++] = sur_elem[node_ids[j][i]-1].size();
00589   for(size_t ecnt=0; ecnt < sur_elem[node_ids[j][i]-1].size(); ecnt++) {
00590     sbuf[a++] = sur_elem[node_ids[j][i]-1][ecnt];
00591   }
00592       }
00593     }
00594 
00595     delete[] node_cmap_node_cnts;
00596     node_cmap_node_cnts = NULL;
00597 
00598     for(int j = 0; j < num_node_cmaps; j++) {
00599       delete[] node_ids[j];
00600     }
00601 
00602     delete[] node_ids;
00603     node_ids = NULL;
00604     ArrayRCP<int> sendBuf;
00605 
00606     if (totalsend)
00607       sendBuf = ArrayRCP<int>(sbuf, 0, totalsend, true);
00608     else
00609       sendBuf = Teuchos::null;
00610 
00611     // Send data; can use readySend since receives are posted.
00612     offset = 0;
00613     for (int i = 0; i < num_node_cmaps; i++) {
00614       if (sendCount[node_proc_ids[i][0]]) {
00615   try{
00616     Teuchos::readySend<int,
00617       int>(comm,
00618      Teuchos::arrayView(&sendBuf[offset],
00619             sendCount[node_proc_ids[i][0]]),
00620      node_proc_ids[i][0]);
00621   }
00622   Z2_FORWARD_EXCEPTIONS;
00623       }
00624       offset += sendCount[node_proc_ids[i][0]];
00625     }
00626 
00627     for(int j = 0; j < num_node_cmaps; j++) {
00628       delete[] node_proc_ids[j];
00629     }
00630 
00631     delete[] node_proc_ids;
00632     node_proc_ids = NULL;
00633     delete[] sendCount;
00634 
00635     // Wait for messages to return.
00636     try{
00637       Teuchos::waitAll<int>(comm, Teuchos::arrayView(requests, nrecvranks));
00638     }
00639     Z2_FORWARD_EXCEPTIONS;
00640 
00641     delete[] requests;
00642     a = 0;
00643 
00644     for (int i = 0; i < num_node_cmaps; i++) {
00645       int num_nodes_this_processor = rbuf[a++];
00646 
00647       for (int j = 0; j < num_nodes_this_processor; j++) {
00648   int this_node = rbuf[a++];
00649   int num_elem_this_node = rbuf[a++];
00650 
00651   for (int ncnt = 0; ncnt < num_nodes_; ncnt++) {
00652     if (node_num_map_[ncnt] == this_node) {
00653       for (int ecnt = 0; ecnt < num_elem_this_node; ecnt++) {
00654         sur_elem[ncnt].push_back(rbuf[a++]);
00655       }
00656     }
00657   }
00658       }
00659     }
00660 
00661     delete[] rbuf;
00662   }
00663 
00664   for(int ecnt=0; ecnt < num_elem_; ecnt++) {
00665     start_[ecnt] = nadj_;
00666     int nnodes = nnodes_per_elem;
00667     for(int ncnt=0; ncnt < nnodes; ncnt++) {
00668       int node = reconnect[ecnt][ncnt]-1;
00669       for(size_t i=0; i < sur_elem[node].size(); i++) {
00670   int entry = sur_elem[node][i];
00671 
00672   if(element_num_map_[ecnt] != entry &&
00673      in_list(entry,
00674        adj.size()-start_[ecnt],
00675        &adj[start_[ecnt]]) < 0) {
00676     adj.push_back(entry);
00677     nadj_++;
00678   }
00679       }
00680     }
00681   }
00682 
00683   for(int b = 0; b < num_elem_; b++) {
00684     delete[] reconnect[b];
00685   }
00686 
00687   delete[] reconnect;
00688   reconnect = NULL;
00689   start_[num_elem_] = nadj_;
00690 
00691   adj_ = new zgid_t [nadj_];
00692 
00693   for (size_t i=0; i < nadj_; i++) {
00694     adj_[i] = adj[i];
00695   }
00696 
00697   delete[] side_nodes;
00698   side_nodes = NULL;
00699   delete[] mirror_nodes;
00700   mirror_nodes = NULL;
00701 }
00702 
00703 template <typename User>
00704 void PamgenMeshAdapter<User>::print(int me)
00705 {
00706   std::string fn(" PamgenMesh ");
00707   std::cout << me << fn
00708             << " dim = " << dimension_
00709             << " nnodes = " << num_nodes_
00710             << " nelems = " << num_elem_
00711             << std::endl;
00712 
00713   for (int i = 0; i < num_elem_; i++) {
00714     std::cout << me << fn << i 
00715               << " Elem " << element_num_map_[i]
00716               << " Coords: ";
00717     for (int j = 0; j < dimension_; j++)
00718       std::cout << Acoords_[i + j * num_elem_] << " ";
00719     std::cout << std::endl;
00720   }
00721 
00722   for (int i = 0; i < num_elem_; i++) {
00723     std::cout << me << fn << i 
00724               << " Elem " << element_num_map_[i]
00725               << " Graph: ";
00726     for (int j = start_[i]; j < start_[i+1]; j++)
00727       std::cout << adj_[j] << " ";
00728     std::cout << std::endl;
00729   }
00730 }
00731   
00732 }  //namespace Zoltan2
00733   
00734 #endif