SundanceHNMesh2D.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 /*
00042  * SundanceHNMesh2D.cpp
00043  *
00044  *  Created on: April 30, 2009
00045  *      Author: benk
00046  */
00047 
00048 #include "SundanceHNMesh2D.hpp"
00049 
00050 #include "SundanceMeshType.hpp"
00051 #include "SundanceCellJacobianBatch.hpp"
00052 #include "SundanceMaximalCofacetBatch.hpp"
00053 #include "SundanceMeshSource.hpp"
00054 #include "SundanceDebug.hpp"
00055 #include "SundanceOut.hpp"
00056 #include "PlayaMPIContainerComm.hpp"
00057 #include "Teuchos_Time.hpp"
00058 #include "Teuchos_TimeMonitor.hpp"
00059 #include "SundanceObjectWithVerbosity.hpp"
00060 #include "SundanceCollectiveExceptionCheck.hpp"
00061 
00062 #ifdef _MSC_VER
00063 static double log2(double x)
00064 {  
00065     return log(x)/log(2.0);  
00066 }
00067 #endif
00068 
00069 using namespace Sundance;
00070 using namespace Teuchos;
00071 using namespace std;
00072 using Playa::MPIComm;
00073 using Playa::MPIContainerComm;
00074 
00075 int HNMesh2D::offs_Points_x_[4] = {0, 1, 0, 1};
00076 
00077 int HNMesh2D::offs_Points_y_[4] = {0, 0, 1, 1};
00078 
00079 int HNMesh2D::edge_Points_localIndex[4][2] = { {0,1} , {0,2} , {1,3} , {2,3} };
00080 
00081 
00082 HNMesh2D::HNMesh2D(int dim, const MPIComm& comm ,
00083       const MeshEntityOrder& order)
00084 : MeshBase(dim, comm , order),_dimension(dim), _comm(comm)
00085 {
00086   setVerb(0);
00087   // get the number of processors
00088   nrProc_ = MPIComm::world().getNProc();
00089   myRank_ = MPIComm::world().getRank();
00090   //------ Point storage ----
00091   points_.resize(0);
00092     nrElem_.resize(3,0);
00093   nrElemOwned_.resize(3,0);
00094   //----- Facets -----
00095     cellsPoints_.resize(0);
00096     cellsEdges_.resize(0);
00097     isCellOut_.resize(0);
00098   edgePoints_.resize(0);
00099   edgeVertex_.resize(0);
00100   // ----- MaxCofacets ----
00101   edgeMaxCoF_.resize(0);
00102     pointMaxCoF_.resize(0);
00103     //------ Element (processor) ownership -----
00104   elementOwner_.resize(3); elementOwner_[0].resize(0); elementOwner_[1].resize(0); elementOwner_[2].resize(0);
00105   // ------------- different boundary ---------
00106     edgeIsProcBonudary_.resize(0);
00107     edgeIsMeshDomainBonudary_.resize(0);
00108     //---- hierarchical storage -----
00109     indexInParent_.resize(0);
00110     parentCellLID_.resize(0);
00111   cellLevel_.resize(0);
00112   isCellLeaf_.resize(0);
00113   // ---- "hanging" info storage ---
00114   isPointHanging_.resize(0);
00115   isEdgeHanging_.resize(0);
00116   // ---- hanging element and refinement (temporary) storage ---
00117   hangElmStore_.resize(2);
00118   hangElmStore_[0] = Hashtable< int, Array<int> >();
00119   hangElmStore_[1] = Hashtable< int, Array<int> >();
00120   refineCell_.resize(0);
00121     // set the leaf counter to zero
00122   nrCellLeafGID_ = 0; nrEdgeLeafGID_ = 0; nrVertexLeafGID_ = 0;
00123   nrVertexLeafLID_ = 0; nrCellLeafLID_ = 0; nrEdgeLeafLID_ = 0;
00124 }
00125 
00126 int HNMesh2D::numCells(int dim) const  {
00127   SUNDANCE_MSG3(verb(),"HNMesh2D::numCells(int dim):   dim:" << dim );
00128   switch (dim){
00129   case 0: return nrVertexLeafLID_;
00130   case 1: return nrEdgeLeafLID_;
00131   case 2: return nrCellLeafLID_;
00132   }
00133   return 0;
00134 }
00135 
00136 Point HNMesh2D::nodePosition(int i) const {
00137   SUNDANCE_MSG3(verb(),"HNMesh2D::nodePosition(int i)   i:"<< i);
00138     // point do not need leaf indexing
00139   return points_[vertexLeafToLIDMapping_[i]];
00140 }
00141 
00142 const double* HNMesh2D::nodePositionView(int i) const {
00143   SUNDANCE_MSG3(verb(),"HNMesh2D::nodePositionView(int i)   i:" << i);
00144   //SUNDANCE_VERB_HIGH("nodePosition(int i)");
00145   return &(points_[vertexLeafToLIDMapping_[i]][0]);;
00146 }
00147 
00148 void HNMesh2D::getJacobians(int cellDim, const Array<int>& cellLID,
00149                           CellJacobianBatch& jBatch) const
00150 {
00151     SUNDANCE_MSG3(verb(),"HNMesh2D::getJacobians  cellDim:"<<cellDim<<" _x:"<<_ofs_x<<" _y:"<<_ofs_y);
00152     SUNDANCE_VERB_HIGH("getJacobians()");
00153     TEUCHOS_TEST_FOR_EXCEPTION(cellDim < 0 || cellDim > spatialDim(), std::logic_error,
00154       "cellDim=" << cellDim << " is not in expected range [0, " << spatialDim() << "]");
00155     int nCells = cellLID.size();
00156     int LID;
00157     Point pnt(0.0,0.0);
00158     jBatch.resize(cellLID.size(), spatialDim(), cellDim);
00159     if (cellDim < spatialDim()) // they need the Jacobian of a lower dinemsional element
00160     {
00161        for (int i=0; i<nCells; i++)
00162         {
00163           double* detJ = jBatch.detJ(i);
00164           switch(cellDim)
00165           {
00166             case 0: *detJ = 1.0;
00167               break;
00168             case 1:
00169           LID = edgeLeafToLIDMapping_[cellLID[i]];
00170             pnt = (points_[edgePoints_[LID][1]] - points_[edgePoints_[LID][0]]);
00171               *detJ = sqrt(pnt * pnt); // the length of the edge
00172             break;
00173             default:
00174               TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "impossible switch value "  "cellDim=" << cellDim << " in HNMesh2D::getJacobians()");
00175           }
00176         }
00177     }else{ // they request the complete Jacoby matrix for this bunch of elements
00178         //Array<double> J(cellDim*cellDim);
00179         SUNDANCE_VERB_HIGH("cellDim == spatialDim()");
00180         for (unsigned int i=0; i<(unsigned int)cellLID.size(); i++)
00181         {
00182           double* J = jBatch.jVals(i);
00183           switch(cellDim)
00184           {
00185             case 2:
00186           LID = cellLeafToLIDMapping_[cellLID[i]];
00187           // Jacobi for unstructured quad this will not work, but because of linear Jacoby we only have structured quads
00188               J[0] = points_[cellsPoints_[LID][1]][0] - points_[cellsPoints_[LID][0]][0];
00189               J[1] = 0.0;
00190               J[2] = 0.0;
00191               J[3] = points_[cellsPoints_[LID][2]][1] - points_[cellsPoints_[LID][0]][1];
00192             SUNDANCE_MSG3(verb() , "HNMesh2D::getJacobians X:" << J[0] << " Y:" << J[3] );
00193             break;
00194             default:
00195               TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "impossible switch value " "cellDim=" << cellDim << " in HNMesh2D::getJacobians()");
00196           }
00197         }
00198     }
00199 }
00200 
00201 void HNMesh2D::getCellDiameters(int cellDim, const Array<int>& cellLID,
00202                               Array<double>& cellDiameters) const {
00203    TEUCHOS_TEST_FOR_EXCEPTION(cellDim < 0 || cellDim > spatialDim(), std::logic_error,
00204       "cellDim=" << cellDim << " is not in expected range [0, " << spatialDim() << "]");
00205    SUNDANCE_VERB_HIGH("getCellDiameters()");
00206     cellDiameters.resize(cellLID.size());
00207     Point pnt(0.0,0.0);
00208     int LID;
00209     if (cellDim < spatialDim())
00210     {
00211     SUNDANCE_MSG3(verb(),"HNMesh2D::getCellDiameters(), cellDim < spatialDim() ");
00212       for (unsigned int i=0; i<(unsigned int)cellLID.size(); i++)
00213       {
00214         switch(cellDim)
00215         {
00216           case 0:
00217                cellDiameters[i] = 1.0;
00218             break;
00219           case 1:  //length of the edge
00220           LID = edgeLeafToLIDMapping_[cellLID[i]];
00221             pnt = (points_[edgePoints_[LID][1]] - points_[edgePoints_[LID][0]]);
00222             cellDiameters[i] = sqrt(pnt * pnt); // the length of the edge
00223           break;
00224           default:
00225             TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "impossible switch value "  "cellDim=" << cellDim << " in HNMesh2D::getCellDiameters()");
00226         }
00227       }
00228     }
00229     else
00230     {
00231     SUNDANCE_MSG3(verb(),"HNMesh2D::getCellDiameters(), cellDim == spatialDim() ");
00232       for (unsigned int i=0; i<(unsigned int)cellLID.size(); i++)
00233       {
00234         switch(cellDim)
00235         {
00236           case 2:
00237             LID = cellLeafToLIDMapping_[cellLID[i]];
00238             pnt = points_[cellsPoints_[LID][3]] - points_[cellsPoints_[LID][0]];
00239             cellDiameters[i] = sqrt(pnt * pnt);
00240           break;
00241           default:
00242             TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "impossible switch value "
00243              "cellDim=" << cellDim  << " in HNMesh2D::getCellDiameters()");
00244         }
00245       }
00246     }
00247 }
00248 
00249 void HNMesh2D::pushForward(int cellDim, const Array<int>& cellLID,
00250                          const Array<Point>& refQuadPts,
00251                          Array<Point>& physQuadPts) const {
00252 
00253     SUNDANCE_MSG3(verb(),"HNMesh2D::pushForward cellDim:"<<cellDim);
00254     TEUCHOS_TEST_FOR_EXCEPTION(cellDim < 0 || cellDim > spatialDim(), std::logic_error,
00255       "cellDim=" << cellDim << " is not in expected range [0, " << spatialDim() << "]");
00256 
00257     int nQuad = refQuadPts.size();
00258     Point pnt( 0.0 , 0.0 );
00259     Point pnt1( 0.0 , 0.0 );
00260 
00261     if (physQuadPts.size() > 0) physQuadPts.resize(0);
00262     physQuadPts.reserve(cellLID.size() * refQuadPts.size());
00263     for (unsigned int i=0; i<(unsigned int)cellLID.size(); i++)
00264     {
00265       switch(cellDim)
00266       {
00267         case 0: // integrate one point
00268            physQuadPts.append(pnt);
00269           break;
00270         case 1:{ // integrate on one line
00271            int LID = edgeLeafToLIDMapping_[cellLID[i]];
00272              pnt = points_[edgePoints_[LID][0]];
00273              pnt1 = points_[edgePoints_[LID][1]] - points_[edgePoints_[LID][0]];
00274                for (int q=0; q<nQuad; q++) {
00275                  physQuadPts.append(pnt + (pnt1)*refQuadPts[q][0]);
00276             }
00277         break;}
00278         case 2:{
00279                int LID = cellLeafToLIDMapping_[cellLID[i]];
00280                pnt = points_[cellsPoints_[LID][0]];
00281                // this works only for structured, but we only work on structured quads
00282                pnt1 = points_[cellsPoints_[LID][3]] - points_[cellsPoints_[LID][0]];
00283              for (int q=0; q<nQuad; q++) {
00284                   physQuadPts.append( pnt + Point( refQuadPts[q][0] * pnt1[0] , refQuadPts[q][1] * pnt1[1] ) );
00285              }
00286         break;}
00287         default:
00288         TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "impossible switch value " "in HNMesh2D::getJacobians()");
00289       }
00290     }
00291 }
00292 
00293 int HNMesh2D::ownerProcID(int cellDim, int cellLID) const  {
00294    int ID = -1;
00295    if (cellDim == 0) ID = vertexLeafToLIDMapping_[cellLID];
00296      if (cellDim == 1) ID = edgeLeafToLIDMapping_[cellLID];
00297      if (cellDim == 2) ID = cellLeafToLIDMapping_[cellLID];
00298      SUNDANCE_MSG3(verb() , " HNMesh2D::ownerProcID ,cellDim:" << cellDim << ", cellLID:"
00299          << cellLID <<" ,ID:" << ID << ", ret:"<< elementOwner_[cellDim][ID] );
00300    return elementOwner_[cellDim][ID];
00301 }
00302 
00303 
00304 int HNMesh2D::numFacets(int cellDim, int cellLID,
00305                       int facetDim) const  {
00306   //SUNDANCE_VERB_HIGH("numFacets()");
00307   if (cellDim==1) { // 1 dimension
00308          return 2; //one line has 2 points
00309     }
00310     else if (cellDim==2) { // 2 dimensions
00311          return 4; //one quad has 4 edges and 4 points
00312     }
00313   return -1;
00314 }
00315 
00316 int HNMesh2D::facetLID(int cellDim, int cellLID,
00317                      int facetDim, int facetIndex,
00318                      int& facetOrientation) const  {
00319   // todo: check weather facet orientation is right
00320   facetOrientation = 1;
00321   SUNDANCE_MSG3(verb(),"HNMesh2D::facetLID  cellDim:"<<cellDim<<", cellLID:"<<cellLID<<", facetDim:"<<facetDim<< ", facetIndex:" << facetIndex);
00322   int rnt = -1 , LID=-1 , tmp=-1;
00323   if (facetDim == 0){ // return the Number/ID of a Vertex
00324     if (cellDim == 2 ){
00325         LID = cellLeafToLIDMapping_[cellLID];
00326         rnt = cellsPoints_[LID][facetIndex]; tmp = rnt;
00327         rnt = vertexLIDToLeafMapping_[rnt];
00328       }
00329       else if ((cellDim==1)){
00330           LID = edgeLeafToLIDMapping_[cellLID];
00331           rnt = edgePoints_[LID][facetIndex]; tmp = rnt;
00332           rnt = vertexLIDToLeafMapping_[rnt];
00333       }
00334   } else if (facetDim == 1){
00335           LID = cellLeafToLIDMapping_[cellLID];
00336           rnt = cellsEdges_[LID][facetIndex]; tmp = rnt;
00337       rnt = edgeLIDToLeafMapping_[rnt];
00338          }
00339   SUNDANCE_MSG3(verb()," RET = " << rnt << ", LID:" << LID << ", tmp:" <<  tmp);
00340   return rnt;
00341 }
00342 
00343 
00344 void HNMesh2D::getFacetLIDs(int cellDim,
00345                           const Array<int>& cellLID,
00346                           int facetDim,
00347                           Array<int>& facetLID,
00348                           Array<int>& facetSign) const {
00349 
00350   SUNDANCE_MSG3(verb(),"HNMesh2D::getFacetLIDs()  cellDim:"<<cellDim<<"  cellLID.size():"<<cellLID.size()<<"  facetDim:" <<facetDim);
00351     int LID = 0 , cLID , facetOrientation ;
00352     int ptr = 0;
00353 
00354     int nf = numFacets(cellDim, cellLID[0], facetDim);
00355     facetLID.resize(cellLID.size() * nf);
00356     facetSign.resize(cellLID.size() * nf);
00357     // At this moment we just use the previous function
00358   for (unsigned int i = 0 ; i < (unsigned int)cellLID.size() ; i++){
00359       cLID = cellLID[i];
00360         for (int f=0; f<nf; f++, ptr++) {
00361           // we use this->facetLID caz facetLID is already used as variable
00362         LID = this->facetLID( cellDim, cLID, facetDim, f , facetOrientation);
00363             facetLID[ptr] = LID;
00364             facetSign[ptr] = facetOrientation;
00365         }
00366   }
00367   SUNDANCE_MSG3(verb() ,"HNMesh2D::getFacetLIDs()  DONE. ");
00368 }
00369 
00370 
00371 const int* HNMesh2D::elemZeroFacetView(int cellLID) const {
00372     int LID = cellLeafToLIDMapping_[cellLID];
00373     SUNDANCE_MSG3(verb() , "HNMesh2D::elemZeroFacetView ");
00374   return (const int*)(&cellsPoints_[LID]);
00375 }
00376 
00377 
00378 int HNMesh2D::numMaxCofacets(int cellDim, int cellLID) const  {
00379   //SUNDANCE_VERB_HIGH("numMaxCofacets()");
00380   SUNDANCE_MSG3(verb() , "HNMesh2D::numMaxCofacets():  cellDim:"<<cellDim<<" cellLID:"<<cellLID );
00381   int rnt = -1;
00382   if (cellDim==0) { // 1 dimension
00383     int LID = vertexLeafToLIDMapping_[cellLID];
00384         int sum = 0;
00385         for (int i = 0 ; i < 4 ; i++)
00386           if ( (pointMaxCoF_[LID][i] >= 0) && ( cellLIDToLeafMapping_[pointMaxCoF_[LID][i]] >= 0) )
00387             sum++;
00388         // return the value, how many cells has this point, on the leaf level
00389         rnt = sum;
00390     }
00391     else if (cellDim==1) { // 2 dimensions
00392         int LID = edgeLeafToLIDMapping_[cellLID];
00393     if ((edgeMaxCoF_[LID][0] >= 0) && ( cellLIDToLeafMapping_[edgeMaxCoF_[LID][0]] >= 0) &&
00394       (edgeMaxCoF_[LID][1] >= 0) && ( cellLIDToLeafMapping_[edgeMaxCoF_[LID][1]] >= 0))
00395       rnt = 2;
00396     else
00397       rnt = 1;
00398     }
00399   SUNDANCE_MSG3(verb() ," RET = " << rnt );
00400   return rnt;
00401 }
00402 
00403 
00404 int HNMesh2D::maxCofacetLID(int cellDim, int cellLID,
00405                        int cofacetIndex,
00406                        int& facetIndex) const  {
00407 
00408   SUNDANCE_MSG3(verb() ,"HNMesh2D::maxCofacetLID() cellDim:"<<cellDim<<" cellLID:"<<cellLID<<" cofacetIndex:"<<cofacetIndex<< " facetIndex:"
00409       << facetIndex);
00410   int rnt =-1;
00411   if (cellDim==0) { // 1 dimension
00412     //facetIndex = cofacetIndex;
00413     int actCoFacetIndex = 0;
00414       int LID = vertexLeafToLIDMapping_[cellLID];
00415     for (int ii = 0 ; ii < 4 ; ii++){
00416       // take this maxCoFacet only if that exist and is inside
00417       if ( (pointMaxCoF_[LID][ii] >= 0) && (cellLIDToLeafMapping_[pointMaxCoF_[LID][ii]] >= 0) ){
00418         if ( actCoFacetIndex < cofacetIndex ){
00419           actCoFacetIndex++;
00420         }else{
00421           facetIndex = ii;
00422           rnt = pointMaxCoF_[LID][ii];
00423           break;
00424         }
00425       }
00426     }
00427     }
00428     else if (cellDim==1) { // 2 dimensions
00429       int orientation = 0;
00430       int addFakt = 0;
00431       int maxCoFacet = 0;
00432         int LID = edgeLeafToLIDMapping_[cellLID];
00433         // this works only in structured mesh case, but we will only use structured quads because of the Jacoby
00434     if ( edgeVertex_[LID] == 0 ){
00435       orientation = 0;   addFakt = 2;
00436     }else{
00437       orientation = 1;   addFakt = 1;
00438     }
00439     SUNDANCE_MSG3(verb() ," HNMesh2D::maxCofacetLID() , orientation:" <<orientation<< " addFakt:" << addFakt );
00440         // return the index in the vector, which later will be corrected later
00441     int actCoFacetIndex = 0;
00442     for (int ii = 0 ; ii < 2 ; ii++){
00443       // take this maxCoFacet only if that exist and is inside
00444       if ( (edgeMaxCoF_[LID][ii] >= 0) && (cellLIDToLeafMapping_[edgeMaxCoF_[LID][ii]] >= 0) ){
00445         if ( actCoFacetIndex < cofacetIndex ){
00446           actCoFacetIndex++;
00447         }else{
00448           facetIndex = 1-ii;
00449           maxCoFacet = edgeMaxCoF_[LID][ii];
00450           break;
00451         }
00452       }
00453     }
00454     SUNDANCE_MSG3(verb() ,"HNMesh2D::maxCofacetLID() , facetIndex:" << facetIndex <<", _edgeMaxCoFacet[0]:" << edgeMaxCoF_[LID][0] <<
00455         "_edgeMaxCoFacet[1]:" <<  edgeMaxCoF_[LID][1] );
00456     // calculate the correct facetIndex of the edge in the cell of cofacetIndex
00457     if ( orientation == 0 ){
00458       facetIndex = facetIndex + facetIndex*addFakt; // this should be eighter 0 or 3
00459     } else {
00460       facetIndex = facetIndex + addFakt; // this should be eighter 1 or 2
00461     }
00462     SUNDANCE_MSG3(verb() ," maxCoFacet = " << maxCoFacet );
00463     rnt = ( maxCoFacet );
00464     }
00465   // transform back to leaf indexing
00466   rnt = cellLIDToLeafMapping_[ rnt ];
00467   SUNDANCE_MSG3(verb() ," RET = " << rnt << ",  facetIndex:" << facetIndex);
00468   return rnt;
00469 }
00470 
00471 void HNMesh2D::getCofacets(int cellDim, int cellLID,
00472                  int cofacetDim, Array<int>& cofacetLIDs) const {
00473   // Nothing to do
00474   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error," HNMesh2D::getCofacets() not implemented");
00475 }
00476 
00477 
00478 void HNMesh2D::getMaxCofacetLIDs(const Array<int>& cellLIDs,
00479   MaximalCofacetBatch& cofacets) const {
00480   // nothing to do here
00481   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error," HNMesh2D::getMaxCofacetLIDs() not implemented");
00482 }
00483 
00484 
00485 int HNMesh2D::mapGIDToLID(int cellDim, int globalIndex) const  {
00486   //SUNDANCE_VERB_HIGH("mapGIDToLID()");
00487   switch (cellDim){
00488   case 0:{
00489            int ID = vertexLeafToGIDMapping_[globalIndex];
00490          SUNDANCE_MSG3(verb() , " HNMesh2D::mapGIDToLID 0 , globalIndex:" << globalIndex << " ,ID:" << ID << ", ret:"<< vertexLIDToLeafMapping_[ID]);
00491            return vertexLIDToLeafMapping_[ID];
00492         break;}
00493   case 1:{
00494          int ID = edgeLeafToGIDMapping_[globalIndex];
00495          SUNDANCE_MSG3(verb() , " HNMesh2D::mapGIDToLID 1 , globalIndex:" << globalIndex << " ,ID:" << ID << ", ret:"<< edgeLIDToLeafMapping_[ID]);
00496          return edgeLIDToLeafMapping_[ID];
00497         break;}
00498   case 2:{
00499              int ID = cellLeafToGIDMapping_[globalIndex];
00500              SUNDANCE_MSG3(verb() , " HNMesh2D::mapGIDToLID 2 , globalIndex:" << globalIndex << " ,ID:" << ID << ", ret:"<< cellLIDToLeafMapping_[ID]);
00501              return cellLIDToLeafMapping_[ID];
00502         break;}
00503   }
00504   return -1; //Wall
00505 }
00506 
00507 
00508 bool HNMesh2D::hasGID(int cellDim, int globalIndex) const {
00509   //SUNDANCE_VERB_HIGH("hasGID()");
00510   // we should always have all GIDs
00511   return true;
00512 }
00513 
00514 
00515 int HNMesh2D::mapLIDToGID(int cellDim, int localIndex) const  {
00516   //SUNDANCE_VERB_HIGH("mapLIDToGID()");
00517   switch (cellDim){
00518   case 0:{
00519            int ID = vertexLeafToLIDMapping_[localIndex];
00520          SUNDANCE_MSG3(verb() , " HNMesh2D::mapLIDToGID 0 , localIndex:" << localIndex << " ,ID:" << ID << ", ret:"<< vertexGIDToLeafMapping_[ID]);
00521            return vertexGIDToLeafMapping_[ID];
00522         break;}
00523   case 1:{
00524          int ID = edgeLeafToLIDMapping_[localIndex];
00525          SUNDANCE_MSG3(verb() , " HNMesh2D::mapLIDToGID 1 , localIndex:" << localIndex << " ,ID:" << ID << ", ret:"<< edgeGIDToLeafMapping_[ID]);
00526          return edgeGIDToLeafMapping_[ID];
00527         break;}
00528   case 2:{
00529              int ID = cellLeafToLIDMapping_[localIndex];
00530              SUNDANCE_MSG3(verb() , " HNMesh2D::mapLIDToGID 2 , localIndex:" << localIndex << " ,ID:" << ID << ", ret:"<< cellGIDToLeafMapping_[ID]);
00531              return cellGIDToLeafMapping_[ID];
00532         break;}
00533   }
00534   return -1; //Wall
00535 }
00536 
00537 
00538 CellType HNMesh2D::cellType(int cellDim) const  {
00539    switch(cellDim)
00540     {
00541       case 0:  return PointCell;
00542       case 1:  return LineCell;
00543       case 2:  return QuadCell;
00544       default:
00545         return NullCell; // -Wall
00546     }
00547 }
00548 
00549 
00550 int HNMesh2D::label(int cellDim, int cellLID) const {
00551    // not used
00552    TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error," HNMesh2D::label() not implemented yet");
00553    return 0;
00554 }
00555 
00556 
00557 void HNMesh2D::getLabels(int cellDim, const Array<int>& cellLID,
00558     Array<int>& labels) const {
00559    // not used
00560   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error," HNMesh2D::getLabels() not implemented yet");
00561 }
00562 
00563 Set<int> HNMesh2D::getAllLabelsForDimension(int cellDim) const {
00564    Set<int>                 rtn;
00565    // not used
00566    TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error," HNMesh2D::getAllLabelsForDimension() not implemented yet");
00567    return rtn;
00568 }
00569 
00570 void HNMesh2D::getLIDsForLabel(int cellDim, int label, Array<int>& cellLIDs) const {
00571     // not used
00572   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error," HNMesh2D::getLIDsForLabel() not implemented yet");
00573 }
00574 
00575 void HNMesh2D::setLabel(int cellDim, int cellLID, int label) {
00576    // not used
00577   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error," HNMesh2D::setLabel() not implemented yet");
00578 }
00579 
00580 
00581 void HNMesh2D::assignIntermediateCellGIDs(int cellDim) {
00582   // The GIDs are assigned
00583   //SUNDANCE_VERB_HIGH("assignIntermediateCellGIDs()");
00584 }
00585 
00586 
00587 bool HNMesh2D::hasIntermediateGIDs(int dim) const {
00588   //SUNDANCE_VERB_HIGH("hasIntermediateGIDs()");
00589   // the mesh always has intermediate cells
00590   return true; // true means they have been synchronized ... not used now
00591 }
00592 
00593 
00594 // =============================== HANGING NODE FUNCTIONS ==========================
00595 bool HNMesh2D::isElementHangingNode(int cellDim , int cellLID) const {
00596   SUNDANCE_MSG3(verb() ,"HNMesh2D::isElementHangingNode  cellDim:"<<cellDim<<" LID:"<< cellLID);
00597   if (cellDim==0) { // 1 dimension
00598       int LID = vertexLeafToLIDMapping_[cellLID];
00599     return (isPointHanging_[LID]);
00600     }
00601     else if (cellDim==1) { // 2 dimensions
00602       int LID = edgeLeafToLIDMapping_[cellLID];
00603         return (isEdgeHanging_[LID]);
00604     } else {
00605   return false; //Wall
00606     }
00607   return false; //Wall
00608 }
00609 
00610 int HNMesh2D::indexInParent(int maxCellLID) const {
00611   // this is just a mapping from the HNMesh2D child numbering to the DoFMapHN child numbering in 3D
00612   int mapMyChilderIndexToStandardDoFMAP[9] = {0,5,6,1,4,7,2,3,8};
00613   int LID = cellLeafToLIDMapping_[maxCellLID];
00614   int indexInPar = indexInParent_[LID];
00615   //map to the trisection standard which is used to the DoFMaps STANDARD NUMBERING(PEANO CURVE) !
00616   return mapMyChilderIndexToStandardDoFMAP[indexInPar];
00617 }
00618 
00619 void HNMesh2D::returnParentFacets(  int childCellLID , int dimFacets ,
00620                              Array<int> &facetsLIDs , int &parentCellLIDs ) const {
00621   int LID = cellLeafToLIDMapping_[childCellLID];
00622   parentCellLIDs = parentCellLID_[LID];
00623   facetsLIDs.resize(4);
00624   SUNDANCE_MSG3(verb() , "HNMesh2D::returnParentFacets  childCellLID:"<<childCellLID<<" dimFacets:"<<dimFacets<<
00625       "  parentCellLIDs:"<< parentCellLIDs);
00626   // this is the same for edges and for points
00627   facetsLIDs[0] = facetLID_tree( 2 , parentCellLIDs ,  dimFacets , 0 );
00628   facetsLIDs[1] = facetLID_tree( 2 , parentCellLIDs ,  dimFacets , 1 );
00629   facetsLIDs[2] = facetLID_tree( 2 , parentCellLIDs ,  dimFacets , 2 );
00630   facetsLIDs[3] = facetLID_tree( 2 , parentCellLIDs ,  dimFacets , 3 );
00631   // map parent cell ID back to leaf indexing
00632   parentCellLIDs = cellLIDToLeafMapping_[parentCellLIDs];
00633 }
00634 
00635 // only used in determining the parents
00636 int HNMesh2D::facetLID_tree(int cellDim, int cellLID,
00637                      int facetDim, int facetIndex) const{
00638     int rnt = -1;
00639   if (facetDim == 0){ // return the Number/ID of a Vertex
00640        rnt = cellsPoints_[cellLID][facetIndex];
00641        rnt = vertexLIDToLeafMapping_[rnt];
00642        // rnt must be greater than 0
00643   } else if (facetDim == 1){
00644        rnt = cellsEdges_[cellLID][facetIndex];
00645        rnt = edgeLIDToLeafMapping_[rnt];
00646        // rnt must be greater than 0
00647   }
00648   SUNDANCE_MSG3(verb() , "HNMesh2D::facetLID_tree cellDim:"<<cellDim<<", cellLID:"<<cellLID<<", facetDim:"<<facetDim<<
00649       ", facetIndex:"<<facetIndex<<" RET = " << rnt );
00650   return rnt;
00651 }
00652 
00653 // =========================== MESH CREATION ========================================
00654 
00655 /** adds one vertex to the mesh */
00656 void HNMesh2D::addVertex(int vertexLID , int ownerProc , bool isHanging ,
00657      double coordx , double coordy , const Array<int> &maxCoF){
00658   // add only when the LID is new
00659   // WE ASSUME THAT THE "vertexLID" will come in increasing manner
00660   if (points_.size() <= vertexLID){
00661     TEUCHOS_TEST_FOR_EXCEPTION(vertexLID != nrElem_[0] , std::logic_error ,"HNMesh2D::addVertex " <<
00662        " vertexLID:" << vertexLID << " nrElem_[0]:" << nrElem_[0] );
00663      Point pt(coordx,coordy);
00664      points_.append( pt );
00665      pointMaxCoF_.append( maxCoF );
00666      isPointHanging_.append( isHanging );
00667      elementOwner_[0].append( ownerProc );
00668      SUNDANCE_MSG3(verb() , "HNMesh2D::addVertex: " << nrElem_[0] << " P:" << pt << " ,  maxCoF:" << maxCoF);
00669      SUNDANCE_MSG3(verb() , " ownerProc:" << ownerProc << " , isHanging:" << isHanging);
00670      nrElem_[0]++;
00671   }
00672 }
00673 
00674 /** adds one edge to the mesh */
00675 void HNMesh2D::addEdge(int edgeLID , int ownerProc , bool isHanging , int edgeVertex ,
00676                    bool isProcBoundary , bool isMeshBoundary ,
00677                    const Array<int> &vertexLIDs , const Array<int> &maxCoF){
00678     // add only when the edgeLID is new
00679     if (edgePoints_.size() <= edgeLID ){
00680       TEUCHOS_TEST_FOR_EXCEPTION(edgeLID != nrElem_[1], std::logic_error, "HNMesh2D::addEdge edgeLID != nrElem_[1]");
00681      edgePoints_.append( vertexLIDs );
00682      edgeVertex_.append( edgeVertex );
00683      edgeMaxCoF_.append( maxCoF );
00684      edgeIsProcBonudary_.append( isProcBoundary );
00685      edgeIsMeshDomainBonudary_.append( isMeshBoundary );
00686      isEdgeHanging_.append(isHanging);
00687        elementOwner_[1].append( ownerProc );
00688        SUNDANCE_MSG3(verb() , "HNMesh2D::addEdge: " << nrElem_[1] << " vertexLIDs:" << vertexLIDs << " ,  maxCoF:" << maxCoF );
00689        SUNDANCE_MSG3(verb() , "          ownerProc:" << ownerProc << ", isHanging:" << isHanging << ", edgeVertex:" << edgeVertex <<
00690            ", isProcBoundary:" << isProcBoundary << ", isMeshBoundary:" << isMeshBoundary);
00691        nrElem_[1]++;
00692     }
00693 }
00694 
00695 /** adds one cell(2D) to the mesh */
00696 void HNMesh2D::addCell(int cellLID , int ownerProc ,
00697                    int indexInParent , int parentCellLID , int level ,
00698                    const Array<int> &edgeLIDs , const Array<int> &vertexLIDs){
00699     // add only when the edgeLID is new
00700     if (cellsPoints_.size() <= cellLID ) {
00701       TEUCHOS_TEST_FOR_EXCEPTION(cellLID != nrElem_[2], std::logic_error, "HNMesh2D::cellLID cellLID != nrElem_[2]");
00702      cellsPoints_.append( vertexLIDs );
00703      cellsEdges_.append( edgeLIDs );
00704        indexInParent_.append( indexInParent );
00705        parentCellLID_.append( parentCellLID );
00706        cellLevel_.append( level );
00707        isCellLeaf_.append( true );
00708        refineCell_.append( 0 );
00709        cellsChildren_.append( Teuchos::tuple(1) );
00710        elementOwner_[2].append( ownerProc );
00711        SUNDANCE_MSG3(verb() , "HNMesh2D::addCell: " << nrElem_[2] << " vertexLIDs:" << vertexLIDs << " edgeLIDs:" << edgeLIDs);
00712        SUNDANCE_MSG3(verb() , "HNMesh2D::addCell p0:" << points_[vertexLIDs[0]] );
00713        SUNDANCE_MSG3(verb() , "HNMesh2D::addCell p1:" << points_[vertexLIDs[1]] );
00714        SUNDANCE_MSG3(verb() , "HNMesh2D::addCell p2:" << points_[vertexLIDs[2]] );
00715        SUNDANCE_MSG3(verb() , "HNMesh2D::addCell p3:" << points_[vertexLIDs[3]] );
00716      // calculate if the cell is complete outside the mesh domain
00717      isCellOut_.append( !( meshDomain_.isInsideComputationalDomain(points_[vertexLIDs[0]]) ||
00718                        meshDomain_.isInsideComputationalDomain(points_[vertexLIDs[1]]) ||
00719                        meshDomain_.isInsideComputationalDomain(points_[vertexLIDs[2]]) ||
00720                        meshDomain_.isInsideComputationalDomain(points_[vertexLIDs[3]]) ) );
00721      SUNDANCE_MSG3(verb() , "HNMesh2D::addCell IN DOMAIN:" <<  isCellOut_[nrElem_[2]] );
00722        nrElem_[2]++;
00723     }
00724 }
00725 
00726 /** creates one regular mesh without refinement. With a different function the
00727  * refinement can start later , independently from this function. <br>
00728  * The structure of this mesh also supports unstructured storage of the cells,
00729  * so we might create unstructured mesh and later refine in the same way */
00730 void HNMesh2D::createMesh(
00731                       double position_x,
00732                 double position_y,
00733                 double offset_x,
00734                 double offset_y,
00735                 int resolution_x,
00736                 int resolution_y,
00737                 const RefinementClass& refineClass ,
00738                 const MeshDomainDef& meshDomain
00739 ){
00740 
00741   setVerb(0);
00742 
00743   // initialize object fields
00744   _pos_x = position_x; _pos_y = position_y;
00745   _ofs_x = offset_x; _ofs_y = offset_y;
00746   _res_x = resolution_x; _res_y = resolution_y;
00747   refineClass_ = refineClass;
00748   meshDomain_ = meshDomain;
00749 
00750   // create coarsest mesh
00751   createCoarseMesh();
00752 
00753   // loop as long there is no refinement
00754     bool doRefinement = true;
00755     while (doRefinement){
00756       doRefinement = oneRefinementIteration();
00757     }
00758 
00759   // calculate global IDs and create leaf Numbering
00760     //createLeafNumbering();
00761     createLeafNumbering_sophisticated();
00762 
00763 }
00764 
00765 void HNMesh2D::createCoarseMesh(){
00766   // estimate load for parallel case,
00767   // assign cells to each processors, based on the load and the domain
00768   // we assign cells to processors, (y,x) (optimal for vertical channel flow)
00769   // the estimation is done in each processor, globally but then only the local mesh will be build
00770   int nrCoarseCell = _res_x*_res_y;
00771   int nrCoarsePoints = (_res_x+1)*(_res_y+1);
00772   int nrCoarseEdge = (_res_x+1)*_res_y + _res_x*(_res_y+1);
00773   Array<int> coarseProcessCell( nrCoarseCell , -1 );
00774   Array<int> coarseCellOwner( nrCoarseCell , -1 );
00775   Array<int> coarsePointOwner( nrCoarsePoints , -1 );
00776   Array<int> coarseEdgeOwner( nrCoarseEdge , -1 );
00777   Array<int> coarseCellLID( nrCoarseCell , -1 );
00778   Array<int> coarsePointLID( nrCoarsePoints , -1 );
00779   Array<int> coarseEdgeLID( nrCoarseEdge , -1 );
00780   Array<int> coarseCellsLoad( nrCoarseCell , 0 );
00781   int totalLoad = 0;
00782 
00783   SUNDANCE_MSG3(verb() , "HNMesh2D::createMesh nrCoarseCell:" << nrCoarseCell << " nrCoarsePoints:" << nrCoarsePoints
00784                 << " nrCoarseEdge:" << nrCoarseEdge << " nrProc_:" << nrProc_ << " myRank_:" << myRank_);
00785   TEUCHOS_TEST_FOR_EXCEPTION( nrCoarseCell < nrProc_ , std::logic_error," HNMesh2D::createMesh nrCoarseCell < nrProc_ ");
00786   // now always divide as a flow channel , no resolution driven division
00787 
00788     // calculate total load and load per coarse cell
00789   double h[2];
00790   h[0] = _ofs_x/(double)_res_x; h[1] = _ofs_y/(double)_res_y;
00791   Point pos(h[0],h[1]);
00792   Point res(h[0],h[1]);
00793   // estimate total estimated load of the mesh
00794   for (int i=0; i < nrCoarseCell; i++){
00795     // midpoint of the cell
00796     pos[0] = _pos_x + (double)(i / _res_y)*h[0] + 0.5*h[0];
00797     pos[1] = _pos_y + (double)(i % _res_y)*h[1] + 0.5*h[1];
00798     // todo: take the domain in consideration (take the 4 points) (when cells are turned off)
00799     coarseCellsLoad[i] = refineClass_.estimateRefinementLevel( pos , res );
00800     totalLoad += coarseCellsLoad[i];
00801   }
00802   // calculate average load per cell
00803   double loadPerProc = (double)totalLoad / (double)nrProc_;
00804   int actualProc=0;
00805   totalLoad = 0;
00806   Array<int>  ind(2); // vertex is mesh boundary
00807   // offsets for vertex and edge index
00808   int vertexOffs[4] = {0 , _res_y + 1 , 1 ,  _res_y + 2};
00809   int edgeOffs[4] = {_res_y , 0 , 2*_res_y + 1 , _res_y + 1};
00810 
00811   // assign owners to the cells, edges, vertexes , greedy method
00812   SUNDANCE_MSG3(verb() , "Processor asign, loadPerProc:" << loadPerProc );
00813   double diff_load = 0.0;
00814   for (int i=0; i < nrCoarseCell; i++){
00815     ind[0] = (i / _res_y);
00816     ind[1] = (i % _res_y);
00817     int vertexInd = (_res_y+1)*ind[0] + ind[1];
00818     int edgeInd = (2*_res_y+1)*ind[0] + ind[1];
00819     //SUNDANCE_MSG3(verb() , "Cell ID:" << i << " vertexInd:" <<vertexInd << " edgeInd:" << edgeInd );
00820     //SUNDANCE_MSG3(verb() , "Cell, actual index" << ind  );
00821     // assign ownership for vertexes
00822     for (int jj = 0 ; jj < 4 ; jj++){
00823       if (coarsePointOwner[vertexInd+vertexOffs[jj]] < 0){
00824         coarsePointOwner[vertexInd+vertexOffs[jj]] = actualProc;
00825         SUNDANCE_MSG3(verb() , "Vertex CPU assign " << vertexInd+vertexOffs[jj] << " ->" << actualProc );
00826       }
00827     }
00828     // assign ownership for edges
00829     for (int jj = 0 ; jj < 4 ; jj++){
00830       if (coarseEdgeOwner[edgeInd+edgeOffs[jj]] < 0){
00831         coarseEdgeOwner[edgeInd+edgeOffs[jj]] = actualProc;
00832         //SUNDANCE_MSG3(verb() , "Edge CPU assign " << edgeInd+edgeOffs[jj] << " ->" << actualProc );
00833       }
00834     }
00835     // assign ownership for the cell
00836     coarseCellOwner[i] = actualProc;
00837     totalLoad += coarseCellsLoad[i];
00838     SUNDANCE_MSG3(verb() , "Cell CPU assign " << i << " ->" << actualProc <<
00839         ", totalLoad:" << totalLoad << " loadPerProc:" << loadPerProc);
00840     // the rounding of the load estimator is in favor to late earlier
00841     if (((double)totalLoad >= (loadPerProc - 1e-8 - diff_load)) && ( actualProc < nrProc_-1 )){
00842       SUNDANCE_MSG3(verb() , "Increase CPU , totalLoad:" << totalLoad << " loadPerProc:" << loadPerProc );
00843       // compensate the load difference for the next CPU
00844       diff_load = totalLoad - loadPerProc;
00845       actualProc = actualProc + 1;
00846       totalLoad = 0;
00847     }
00848   }
00849 
00850   // next step is to see which cell we will process (we also have to add the remote cells)
00851   for (int i=0; i < nrCoarseCell; i++){
00852     ind[0] = (i / _res_y);
00853     ind[1] = (i % _res_y);
00854     coarseProcessCell[i] = 1;
00855   }
00856 
00857   // now go trough all cells which have to be added to this processor
00858   SUNDANCE_MSG3(verb() , " Process Cells:" << nrCoarseCell );
00859   for (int i=0; i < nrCoarseCell; i++){
00860     ind[0] = (i / _res_y);
00861     ind[1] = (i % _res_y);
00862     pos[0] = _pos_x + (double)(ind[0])*h[0];
00863     pos[1] = _pos_y + (double)(ind[1])*h[1];
00864     SUNDANCE_MSG3(verb() , "PCell ID:" << i << " coarseProcessCell[i]:" <<coarseProcessCell[i] << " pos:" << pos );
00865     SUNDANCE_MSG3(verb() , "PCell, actual index" << ind  );
00866     // this condition is so that remote cells will be added
00867     if (coarseProcessCell[i] > 0) {
00868       int vertexInd = (_res_y+1)*ind[0] + ind[1];
00869       int edgeInd = (2*_res_y+1)*ind[0] + ind[1];
00870       int cellLID = coarseCellLID[i];
00871       Array<int> vertexLID(4,-1) , vertexMaxCoF(4,-1) , vLID(4,-1);;
00872       Array<int> edgeLID(4,-1) , edgeVert(2,-1) , edgeMaxCoef(2,-1);
00873       //SUNDANCE_MSG3(verb() , "Cell ID:" << i << " vertexInd:" <<vertexInd << " edgeInd:" << edgeInd << " cellLID:" << cellLID);
00874       //SUNDANCE_MSG3(verb() , "Cell, actual index" << ind << " pos:" << pos);
00875       // assign new cellID if necessary
00876       if (coarseCellLID[i] < 0 ){
00877         coarseCellLID[i] = nrElem_[2];
00878         cellLID = coarseCellLID[i];
00879       }
00880       // add all Vertexes , ignoring neighbor cells (maxcofacets)
00881             for (int jj = 0 ; jj < 4 ; jj++){
00882               vLID[jj] = coarsePointLID[vertexInd+vertexOffs[jj]];
00883               //SUNDANCE_MSG3(verb() , "Vertex  vertexInd:" << vertexInd);
00884               //SUNDANCE_MSG3(verb() , "Vertex  vertexOffs[jj]:" << vertexOffs[jj]);
00885               //SUNDANCE_MSG3(verb() , "Vertex  index:" << vertexInd+vertexOffs[jj]);
00886               if (coarsePointLID[vertexInd+vertexOffs[jj]] < 0){
00887                 coarsePointLID[vertexInd+vertexOffs[jj]] = nrElem_[0];
00888               }
00889               vLID[jj] = coarsePointLID[vertexInd+vertexOffs[jj]];
00890                 // add vertex with -1 maxCOfacets
00891               //SUNDANCE_MSG3(verb() , "Vertex  X:" << ((double)offs_Points_x_[jj])*h[0] << "  Y:" << pos[1] + ((double)offs_Points_y_[jj])*h[1]);
00892               //SUNDANCE_MSG3(verb() , "Vertex  vLID[jj]:" << vLID[jj] << "  , coarsePointOwner[vertexInd+vertexOffs[jj]]" << coarsePointOwner[vertexInd+vertexOffs[jj]] );
00893               addVertex( vLID[jj] , coarsePointOwner[vertexInd+vertexOffs[jj]] , false ,
00894                      pos[0] + ((double)offs_Points_x_[jj])*h[0] , pos[1] + ((double)offs_Points_y_[jj])*h[1] ,
00895                          vertexMaxCoF );
00896             }
00897       // add all Edges , ignoring neighbor cells (maxcofacets)
00898             for (int jj = 0 ; jj < 4 ; jj++){
00899               edgeLID[jj] = coarseEdgeLID[edgeInd+edgeOffs[jj]];
00900               if (coarseEdgeLID[edgeInd+edgeOffs[jj]] < 0){
00901                 coarseEdgeLID[edgeInd+edgeOffs[jj]] = nrElem_[1];
00902               }
00903               edgeLID[jj] = coarseEdgeLID[edgeInd+edgeOffs[jj]];
00904               edgeVert[0] = vLID[edge_Points_localIndex[jj][0]];
00905               edgeVert[1] = vLID[edge_Points_localIndex[jj][1]];
00906                 // add edge with -1 maxCOfacets
00907               addEdge( edgeLID[jj] , coarseEdgeOwner[edgeInd+edgeOffs[jj]] , false , (jj==0 || jj==3) ? 0 : 1 ,
00908                             false , false , // these two flags later need to be updated
00909                           edgeVert , edgeMaxCoef );
00910             }
00911       // add the Cell
00912             addCell( cellLID , coarseCellOwner[i] , 0 , cellLID , 0 , edgeLID , vLID);
00913     }
00914   } // --- end from for loop
00915 
00916   // next is maxCoFacet and boundary info update for vertexes and edges
00917   SUNDANCE_MSG3(verb() , " Process maxCofacets:" << nrCoarseCell );
00918   for (int i=0; i < nrCoarseCell; i++){
00919     // this condition is so that remote cells will be added
00920     if (coarseProcessCell[i] > 0){
00921       Array<int> vLID(4,-1) , eLID(4,-1) , maxVertexCoF(4,-1);
00922       ind[0] = (i / _res_y);
00923       ind[1] = (i % _res_y);
00924       int vertexInd = (_res_y+1)*ind[0] + ind[1];
00925       int edgeInd = (2*_res_y+1)*ind[0] + ind[1];
00926       int cellLID = coarseCellLID[i];
00927       SUNDANCE_MSG3(verb() , "MCell cellLID:" << cellLID << " coarseProcessCell[i]:" <<coarseProcessCell[i] );
00928       //SUNDANCE_MSG3(verb() , "MCell ID:" << i << " vertexInd:" <<vertexInd << " edgeInd:" << edgeInd );
00929       //SUNDANCE_MSG3(verb() , "MCell, actual index" << ind  );
00930       // vertex maxCoFac
00931             for (int jj = 0 ; jj < 4 ; jj++){
00932               vLID[jj] = coarsePointLID[vertexInd+vertexOffs[jj]];
00933               // if all elements are added then this is OK
00934               pointMaxCoF_[vLID[jj]][jj] = cellLID;
00935               SUNDANCE_MSG3(verb() , "Vertex MaxCoFacet vLID[jj]:" << vLID[jj] << " jj:" << jj << " cellLID:" << cellLID );
00936             }
00937             // edge maxCoFac
00938             for (int jj = 0 ; jj < 4 ; jj++){
00939               eLID[jj] = coarseEdgeLID[edgeInd+edgeOffs[jj]];
00940               // if all elements are added then this is OK
00941               edgeMaxCoF_[eLID[jj]][(3-jj)/2] = cellLID;
00942               SUNDANCE_MSG3(verb() , "Edge MaxCoFacet eLID[jj]:" << eLID[jj] << " (3-jj)/2:" << (3-jj)/2 << " cellLID:" << cellLID );
00943               // update boundary info of the edge
00944               int orientation = ( (jj==0) || (jj==3)) ? 1 : 0;
00945 
00946               if (orientation == 0){ // vertical edge
00947                  // mesh boundary
00948                    if ( (ind[0] == 0) && (jj==1))   edgeIsMeshDomainBonudary_[eLID[jj]] = true;
00949                    if ( (ind[0] == _res_x - 1 ) && (jj==2))   edgeIsMeshDomainBonudary_[eLID[jj]] = true;
00950                    // process boundary
00951                    if ( edgeIsMeshDomainBonudary_[eLID[jj]] != true){
00952                      // now here is dummy implementation
00953                        edgeIsProcBonudary_[eLID[jj]] = false; //(bool)(edgeOwner != edgeOwnerN);
00954                    }
00955               }else{ // horizontal edge
00956                  // mesh boundary
00957                    if ( (ind[1] == 0) && (jj==0))  { edgeIsMeshDomainBonudary_[eLID[jj]] = true; }
00958                    if ( (ind[1] == _res_y - 1 ) && (jj==3))  { edgeIsMeshDomainBonudary_[eLID[jj]] = true; }
00959                    // process boundary
00960                    if ( edgeIsMeshDomainBonudary_[eLID[jj]] != true){
00961                      // now there is only the dummy implementation
00962                        edgeIsProcBonudary_[eLID[jj]] = false; //(bool)(edgeOwner != edgeOwnerN);
00963                    }
00964                    SUNDANCE_MSG3(verb() , "Neighb. H  Cell DONE ");
00965               }
00966             }
00967     }
00968   }
00969   // basic rectangular mesh is build
00970 }
00971 
00972 // -----------
00973 bool HNMesh2D::oneRefinementIteration(){
00974 
00975   Array<int> ind(2);
00976     int nrActualCell = nrElem_[2];
00977     bool rtn = false;
00978     SUNDANCE_MSG3(verb() , " HNMesh2D::oneRefinementIteration, start one refinement iteration cycle ");
00979     // we iterate only over the existing cells (not the ones which will be later created)
00980   for (int i=0 ; i < nrActualCell ; i++){
00981 
00982     ind[0] = (i / _res_y);
00983     ind[1] = (i % _res_y);
00984 
00985     // cell is owned by the current processor, and is leaf and is inside the mesh domain
00986       SUNDANCE_MSG3(verb() , " Test cell " << i << ", elementOwner_[2][i]:" << elementOwner_[2][i] <<
00987                          ", isCellLeaf_[i]:" << isCellLeaf_[i] << ", out:" << (!isCellOut_[i]));
00988 
00989     if ( (isCellLeaf_[i] == true) )
00990       //(elementOwner_[2][i] == myRank_) && (isCellLeaf_[i] == true) )
00991       //( (elementOwner_[2][i] == myRank_) && (isCellLeaf_[i] == true) && (!isCellOut_[i]))
00992       //  mark neighbors for refinements if because of the hanging nodes a refinement is not possible, regardless of the IN or OUT of Mesh domain
00993     {
00994       // check if refinement is needed and possible, none of the vertexes can be hanging
00995       Array<int>& cellsEdges = cellsEdges_[i];
00996             bool doRefined = true;
00997             bool refFunction = false;
00998             for (int jj = 0 ; jj < cellsEdges.size() ; jj++){
00999               SUNDANCE_MSG3(verb() , " eLID: " << cellsEdges[jj] << ", isHanging:" << isEdgeHanging_[cellsEdges[jj]]);
01000               doRefined = ( doRefined && ((isEdgeHanging_[cellsEdges[jj]]) == false) );
01001             }
01002             // --- if refinement is possible
01003             SUNDANCE_MSG3(verb() , " is possible to refine cell nr: " << i << ", doRefined:" << doRefined);
01004             // call refinement function
01005       Array<int>& cellsVertex = cellsPoints_[i];
01006       Point h = points_[cellsVertex[3]] - points_[cellsVertex[0]];
01007       Point p2 = points_[cellsVertex[0]] + 0.5*h;
01008       refFunction = ((refineCell_[i] == 1) || refineClass_.refine( cellLevel_[i] , p2 , h ));
01009 
01010             // decide if we refine this cell
01011             SUNDANCE_MSG3( verb() , " execute refinement on cell nr: " << i << ", refFunction:" << refFunction);
01012             if (doRefined && refFunction)
01013             {
01014               // -- call the function to refine the actual cell ---
01015               refineCell(i);
01016               rtn = true;
01017               refineCell_[i] = 0;
01018             }
01019             else
01020             {
01021               // Cell can not be refined
01022                 // we mark neighbor cells, based on "refFunction"
01023               if (refFunction){
01024                 //SUNDANCE_MSG3( verb() , " HNMesh2D::oneRefinementIteration mark neighbor cells ");
01025                     for (int jj = 0 ; jj < cellsEdges.size() ; jj++){
01026                       if (isEdgeHanging_[cellsEdges[jj]]){
01027                         //SUNDANCE_MSG3( verb() , " HNMesh2D::oneRefinementIteration isEdgeHanging_[cellsEdges[jj]] == true , " << jj);
01028                         // get the parent cell
01029                         int cLevel = cellLevel_[i];
01030                         int parentID = parentCellLID_[i];
01031                         int parentCEdge = cellsEdges_[parentID][jj];
01032                         int refCell = -1;
01033                         // look for maxCoFacets
01034                         if ( (jj == 0) || ( jj == 1) )
01035                           refCell = edgeMaxCoF_[parentCEdge][0];
01036                         else
01037                           refCell = edgeMaxCoF_[parentCEdge][1];
01038                         // refCell should be refined and mark for refinement
01039                         //SUNDANCE_MSG3( verb() , " cLevel:" << cLevel << " parentID:" << parentID << " parentCEdge:" << parentCEdge
01040                         //    << " refCell:" << refCell );
01041                         //SUNDANCE_MSG3( verb() ," edgeMaxCoF_[parentCEdge]:" << edgeMaxCoF_[parentCEdge]);
01042                             if ( (refCell >= 0) && (cellLevel_[refCell] < cLevel) && (isCellLeaf_[refCell])){
01043 
01044                               refineCell_[refCell] = 1;
01045                               rtn = true;
01046                               //SUNDANCE_MSG3( verb() , " HNMesh2D::oneRefinementIteration refineCell_[refCell] = 1 , " << refCell
01047                               //    << ", cellLevel_[refCell]:" << cellLevel_[refCell]);
01048                             }
01049                       }
01050                     }
01051               }
01052             }
01053     }
01054   }
01055 
01056   //  -> communicate with neighbor processor
01057   //     not needed if the mesh exist globally
01058 
01059   SUNDANCE_MSG3(verb() , " HNMesh2D::oneRefinementIteration DONE with one refinement iteration");
01060   // return if there was refinement or attempt to refine
01061   return rtn;
01062 }
01063 
01064 // -------- refine cell cellID (assuming all conditions are satisfied)--
01065 void HNMesh2D::refineCell(int cellLID){
01066     // data initialization
01067   Array<int>& cellsEdges = cellsEdges_[cellLID];
01068   Array<int>& cellsVertex = cellsPoints_[cellLID];
01069   int cellOwner = elementOwner_[2][cellLID];
01070   Point p = points_[cellsVertex[0]];
01071   Point h = points_[cellsVertex[3]] - points_[cellsVertex[0]];
01072     // the X and the Y coordinates of the newly
01073   double vertex_X[16] = { 0.0 , 0.0 , 0.0 , 0.0 , 1.0/3.0 , 1.0/3.0 , 1.0/3.0 , 1.0/3.0 ,
01074                       2.0/3.0 , 2.0/3.0 , 2.0/3.0 , 2.0/3.0 , 1.0 , 1.0 , 1.0 , 1.0 };
01075   double vertex_Y[16] = { 0.0 , 1.0/3.0 , 2.0/3.0 , 1.0 , 0.0 , 1.0/3.0 , 2.0/3.0 , 1.0 ,
01076                       0.0 , 1.0/3.0 , 2.0/3.0 , 1.0 , 0.0 , 1.0/3.0 , 2.0/3.0 , 1.0 };
01077     // if we have pre stored  hanging edge , we might just load them and these are the indexes (in 3X3 refinement)
01078   int hanginEdgeI[4][3] = { {3,10,17} , {0,1,2} , {21,22,23} , {6,13,20} };
01079   // existing vertexes and their index in the 3X3 cell refinement
01080   int hanginVertexI[4][2] = { {4,8} , {1,2} , {13,14} , {7,11} };
01081   // orientation of the newly (or existing) edges
01082   int edgeVertex[24] = { 1,1,1 , 0,0,0,0 , 1,1,1  ,  0,0,0,0  ,  1,1,1  ,  0,0,0,0  ,  1,1,1};
01083   // the index in the vertex for one edge where the existing elements are stored
01084   int VertexIndex[4] = { 0 , 1 , 1 , 0 };
01085   // for each edge (where the existing vertexes are stored)
01086   int VertexI[4] = { 0 , 0 , 1 , 2 };
01087 
01088     // vertex info , owner of the new vertexes
01089   int vertexOwner[16] = { elementOwner_[0][cellsVertex[0]] , elementOwner_[1][cellsEdges[1]] ,
01090                       elementOwner_[1][cellsEdges[1]]  , elementOwner_[0][cellsVertex[2]] ,
01091                       elementOwner_[1][cellsEdges[0]]  , cellOwner , cellOwner , elementOwner_[1][cellsEdges[3]] ,
01092                       elementOwner_[1][cellsEdges[0]]  , cellOwner , cellOwner , elementOwner_[1][cellsEdges[3]] ,
01093                       elementOwner_[0][cellsVertex[1]] , elementOwner_[1][cellsEdges[2]] ,
01094                       elementOwner_[1][cellsEdges[2]]  , elementOwner_[0][cellsVertex[3]]  };
01095   // if vertex is hanging
01096   bool vertexIsHanging[16] = { false , !edgeIsMeshDomainBonudary_[cellsEdges[1]] , !edgeIsMeshDomainBonudary_[cellsEdges[1]], false ,
01097                            !edgeIsMeshDomainBonudary_[cellsEdges[0]] , false , false , !edgeIsMeshDomainBonudary_[cellsEdges[3]] ,
01098                            !edgeIsMeshDomainBonudary_[cellsEdges[0]] , false , false , !edgeIsMeshDomainBonudary_[cellsEdges[3]] ,
01099                                false , !edgeIsMeshDomainBonudary_[cellsEdges[2]] , !edgeIsMeshDomainBonudary_[cellsEdges[2]], false };
01100   // edge info
01101   int edgeOwner[24] = { elementOwner_[1][cellsEdges[1]] , elementOwner_[1][cellsEdges[1]] , elementOwner_[1][cellsEdges[1]] ,
01102                     elementOwner_[1][cellsEdges[0]] , cellOwner , cellOwner , elementOwner_[1][cellsEdges[3]] ,
01103                     cellOwner , cellOwner , cellOwner ,
01104                     elementOwner_[1][cellsEdges[0]] , cellOwner , cellOwner , elementOwner_[1][cellsEdges[3]] ,
01105                     cellOwner , cellOwner , cellOwner ,
01106                     elementOwner_[1][cellsEdges[0]] , cellOwner , cellOwner , elementOwner_[1][cellsEdges[3]] ,
01107                     elementOwner_[1][cellsEdges[2]] , elementOwner_[1][cellsEdges[2]] , elementOwner_[1][cellsEdges[2]]  };
01108   // edge hanging
01109   bool edgeIsHanging[24] = { !edgeIsMeshDomainBonudary_[cellsEdges[1]] , !edgeIsMeshDomainBonudary_[cellsEdges[1]] , !edgeIsMeshDomainBonudary_[cellsEdges[1]] ,
01110                          !edgeIsMeshDomainBonudary_[cellsEdges[0]] , false , false , !edgeIsMeshDomainBonudary_[cellsEdges[3]] ,
01111                              false , false , false ,
01112                              !edgeIsMeshDomainBonudary_[cellsEdges[0]] , false , false , !edgeIsMeshDomainBonudary_[cellsEdges[3]] ,
01113                              false , false , false ,
01114                              !edgeIsMeshDomainBonudary_[cellsEdges[0]] , false , false , !edgeIsMeshDomainBonudary_[cellsEdges[3]] ,
01115                              !edgeIsMeshDomainBonudary_[cellsEdges[2]] , !edgeIsMeshDomainBonudary_[cellsEdges[2]] , !edgeIsMeshDomainBonudary_[cellsEdges[2]] };
01116   // vertexes which form the new (or existing) edges
01117   int edgeVertexes[24][2] = { {0,1} , {1,2} , {2,3} , {0,4} , {1,5} , {2,6} , {3,7} , {4,5} , {5,6} , {6,7} ,
01118                         {4,8} , {5,9} , {6,10} , {7,11} , {8,9} , {9,10} , {10,11} ,
01119                         {8,12} , {9,13} , {10,14} , {11,15} , {12,13} , {13,14} , {14,15}};
01120   // if edge is processor boundary
01121   bool edgePBnd[24] = { edgeIsProcBonudary_[cellsEdges[1]] , edgeIsProcBonudary_[cellsEdges[1]] , edgeIsProcBonudary_[cellsEdges[1]] ,
01122                     edgeIsProcBonudary_[cellsEdges[0]] , false , false , edgeIsProcBonudary_[cellsEdges[3]] ,
01123                         false , false , false ,
01124                         edgeIsProcBonudary_[cellsEdges[0]] , false , false , edgeIsProcBonudary_[cellsEdges[3]] ,
01125                         false , false , false ,
01126                         edgeIsProcBonudary_[cellsEdges[0]] , false , false , edgeIsProcBonudary_[cellsEdges[3]] ,
01127                         edgeIsProcBonudary_[cellsEdges[2]] , edgeIsProcBonudary_[cellsEdges[2]] , edgeIsProcBonudary_[cellsEdges[2]] };
01128   // if edge is mesh boundary
01129   bool edgeMBnd[24] = { edgeIsMeshDomainBonudary_[cellsEdges[1]] , edgeIsMeshDomainBonudary_[cellsEdges[1]] , edgeIsMeshDomainBonudary_[cellsEdges[1]] ,
01130                     edgeIsMeshDomainBonudary_[cellsEdges[0]] , false , false , edgeIsMeshDomainBonudary_[cellsEdges[3]] ,
01131               false , false , false ,
01132               edgeIsMeshDomainBonudary_[cellsEdges[0]] , false , false , edgeIsMeshDomainBonudary_[cellsEdges[3]] ,
01133                           false , false , false ,
01134                           edgeIsMeshDomainBonudary_[cellsEdges[0]] , false , false , edgeIsMeshDomainBonudary_[cellsEdges[3]] ,
01135                           edgeIsMeshDomainBonudary_[cellsEdges[2]] , edgeIsMeshDomainBonudary_[cellsEdges[2]] , edgeIsMeshDomainBonudary_[cellsEdges[2]] };
01136   // vertex index in the 3X3 context which is needed for the cell creation
01137   int refinedCellsVertexes[9][4] = { {0,4,1,5} , {1,5,2,6} , {2,6,3,7} ,
01138                         {4,8,5,9} , {5,9,6,10} , {6,10,7,11} ,
01139                         {8,12,9,13} , {9,13,10,14} , {10,14,11,15} };
01140   // edge context in the 3X3 context, for cell creation
01141   int refinedCellsEdges[9][4] =   { {3,0,7,4} , {4,1,8,5} , {5,2,9,6} ,
01142                         {10,7,14,11} , {11,8,15,12} , {12,9,16,13} ,
01143                         {17,14,21,18} , {18,15,22,19} , {19,16,23,20} };
01144   // the index and offset to store the hanging nodes
01145   int hVertexIndex[16]       = { -1 , 0 , 1 , -1 , 0 , -1 , -1 , 0 , 1 , -1 , -1 , 1 , -1 , 0 , 1 , -1 };
01146   int hEdgeIndex[24]         = { 0 , 1 , 2 , 0 , -1 , -1 , 0 , -1 , -1 , -1 ,  1 , -1 , -1 , 1 , -1 , -1 , -1 , 2 , -1 , -1 , 2 , 0 , 1 , 2 };
01147   int hVertexVertexIndex[16] = { -1 , 1 , 1 , -1 , 0 , -1 , -1 , 3 , 0 , -1 , -1 , 3 , -1 , 2 , 2 , -1 };
01148   int hEdgeVertexIndex[24]   = { 1 , 1 , 1 , 0 , -1 , -1 , 3 , -1 , -1 , -1 ,  0 , -1 , -1 , 3 , -1 , -1 , -1 , 0 , -1 , -1 , 3 , 2 , 2 , 2 };
01149 
01150   // cell index in the 3X3 for vertex maxCoFacets
01151   int vertexMaxCoFacet[16][4] = { {0,-1,-1,-1} , {1,-1,0,-1} , {2 ,-1,1,-1} , {-1,-1,2,-1} ,
01152                               {3,0,-1,-1} , {4,1,3,0}    , {5 ,2,4,1} , {-1,-1,5,2}    ,
01153                               {6,3,-1,-1} , {7,4,6,3}    , {8 ,5,7,4} , {-1,-1,8,5}    ,
01154                               {-1,6,-1,-1} , {-1,7,-1,6} , {-1,8,-1,7} , {-1,-1,-1,8}  };
01155   // there will be 9 newly created cells, these should be maxCoFactes in the vertexes and the edges
01156   int edgeMaxCoFacet[24][2] = { {-1,0} , {-1,1} , {-1,2} ,
01157                             {-1,0} , {0,1} , {1,2} , {2,-1} ,
01158                              {0,3} , {1,4} , {2,5} ,
01159                             {-1,3} , {3,4} , {4,5} , {5,-1} ,
01160                              {3,6} , {4,7} , {5,8} ,
01161                             {-1,6} , {6,7} , {7,8} , {8,-1} ,
01162                             {6,-1} , {7,-1} , {8,-1} };
01163   // we might need to copy the MaxCoFacet from the parent edge
01164   int indexEdgeParentMaxCoFacet[24] = { 1 , 1, 1 , 0 , -1 , -1 , 3 , -1 , -1 , - 1, 0 , -1 , -1 , 3 , -1 , -1 , -1 , 0 ,-1,-1,3, 2,2,2 };
01165   // in which direction to look
01166   int offsEdgeParentMaxCoFacet[24] = { 0 , 0, 0 , 0 , -1 , -1 , 1 , -1 , -1 , - 1, 0 , -1 , -1 , 1 , -1 , -1 , -1 , 0 ,-1,-1,1, 1,1,1 };
01167 
01168     // hanging elements information
01169   Array< Array<int> > hangingInfo(4);
01170   hangingInfo[0].resize(0); hangingInfo[1].resize(0); hangingInfo[2].resize(0); hangingInfo[3].resize(0);
01171 
01172     // the created vertex, edge and cell LIDs
01173     Array<int> vertexLIDs(16,-1);
01174     Array<int> edgeLIDs(24,-1);
01175     Array<int> cellLIDs(9,-1);
01176 
01177     SUNDANCE_MSG3(verb() , " ========== HNMesh2D::refineCell, cellLID:" << cellLID << " ==========");
01178     //SUNDANCE_MSG3( verb() , " cellsVertex:" << cellsVertex );
01179     // the 4 "corner" points are already created (according to refinement numbering!)
01180     vertexLIDs[0] = cellsVertex[0]; vertexLIDs[3] = cellsVertex[2];
01181     vertexLIDs[12] = cellsVertex[1]; vertexLIDs[15] = cellsVertex[3];
01182 
01183     // look for existing elements
01184     for (int v = 0 ; v < 4 ; v++){
01185       // look for already stored elements
01186       //SUNDANCE_MSG3( verb() , " Test vertex VertexIndex[v]:" << VertexIndex[v] << ", cellsVertex[VertexI[v]]:" << cellsVertex[VertexI[v]] );
01187       //SUNDANCE_MSG3( verb() , " hangElmStore_[VertexIndex[v]].size()" << hangElmStore_[VertexIndex[v]].size() );
01188       if (hangElmStore_[VertexIndex[v]].containsKey(cellsVertex[VertexI[v]])){
01189            const Array<int>& hnInfo = hangElmStore_[VertexIndex[v]].get(cellsVertex[VertexI[v]]);
01190            // this is the convention how we store the hanging info
01191            // these elements are not hanging after this
01192            //SUNDANCE_MSG3( verb() , " Found key: " << cellsVertex[VertexI[v]] << ", size:" << hnInfo.size() << " , array:" << hnInfo );
01193            vertexLIDs[hanginVertexI[v][0]] = hnInfo[0];  isPointHanging_[hnInfo[0]] = false;
01194            vertexLIDs[hanginVertexI[v][1]] = hnInfo[1];  isPointHanging_[hnInfo[1]] = false;
01195            edgeLIDs[hanginEdgeI[v][0]] = hnInfo[2];
01196            isEdgeHanging_[hnInfo[2]] = false;
01197            edgeLIDs[hanginEdgeI[v][1]] = hnInfo[3];
01198            isEdgeHanging_[hnInfo[3]] = false;
01199            edgeLIDs[hanginEdgeI[v][2]] = hnInfo[4];  isEdgeHanging_[hnInfo[4]] = false;
01200            // remove this from the tmp storage
01201            hangElmStore_[VertexIndex[v]].remove(cellsVertex[VertexI[v]]);
01202       }
01203     }
01204     SUNDANCE_MSG3(verb() , " refineCell bef. vertexLIDs:" << vertexLIDs );
01205     SUNDANCE_MSG3(verb() , " refineCell bef. edgeLIDs:" << edgeLIDs );
01206 
01207     // create all vertexes, those which are not created
01208     for (int v = 0 ; v < 16 ; v++){
01209       // create vertex if necessary
01210       if (vertexLIDs[v] < 0){
01211         // this means vertex is not created we create now
01212         Array<int> maxCoFacets(4,-1);
01213         // add the hanging node
01214         int vLID = nrElem_[0];
01215           addVertex( nrElem_[0] , vertexOwner[v] , vertexIsHanging[v] ,
01216                      p[0] + vertex_X[v]*h[0] , p[1] + vertex_Y[v]*h[1] , maxCoFacets );
01217           vertexLIDs[v] = vLID;
01218         // if vertex is hanging add to hangElmStore_
01219           if (vertexIsHanging[v]){
01220             Array<int>& hinf = hangingInfo[hVertexVertexIndex[v]];
01221             if (hinf.size() < 1) hinf.resize(5,-1);
01222             hinf[hVertexIndex[v]] = vLID;
01223             // for hanging Vertexes we might add the parent neighbor cell twice as maxCoFacet
01224             if ( (v == 1) || ( v==2 )) {  pointMaxCoF_[vertexLIDs[v]][1] = edgeMaxCoF_[cellsEdges[1]][0];
01225                                           pointMaxCoF_[vertexLIDs[v]][3] = edgeMaxCoF_[cellsEdges[1]][0]; }
01226             if ( (v == 4) || ( v==8 )) {  pointMaxCoF_[vertexLIDs[v]][2] = edgeMaxCoF_[cellsEdges[0]][0];
01227                                           pointMaxCoF_[vertexLIDs[v]][3] = edgeMaxCoF_[cellsEdges[0]][0]; }
01228             if ( (v == 7) || ( v==11 )) {  pointMaxCoF_[vertexLIDs[v]][0] = edgeMaxCoF_[cellsEdges[3]][1];
01229                                            pointMaxCoF_[vertexLIDs[v]][1] = edgeMaxCoF_[cellsEdges[3]][1]; }
01230             if ( (v == 13) || ( v==14 )) {  pointMaxCoF_[vertexLIDs[v]][0] = edgeMaxCoF_[cellsEdges[2]][1];
01231                                             pointMaxCoF_[vertexLIDs[v]][2] = edgeMaxCoF_[cellsEdges[2]][1]; }
01232             //SUNDANCE_MSG3(verb() , " ParentEdgeMaxCofacet 0 v:" << v << "," << edgeMaxCoF_[cellsEdges[0]]);
01233             //SUNDANCE_MSG3(verb() , " ParentEdgeMaxCofacet 1 v:" << v << "," << edgeMaxCoF_[cellsEdges[1]]);
01234             //SUNDANCE_MSG3(verb() , " ParentEdgeMaxCofacet 2 v:" << v << "," << edgeMaxCoF_[cellsEdges[2]]);
01235             //SUNDANCE_MSG3(verb() , " ParentEdgeMaxCofacet 3 v:" << v << "," << edgeMaxCoF_[cellsEdges[3]]);
01236             //SUNDANCE_MSG3(verb() , " vertexLIDs[v]:" << vertexLIDs[v] << ", Maxcof:" << pointMaxCoF_[vertexLIDs[v]] );
01237             //pointMaxCoF_[vertexLIDs[v]][0] = -1;
01238           }
01239       }
01240       // update maxCoFacet info (no additional information is needed)
01241       for (int hh = 0 ; hh < 4 ; hh++){
01242         SUNDANCE_MSG3(verb() , " vertexMaxCoFacet[v][hh]:" << vertexMaxCoFacet[v][hh] << " , vertexLIDs[v]:"<< vertexLIDs[v] );
01243         if (vertexMaxCoFacet[v][hh] >= 0)
01244           pointMaxCoF_[vertexLIDs[v]][hh] = nrElem_[2] + vertexMaxCoFacet[v][hh];
01245       }
01246       SUNDANCE_MSG3(verb() , " MaxCoFac point:" << vertexLIDs[v] << " , MaxCoFac:"<< pointMaxCoF_[vertexLIDs[v]] );
01247     }
01248     SUNDANCE_MSG3(verb() , " refineCell after Vertex creation vertexLIDs:" << vertexLIDs );
01249 
01250     // create all edges , those which are not created
01251     for (int e = 0 ; e < 24 ; e++){
01252       // create edge if necessary
01253       if (edgeLIDs[e] < 0){
01254         Array<int> maxCoFacets(2,-1);
01255         Array<int> edgeVertexLIDs(2,-1);
01256         edgeVertexLIDs[0] = vertexLIDs[edgeVertexes[e][0]];
01257         edgeVertexLIDs[1] = vertexLIDs[edgeVertexes[e][1]];
01258         int eLID = nrElem_[1];
01259         addEdge( nrElem_[1] , edgeOwner[e] , edgeIsHanging[e] , edgeVertex[e] ,
01260             edgePBnd[e] , edgeMBnd[e] ,  edgeVertexLIDs , maxCoFacets );
01261         edgeLIDs[e] = eLID;
01262       //if edge is hanging add to hangElmStore_
01263         if (edgeIsHanging[e]){
01264             Array<int>& hinf = hangingInfo[hEdgeVertexIndex[e]];
01265             if (hinf.size() < 1) hinf.resize(5,-1);
01266             SUNDANCE_MSG3(verb() , " HNI e:" << e << ", hEdgeIndex[e]:" << hEdgeIndex[e] );
01267             hinf[2+hEdgeIndex[e]] = eLID;
01268             // assign MaxCoefs only when is not Mesh boundary
01269             if ( edgeMBnd[e] == false){
01270                 // add maxCoFs from parent edge, so that hanging edges will have also 2 maxCoFs (for boundary)
01271               edgeMaxCoF_[edgeLIDs[e]][offsEdgeParentMaxCoFacet[e]] =
01272                   edgeMaxCoF_[cellsEdges[indexEdgeParentMaxCoFacet[e]]][offsEdgeParentMaxCoFacet[e]];
01273             }
01274         }
01275       }
01276       // update maxCoFacet info for this edge
01277       for (int hh = 0 ; hh < 2 ; hh++){
01278         //SUNDANCE_MSG3(verb() , " edgeMaxCoFacet[e][hh]:" << edgeMaxCoFacet[e][hh] << " , edgeLIDs[e]:"<< edgeLIDs[e] );
01279         if (edgeMaxCoFacet[e][hh] >= 0)
01280           edgeMaxCoF_[edgeLIDs[e]][hh] = nrElem_[2] + edgeMaxCoFacet[e][hh];
01281       }
01282       //SUNDANCE_MSG3(verb() , " MaxCoFac edge:" << edgeLIDs[e] << " , MaxCoFac:"<< edgeMaxCoF_[edgeLIDs[e]] );
01283     }
01284     SUNDANCE_MSG3(verb() , " refineCell after Edges creation edgeLIDs:" << edgeLIDs );
01285 
01286     // add all 9 cells
01287     for (int c = 0 ; c < 9 ; c++){
01288       Array<int> eLIDs(4,-1);
01289       Array<int> vLIDs(4,-1);
01290       vLIDs[0] = vertexLIDs[refinedCellsVertexes[c][0]];  vLIDs[1] = vertexLIDs[refinedCellsVertexes[c][1]];
01291       vLIDs[2] = vertexLIDs[refinedCellsVertexes[c][2]];  vLIDs[3] = vertexLIDs[refinedCellsVertexes[c][3]];
01292       eLIDs[0] = edgeLIDs[refinedCellsEdges[c][0]]; eLIDs[1] = edgeLIDs[refinedCellsEdges[c][1]];
01293       eLIDs[2] = edgeLIDs[refinedCellsEdges[c][2]]; eLIDs[3] = edgeLIDs[refinedCellsEdges[c][3]];
01294       // add cell
01295       cellLIDs[c] = nrElem_[2];
01296         addCell( nrElem_[2] , cellOwner , c , cellLID , cellLevel_[cellLID] + 1 , eLIDs , vLIDs );
01297     }
01298 
01299     SUNDANCE_MSG3(verb() , " ---- Adding hanging node information ----- " );
01300 
01301     if ( (hangElmStore_[0].containsKey(cellsPoints_[cellLID][0]) == false) && ( hangingInfo[0].size() > 0 ))
01302     {
01303       hangElmStore_[0].put(cellsPoints_[cellLID][0],hangingInfo[0]);
01304       //SUNDANCE_MSG3( verb() , " Store array 1 : " << hangingInfo[0] );
01305     }
01306     if ( (hangElmStore_[1].containsKey(cellsPoints_[cellLID][0]) == false) && ( hangingInfo[1].size() > 0 ))
01307     {
01308       hangElmStore_[1].put(cellsPoints_[cellLID][0],hangingInfo[1]);
01309       //SUNDANCE_MSG3( verb() , " Store array 2 : " << hangingInfo[1] );
01310     }
01311     if ( (hangElmStore_[1].containsKey(cellsPoints_[cellLID][1]) == false) && ( hangingInfo[2].size() > 0 ))
01312     {
01313       hangElmStore_[1].put(cellsPoints_[cellLID][1],hangingInfo[2]);
01314       //SUNDANCE_MSG3( verb() , " Store array 3 : " << hangingInfo[2] );
01315     }
01316     if ( (hangElmStore_[0].containsKey(cellsPoints_[cellLID][2]) == false) && ( hangingInfo[3].size() > 0 ))
01317     {
01318       hangElmStore_[0].put(cellsPoints_[cellLID][2],hangingInfo[3]);
01319       //SUNDANCE_MSG3( verb() , " Store array 4 : " << hangingInfo[3] );
01320     }
01321 
01322     SUNDANCE_MSG3(verb() , " ---- Refinement cell DONE , mark cell as not leaf and store children LID ----");
01323     isCellLeaf_[cellLID] = false;
01324     // store the children of the parent cell
01325     cellsChildren_[cellLID] = cellLIDs;
01326 }
01327 
01328 // -----------
01329 void HNMesh2D::createLeafNumbering(){
01330 
01331   // set all leaf numbers to -1
01332 
01333   // - iterate trough the mesh and in the leaf cells , distribute leaf numbering
01334   // , detect if one cell is leaf ()
01335   // , have a tree similar tree traversal ... todo: later
01336 
01337   SUNDANCE_MSG3(verb() , "HNMesh2D::createLeafNumbering nrPoint:" << nrElem_[0] << " , nrEdge:" << nrElem_[1] << ", nrCell:" << nrElem_[2]);
01338   // we resize the leafID - > global
01339   vertexGIDToLeafMapping_.resize(nrElem_[0],-1);
01340   for (int dd = 0 ; dd < nrElem_[0] ; dd++) vertexGIDToLeafMapping_[dd] = -1;
01341   vertexLeafToGIDMapping_.resize(nrElem_[0],-1);
01342   for (int dd = 0 ; dd < nrElem_[0] ; dd++) vertexLeafToGIDMapping_[dd] = -1;
01343 
01344   edgeGIDToLeafMapping_.resize(nrElem_[1],-1);
01345   for (int dd = 0 ; dd < nrElem_[1] ; dd++) edgeGIDToLeafMapping_[dd] = -1;
01346   edgeLeafToGIDMapping_.resize(nrElem_[1],-1);
01347   for (int dd = 0 ; dd < nrElem_[1] ; dd++) edgeLeafToGIDMapping_[dd] = -1;
01348 
01349   cellGIDToLeafMapping_.resize(nrElem_[2],-1);
01350   for (int dd = 0 ; dd < nrElem_[2] ; dd++) cellGIDToLeafMapping_[dd] = -1;
01351   cellLeafToGIDMapping_.resize(nrElem_[2],-1);
01352   for (int dd = 0 ; dd < nrElem_[2] ; dd++) cellLeafToGIDMapping_[dd] = -1;
01353 
01354   nrVertexLeafGID_ = 0; nrCellLeafGID_ = 0; nrEdgeLeafGID_ = 0;
01355 
01356   nrVertexLeafLID_ = 0; nrCellLeafLID_ = 0; nrEdgeLeafLID_ = 0;
01357   vertexLIDToLeafMapping_.resize(nrElem_[0],-1);
01358   for (int dd = 0 ; dd < nrElem_[0] ; dd++) vertexLIDToLeafMapping_[dd] = -1;
01359   vertexLeafToLIDMapping_.resize(nrElem_[0],-1);
01360   for (int dd = 0 ; dd < nrElem_[0] ; dd++) vertexLeafToLIDMapping_[dd] = -1;
01361 
01362   edgeLIDToLeafMapping_.resize(nrElem_[1],-1);
01363   for (int dd = 0 ; dd < nrElem_[1] ; dd++) edgeLIDToLeafMapping_[dd] = -1;
01364   edgeLeafToLIDMapping_.resize(nrElem_[1],-1);
01365   for (int dd = 0 ; dd < nrElem_[1] ; dd++) edgeLeafToLIDMapping_[dd] = -1;
01366 
01367   cellLIDToLeafMapping_.resize(nrElem_[2],-1);
01368   for (int dd = 0 ; dd < nrElem_[2] ; dd++) cellLIDToLeafMapping_[dd] = -1;
01369   cellLeafToLIDMapping_.resize(nrElem_[2],-1);
01370   for (int dd = 0 ; dd < nrElem_[2] ; dd++) cellLeafToLIDMapping_[dd] = -1;
01371 
01372   SUNDANCE_MSG3(verb() , "HNMesh2D::createLeafNumbering , start assigning leaf numbers");
01373 
01374   for (int ind = 0 ; ind < nrElem_[0] ; ind++){
01375     //SUNDANCE_MSG3(verb() , "HNMesh2D::createLeafNumbering point TID :" << ind << " maxCoFac: " << pointMaxCoF_[ind]);
01376   }
01377 
01378   // look for those leaf cells which points have a cell which maxCoFacet owner = myRank_
01379   // only those will have an LID
01380   Array<bool> hasCellLID(nrElem_[2],false);
01381 
01382   for (int ind = 0 ; ind < nrElem_[2] ; ind++){
01383     Array<int>& vertexIDs = cellsPoints_[ind];
01384     hasCellLID[ind] = false;
01385     for (int v = 0 ; v < 4 ; v++){
01386       Array<int>& maxCoFacet = pointMaxCoF_[vertexIDs[v]];
01387       hasCellLID[ind] =  ( hasCellLID[ind]
01388           || ( (maxCoFacet[0] >= 0) && (elementOwner_[2][maxCoFacet[0]] == myRank_) )
01389                     || ( (maxCoFacet[1] >= 0) && (elementOwner_[2][maxCoFacet[1]] == myRank_) )
01390                     || ( (maxCoFacet[2] >= 0) && (elementOwner_[2][maxCoFacet[2]] == myRank_) )
01391                     || ( (maxCoFacet[3] >= 0) && (elementOwner_[2][maxCoFacet[3]] == myRank_) ) ) ;
01392       //SUNDANCE_MSG3(verb() , " Point ID"<< vertexIDs[v] << ", MacCoFacet:" << maxCoFacet);
01393 
01394       // add cells with hanging nodes which have contribution to element which are owned by this processor
01395       // if vertex is hanging look into the parent cell at the same index and if the owner is myRank_ then add
01396       // to the cells which should be processed
01397       if ( (hasCellLID[ind] == false) && (isPointHanging_[vertexIDs[v]] == true)){
01398         int parentID = parentCellLID_[ind];
01399         Array<int>& parentVertexIDs = cellsPoints_[parentID];
01400         hasCellLID[ind] = hasCellLID[ind] || (elementOwner_[0][parentVertexIDs[v]] == myRank_);
01401       }
01402     }
01403     SUNDANCE_MSG3(verb() , "HNMesh2D::createLeafNumbering Cell ID :" << ind << " should be LID: " << hasCellLID[ind] <<
01404         " ,isCellLeaf_[ind]:" << isCellLeaf_[ind]);
01405   }
01406 
01407   //  treat special case, so that each hanging element has its parents
01408   // if we add one cell check hanging face, then add the maxCoF from the parent face if is leaf
01409   // if this is not successful then do the same thing for edges
01410   // - from each hanging edge there should be at least one cell on this processor which contains that parent edge !
01411   bool check_Ghost_cells = true;
01412   while (check_Ghost_cells){
01413     check_Ghost_cells = false;
01414       for (int ind = 0 ; ind < nrElem_[2] ; ind++){
01415        if ( (hasCellLID[ind] == true) && (elementOwner_[2][ind] != myRank_ ) ){
01416         // check edges
01417         Array<int>& edgeIDs = cellsEdges_[ind];
01418         // we have this if only
01419           for (int ii = 0 ; ii < 4 ; ii++ ){
01420           // if the face is hanging and does not belong to me
01421           if (isEdgeHanging_[edgeIDs[ii]] && ( elementOwner_[1][edgeIDs[ii]] != myRank_)){
01422                     // get parent cells same face
01423           int parentCell = parentCellLID_[ind];
01424           Array<int>& parentEdgesIDs = cellsEdges_[parentCell];
01425           for (int f = 0 ; f < 2 ; f++)
01426           if ( ( edgeMaxCoF_[parentEdgesIDs[ii]][f] >= 0 ) &&
01427              ( elementOwner_[2][ edgeMaxCoF_[parentEdgesIDs[ii]][f] ] != myRank_ ) &&
01428              ( hasCellLID[edgeMaxCoF_[parentEdgesIDs[ii]][f]] == false)   &&
01429              ( isCellLeaf_[edgeMaxCoF_[parentEdgesIDs[ii]][f]] )
01430              ){
01431             hasCellLID[edgeMaxCoF_[parentEdgesIDs[ii]][f]] = true;
01432             check_Ghost_cells = true;
01433           }
01434           }
01435          } // from loop
01436        }
01437       }
01438   }
01439 
01440   // we also have to list the cells which are not owned by the processor
01441   for (int ind = 0 ; ind < nrElem_[2] ; ind++)
01442   {
01443      // GID numbering
01444      // if cell is leaf and if is inside the computational domain
01445          if ( (isCellLeaf_[ind] == true) && (!isCellOut_[ind]) )
01446          {
01447            Array<int>& vertexIDs = cellsPoints_[ind];
01448              for (int v = 0; v < 4 ; v++)
01449              {
01450               SUNDANCE_MSG3(verb() , " createLeafGIDNumbering  vertexIDs[v]:" << vertexIDs[v] );
01451               if (vertexGIDToLeafMapping_[vertexIDs[v]] < 0)
01452               {
01453                  SUNDANCE_MSG3(verb() , " createLeafGIDNumbering -> VertexID:" << vertexIDs[v] << " , nrVertexLeafGID_:" << nrVertexLeafGID_ );
01454                  vertexLeafToGIDMapping_[nrVertexLeafGID_] = vertexIDs[v];
01455                  vertexGIDToLeafMapping_[vertexIDs[v]] = nrVertexLeafGID_;
01456                  nrVertexLeafGID_++;
01457               }
01458              }
01459            Array<int>& edgeIDs = cellsEdges_[ind];
01460            // for each edge check weather it already has a leaf index, if not create one
01461            for (int e = 0; e < 4 ; e++)
01462            {
01463              //SUNDANCE_MSG3(verb() , " createLeafNumbering  edgeLIDs[e]:" << edgeLIDs[e] );
01464              if (edgeGIDToLeafMapping_[edgeIDs[e]] < 0)
01465              {
01466                SUNDANCE_MSG3(verb() , " createLeafGIDNumbering -> edgeID:" << edgeIDs[e] << " , nrEdgeLeafGID_:" << nrEdgeLeafGID_ );
01467                //SUNDANCE_MSG3(verb() , " MaxCoFacet:" << edgeMaxCoF_[edgeLIDs[e]] << " edgeVertex:" << edgeVertex_[edgeLIDs[e]]);
01468                edgeLeafToGIDMapping_[nrEdgeLeafGID_] = edgeIDs[e];
01469                edgeGIDToLeafMapping_[edgeIDs[e]] = nrEdgeLeafGID_;
01470                nrEdgeLeafGID_++;
01471              }
01472            }
01473            // create leaf index for the leaf cell
01474        SUNDANCE_MSG3(verb() , " createLeafGIDNumbering CELL cellID:" << ind << " , nrCellLeafGID_:" << nrCellLeafGID_ );
01475            cellLeafToGIDMapping_[nrCellLeafGID_] = ind;
01476            cellGIDToLeafMapping_[ind] = nrCellLeafGID_;
01477            nrCellLeafGID_++;
01478 
01479            // LID numbering
01480            // create leaf LID numbering , if this cell needs to be processed
01481            if (hasCellLID[ind]){
01482              // vertex
01483                  for (int v = 0; v < 4 ; v++)
01484                  {
01485                   if (vertexLIDToLeafMapping_[vertexIDs[v]] < 0)
01486                   {
01487                      SUNDANCE_MSG3(verb() , " createLeafLIDNumbering -> VertexID:" << vertexIDs[v] << " , nrVertexLeafLID_:" << nrVertexLeafLID_ );
01488                      vertexLeafToLIDMapping_[nrVertexLeafLID_] = vertexIDs[v];
01489                      vertexLIDToLeafMapping_[vertexIDs[v]] = nrVertexLeafLID_;
01490                      nrVertexLeafLID_++;
01491                   }
01492                  }
01493                // for each edge check weather it already has a leaf index, if not create one
01494                for (int e = 0; e < 4 ; e++)
01495                {
01496                  if (edgeLIDToLeafMapping_[edgeIDs[e]] < 0)
01497                  {
01498                    SUNDANCE_MSG3(verb() , " createLeafLIDNumbering -> edgeID:" << edgeIDs[e] << " , nrEdgeLeafLID_:" << nrEdgeLeafLID_ );
01499                    edgeLeafToLIDMapping_[nrEdgeLeafLID_] = edgeIDs[e];
01500                    edgeLIDToLeafMapping_[edgeIDs[e]] = nrEdgeLeafLID_;
01501                    nrEdgeLeafLID_++;
01502                  }
01503                }
01504                // create leaf index for the leaf cell
01505                SUNDANCE_MSG3(verb() , " createLeafLIDNumbering CELL cellID:" << ind << " , nrCellLeafLID_:" << nrCellLeafLID_ );
01506                cellLeafToLIDMapping_[nrCellLeafLID_] = ind;
01507                cellLIDToLeafMapping_[ind] = nrCellLeafLID_;
01508                nrCellLeafLID_++;
01509            }
01510          }
01511   }
01512   SUNDANCE_MSG3(verb() , "HNMesh2D::createLeafNumbering , DONE");
01513 }
01514 
01515 
01516 // ====================================== OTHER LEAF NUMBERING ALGORITHM ==================
01517 
01518 int HNMesh2D::estimateCellLoad(int ID){
01519   int rtn = 0;
01520   if (isCellLeaf_[ID]){
01521     if (!isCellOut_[ID]) rtn = 1;
01522   } else {
01523     // for each child call recursivly the function
01524     for (int r = 0 ; r < (int)cellsChildren_[ID].size() ; r++){
01525       rtn = rtn + estimateCellLoad(cellsChildren_[ID][r]);
01526     }
01527   }
01528     return rtn;
01529 }
01530 
01531 /** mark the cells and its facets for one processor*/
01532 void HNMesh2D::markCellsAndFacets(int cellID , int procID){
01533   // mark the cell and the facets
01534   if (elementOwner_[2][cellID] < 0)  { elementOwner_[2][cellID] = procID; }
01535   //SUNDANCE_MSG3(verb() , "mark cell: " << cellID );
01536   if (elementOwner_[1][cellsEdges_[cellID][0]] < 0 ) { elementOwner_[1][cellsEdges_[cellID][0]] = procID;}
01537   if (elementOwner_[1][cellsEdges_[cellID][1]] < 0 ) { elementOwner_[1][cellsEdges_[cellID][1]] = procID;}
01538   if (elementOwner_[1][cellsEdges_[cellID][2]] < 0 ) { elementOwner_[1][cellsEdges_[cellID][2]] = procID;}
01539   if (elementOwner_[1][cellsEdges_[cellID][3]] < 0 ) { elementOwner_[1][cellsEdges_[cellID][3]] = procID;}
01540   //SUNDANCE_MSG3(verb() , " ,mark edge: " << cellsEdges_[cellID][0] << " ,mark edge: " << cellsEdges_[cellID][1]
01541   //                      << " ,mark edge: " << cellsEdges_[cellID][2] << " ,mark edge: " << cellsEdges_[cellID][3]);
01542   if (elementOwner_[0][cellsPoints_[cellID][0]] < 0 ) { elementOwner_[0][cellsPoints_[cellID][0]] = procID;}
01543   if (elementOwner_[0][cellsPoints_[cellID][1]] < 0 ) { elementOwner_[0][cellsPoints_[cellID][1]] = procID;}
01544   if (elementOwner_[0][cellsPoints_[cellID][2]] < 0 ) { elementOwner_[0][cellsPoints_[cellID][2]] = procID;}
01545   if (elementOwner_[0][cellsPoints_[cellID][3]] < 0 ) { elementOwner_[0][cellsPoints_[cellID][3]] = procID;}
01546   //SUNDANCE_MSG3(verb() , " ,mark point: " << cellsPoints_[cellID][0] << " ,mark point: " << cellsPoints_[cellID][1]
01547   //                      << " ,mark point: " << cellsPoints_[cellID][2] << " ,mark point: " << cellsPoints_[cellID][3] );
01548   if (!isCellLeaf_[cellID]){
01549     // for each child cell do it recursively
01550     for (int r = 0 ; r < (int)cellsChildren_[cellID].size() ; r++){
01551       markCellsAndFacets(cellsChildren_[cellID][r] , procID);
01552     }
01553   }
01554 }
01555 
01556 void HNMesh2D::createLeafNumbering_sophisticated(){
01557 
01558   // this array shows which cell will belong to this processor
01559   Array<bool> hasCellLID(nrElem_[2],false);
01560   double total_load = 0.0;
01561   int nrCoarseCell = _res_x * _res_y;
01562   Array<int> coarseCellLoad( _res_x * _res_y , 1 );
01563 
01564   // the principle for load is that each cell is one unit load
01565   // count the total number of cells which are inside the computational domain and are leaf cells
01566   // make a space filling curve traversal and assign each cell to one processor
01567   // on the coarser level make a Z-curve traversal, and there for each cell make a recursive traversal
01568   // distribute only the coarsest cells, since the tree traversal is not continuous
01569   // "elementOwner_" has to be changed!!!
01570 
01571   for (int ind = 0 ; ind < nrElem_[2] ; ind++){
01572         if (ind < nrCoarseCell) {
01573           // estimate cells load
01574           coarseCellLoad[ind] = estimateCellLoad(ind);
01575         }
01576     if ((isCellLeaf_[ind] == true) && (!isCellOut_[ind]) )
01577     { total_load = total_load + 1 ; }
01578   }
01579 
01580   SUNDANCE_MSG3(verb() , "total_load = " << total_load << " , nrCell = " << nrElem_[2]);
01581 
01582   // generate the space filling curve traversal for a given level and unit square
01583   // and assign the coarsest cells to processors
01584 #ifdef _MSC_VER
01585   int levelM = ::ceil( std::max<double>( ::log2(_res_x) , ::log2(_res_y ) ) );
01586 #else
01587   int levelM = ::ceil( ::fmax( ::log2(_res_x) , ::log2(_res_y ) ) );
01588 #endif
01589   //int unitN = (int)::pow(2, levelM );
01590   Array<int> vectX1(4), vectY1(4), vectX2(4), vectY2(4);
01591   vectX1[0] = 0; vectX1[1] = (int)std::pow(2,levelM-1); vectX1[2] = 0; vectX1[3] = (int)std::pow(2,levelM-1);
01592   vectY1[0] = 0; vectY1[1] = 0; vectY1[2] = (int)std::pow(2,levelM-1); vectY1[3] = (int)std::pow(2,levelM-1);
01593   vectX2[0] = 0; vectX2[1] = (int)std::pow(2,levelM-1); vectX2[2] = 0; vectX2[3] = (int)std::pow(2,levelM-1);
01594   vectY2[0] = 0; vectY2[1] = 0; vectY2[2] = (int)std::pow(2,levelM-1); vectY2[3] = (int)std::pow(2,levelM-1);
01595   int addX[4] = { 0 , 1 , 0 , 1};
01596   int addY[4] = { 0 , 0 , 1 , 1};
01597   Array<int> *inX = &vectX1 , *inY = &vectY1 , *outX = &vectX2 , *outY = &vectY2 , *tmpVectP;
01598   int levelActual = levelM - 2;
01599   // this method generates the index for a unit square Z-curve traversal
01600   while (levelActual >= 0){
01601     outX->resize( 4 * inX->size() );
01602     outY->resize( 4 * inY->size() );
01603     int cI = 0 , addO = (int)std::pow(2,levelActual);
01604     SUNDANCE_MSG3(verb() , " outX->size():" << outX->size() << ", levelActual:" << levelActual << " , addO:" << addO);
01605     // here create the 4 recursive cells
01606     for (int ce = 0 ; ce < inX->size() ; ce++){
01607       (*outX)[cI+0] = (*inX)[ce] + addO*addX[0];
01608       (*outX)[cI+1] = (*inX)[ce] + addO*addX[1];
01609       (*outX)[cI+2] = (*inX)[ce] + addO*addX[2];
01610       (*outX)[cI+3] = (*inX)[ce] + addO*addX[3];
01611       (*outY)[cI+0] = (*inY)[ce] + addO*addY[0];
01612       (*outY)[cI+1] = (*inY)[ce] + addO*addY[1];
01613       (*outY)[cI+2] = (*inY)[ce] + addO*addY[2];
01614       (*outY)[cI+3] = (*inY)[ce] + addO*addY[3];
01615       cI = cI + 4;
01616     }
01617     SUNDANCE_MSG3(verb() , " EX: " << (*outX)[0] << " , " << (*outX)[1] << " , " << (*outX)[2]);
01618     SUNDANCE_MSG3(verb() , " EY: " << (*outY)[0] << " , " << (*outY)[1] << " , " << (*outY)[2]);
01619     // decrease the level
01620     levelActual = levelActual - 1;
01621     tmpVectP = inX; inX = outX; outX = tmpVectP;
01622     tmpVectP = inY; inY = outY; outY = tmpVectP;
01623   }
01624   // switch the vectors back once we are finished
01625   tmpVectP = inX; inX = outX; outX = tmpVectP;
01626   tmpVectP = inY; inY = outY; outY = tmpVectP;
01627 
01628   // unmark the cells owners
01629   for (int tmp = 0 ; tmp < nrElem_[0] ; tmp++ ){ elementOwner_[0][tmp] = -1; }
01630   for (int tmp = 0 ; tmp < nrElem_[1] ; tmp++ ){ elementOwner_[1][tmp] = -1; }
01631   for (int tmp = 0 ; tmp < nrElem_[2] ; tmp++ ){ elementOwner_[2][tmp] = -1; }
01632 
01633   //mark the cells, vertex and edge to which cell they belong, recursively for each cell
01634   int coarseCellID , actProcID = 0 , actualLoad = 0;
01635   double loadPerProc = (double)total_load / (double)nrProc_ , diff_load = 0.0;
01636   for (int ind = 0 ; ind < outX->size() ; ind++){
01637     // first test the combinaiton if this is in the range
01638         if ( ((*outX)[ind] < _res_x) && ((*outY)[ind] < _res_y) ){
01639           // !!!! --- here is very important that we compute the right index
01640           coarseCellID = ((*outX)[ind])*_res_y + ((*outY)[ind]);
01641           SUNDANCE_MSG3(verb(),"Z-curve trav. ind:" << ind << " , coarseCellID:" << coarseCellID << " , indX:" << (*outX)[ind] << " , indY:" << (*outY)[ind]);
01642           //the level of this cell with the ID should be zero
01643           TEUCHOS_TEST_FOR_EXCEPTION( cellLevel_[coarseCellID] > 0 , std::logic_error, " coarseCellID:" << coarseCellID << " has level:" << cellLevel_[coarseCellID] );
01644           markCellsAndFacets( coarseCellID , actProcID);
01645           actualLoad = actualLoad + coarseCellLoad[coarseCellID];
01646           // increment the processor if necessary
01647         if (((double)actualLoad >= (loadPerProc - 1e-8 - diff_load)) && ( actProcID < nrProc_-1 )){
01648           SUNDANCE_MSG3(verb() , "Increase CPU , actualLoad:" << actualLoad << " loadPerProc:" << loadPerProc );
01649           // compensate the load difference for the next CPU
01650           diff_load = actualLoad - loadPerProc;
01651           actProcID = actProcID + 1;
01652           actualLoad = 0;
01653         }
01654         }
01655   }
01656 
01657   // unmark the cells owners
01658   SUNDANCE_MSG3(verb()," nrElem_[0]:" << nrElem_[0] << " , nrElem_[1]:" << nrElem_[1] << " , nrElem_[2]" << nrElem_[2]);
01659   for (int tmp = 0 ; tmp < nrElem_[0] ; tmp++ ){ TEUCHOS_TEST_FOR_EXCEPTION( elementOwner_[0][tmp] < 0 , std::logic_error, " 0 tmp:" << tmp); }
01660   for (int tmp = 0 ; tmp < nrElem_[1] ; tmp++ ){ TEUCHOS_TEST_FOR_EXCEPTION( elementOwner_[1][tmp] < 0 , std::logic_error, " 1 tmp:" << tmp); }
01661   for (int tmp = 0 ; tmp < nrElem_[2] ; tmp++ ){ TEUCHOS_TEST_FOR_EXCEPTION( elementOwner_[2][tmp] < 0 , std::logic_error, " 2 tmp:" << tmp); }
01662 
01663 // ==== what comes here is a code duplication from the method above ===========
01664   // set all leaf numbers to -1
01665   // - iterate trough the mesh and in the leaf cells , distribute leaf numbering
01666   // , detect if one cell is leaf ()
01667   // , have a tree similar tree traversal ... todo: later
01668 
01669   SUNDANCE_MSG3(verb() , "HNMesh2D::createLeafNumbering nrPoint:" << nrElem_[0] << " , nrEdge:" << nrElem_[1] << ", nrCell:" << nrElem_[2]);
01670   // we resize the leafID - > global
01671   vertexGIDToLeafMapping_.resize(nrElem_[0],-1);
01672   for (int dd = 0 ; dd < nrElem_[0] ; dd++) vertexGIDToLeafMapping_[dd] = -1;
01673   vertexLeafToGIDMapping_.resize(nrElem_[0],-1);
01674   for (int dd = 0 ; dd < nrElem_[0] ; dd++) vertexLeafToGIDMapping_[dd] = -1;
01675 
01676   edgeGIDToLeafMapping_.resize(nrElem_[1],-1);
01677   for (int dd = 0 ; dd < nrElem_[1] ; dd++) edgeGIDToLeafMapping_[dd] = -1;
01678   edgeLeafToGIDMapping_.resize(nrElem_[1],-1);
01679   for (int dd = 0 ; dd < nrElem_[1] ; dd++) edgeLeafToGIDMapping_[dd] = -1;
01680 
01681   cellGIDToLeafMapping_.resize(nrElem_[2],-1);
01682   for (int dd = 0 ; dd < nrElem_[2] ; dd++) cellGIDToLeafMapping_[dd] = -1;
01683   cellLeafToGIDMapping_.resize(nrElem_[2],-1);
01684   for (int dd = 0 ; dd < nrElem_[2] ; dd++) cellLeafToGIDMapping_[dd] = -1;
01685 
01686   nrVertexLeafGID_ = 0; nrCellLeafGID_ = 0; nrEdgeLeafGID_ = 0;
01687 
01688   nrVertexLeafLID_ = 0; nrCellLeafLID_ = 0; nrEdgeLeafLID_ = 0;
01689   vertexLIDToLeafMapping_.resize(nrElem_[0],-1);
01690   for (int dd = 0 ; dd < nrElem_[0] ; dd++) vertexLIDToLeafMapping_[dd] = -1;
01691   vertexLeafToLIDMapping_.resize(nrElem_[0],-1);
01692   for (int dd = 0 ; dd < nrElem_[0] ; dd++) vertexLeafToLIDMapping_[dd] = -1;
01693 
01694   edgeLIDToLeafMapping_.resize(nrElem_[1],-1);
01695   for (int dd = 0 ; dd < nrElem_[1] ; dd++) edgeLIDToLeafMapping_[dd] = -1;
01696   edgeLeafToLIDMapping_.resize(nrElem_[1],-1);
01697   for (int dd = 0 ; dd < nrElem_[1] ; dd++) edgeLeafToLIDMapping_[dd] = -1;
01698 
01699   cellLIDToLeafMapping_.resize(nrElem_[2],-1);
01700   for (int dd = 0 ; dd < nrElem_[2] ; dd++) cellLIDToLeafMapping_[dd] = -1;
01701   cellLeafToLIDMapping_.resize(nrElem_[2],-1);
01702   for (int dd = 0 ; dd < nrElem_[2] ; dd++) cellLeafToLIDMapping_[dd] = -1;
01703 
01704   SUNDANCE_MSG3(verb() , "HNMesh2D::createLeafNumbering , start assigning leaf numbers");
01705 
01706   for (int ind = 0 ; ind < nrElem_[2] ; ind++){
01707     Array<int>& vertexIDs = cellsPoints_[ind];
01708     hasCellLID[ind] = false;
01709     for (int v = 0 ; v < 4 ; v++){
01710       Array<int>& maxCoFacet = pointMaxCoF_[vertexIDs[v]];
01711       hasCellLID[ind] =  ( hasCellLID[ind]
01712           || ( (maxCoFacet[0] >= 0) && (elementOwner_[2][maxCoFacet[0]] == myRank_) )
01713                     || ( (maxCoFacet[1] >= 0) && (elementOwner_[2][maxCoFacet[1]] == myRank_) )
01714                     || ( (maxCoFacet[2] >= 0) && (elementOwner_[2][maxCoFacet[2]] == myRank_) )
01715                     || ( (maxCoFacet[3] >= 0) && (elementOwner_[2][maxCoFacet[3]] == myRank_) ) ) ;
01716       //SUNDANCE_MSG3(verb() , " Point ID"<< vertexIDs[v] << ", MacCoFacet:" << maxCoFacet);
01717 
01718       // add cells with hanging nodes which have contribution to element which are owned by this processor
01719       // if vertex is hanging look into the parent cell at the same index and if the owner is myRank_ then add
01720       // to the cells which should be processed
01721       if ( (hasCellLID[ind] == false) && (isPointHanging_[vertexIDs[v]] == true)){
01722         int parentID = parentCellLID_[ind];
01723         Array<int>& parentVertexIDs = cellsPoints_[parentID];
01724         hasCellLID[ind] = hasCellLID[ind] || (elementOwner_[0][parentVertexIDs[v]] == myRank_);
01725       }
01726     }
01727     SUNDANCE_MSG3(verb() , "HNMesh2D::createLeafNumbering Cell ID :" << ind << " should be LID: " << hasCellLID[ind] <<
01728         " ,isCellLeaf_[ind]:" << isCellLeaf_[ind]);
01729   }
01730 
01731   //  treat special case, so that each hanging element has its parents
01732   // if we add one cell check hanging face, then add the maxCoF from the parent face if is leaf
01733   // if this is not successful then do the same thing for edges
01734   // - from each hanging edge there should be at least one cell on this processor which contains that parent edge !
01735   bool check_Ghost_cells = true;
01736   while (check_Ghost_cells){
01737     check_Ghost_cells = false;
01738       for (int ind = 0 ; ind < nrElem_[2] ; ind++){
01739        if ( (hasCellLID[ind] == true) && (elementOwner_[2][ind] != myRank_ ) ){
01740         // check edges
01741         Array<int>& edgeIDs = cellsEdges_[ind];
01742         // we have this if only
01743           for (int ii = 0 ; ii < 4 ; ii++ ){
01744           // if the face is hanging and does not belong to me
01745           if (isEdgeHanging_[edgeIDs[ii]] && ( elementOwner_[1][edgeIDs[ii]] != myRank_)){
01746                     // get parent cells same face
01747           int parentCell = parentCellLID_[ind];
01748           Array<int>& parentEdgesIDs = cellsEdges_[parentCell];
01749           for (int f = 0 ; f < 2 ; f++)
01750           if ( ( edgeMaxCoF_[parentEdgesIDs[ii]][f] >= 0 ) &&
01751              ( elementOwner_[2][ edgeMaxCoF_[parentEdgesIDs[ii]][f] ] != myRank_ ) &&
01752              ( hasCellLID[edgeMaxCoF_[parentEdgesIDs[ii]][f]] == false)   &&
01753              ( isCellLeaf_[edgeMaxCoF_[parentEdgesIDs[ii]][f]] )
01754              ){
01755             hasCellLID[edgeMaxCoF_[parentEdgesIDs[ii]][f]] = true;
01756             check_Ghost_cells = true;
01757           }
01758           }
01759          } // from loop
01760        }
01761       }
01762   }
01763 
01764   // we also have to list the cells which are not owned by the processor
01765   for (int ind = 0 ; ind < nrElem_[2] ; ind++)
01766   {
01767      // GID numbering
01768      // if cell is leaf and if is inside the computational domain
01769          if ( (isCellLeaf_[ind] == true) && (!isCellOut_[ind]) )
01770          {
01771            Array<int>& vertexIDs = cellsPoints_[ind];
01772              for (int v = 0; v < 4 ; v++)
01773              {
01774               SUNDANCE_MSG3(verb() , " createLeafGIDNumbering  vertexIDs[v]:" << vertexIDs[v] );
01775               if (vertexGIDToLeafMapping_[vertexIDs[v]] < 0)
01776               {
01777                  SUNDANCE_MSG3(verb() , " createLeafGIDNumbering -> VertexID:" << vertexIDs[v] << " , nrVertexLeafGID_:" << nrVertexLeafGID_ );
01778                  vertexLeafToGIDMapping_[nrVertexLeafGID_] = vertexIDs[v];
01779                  vertexGIDToLeafMapping_[vertexIDs[v]] = nrVertexLeafGID_;
01780                  nrVertexLeafGID_++;
01781               }
01782              }
01783            Array<int>& edgeIDs = cellsEdges_[ind];
01784            // for each edge check weather it already has a leaf index, if not create one
01785            for (int e = 0; e < 4 ; e++)
01786            {
01787              //SUNDANCE_MSG3(verb() , " createLeafNumbering  edgeLIDs[e]:" << edgeLIDs[e] );
01788              if (edgeGIDToLeafMapping_[edgeIDs[e]] < 0)
01789              {
01790                SUNDANCE_MSG3(verb() , " createLeafGIDNumbering -> edgeID:" << edgeIDs[e] << " , nrEdgeLeafGID_:" << nrEdgeLeafGID_ );
01791                //SUNDANCE_MSG3(verb() , " MaxCoFacet:" << edgeMaxCoF_[edgeLIDs[e]] << " edgeVertex:" << edgeVertex_[edgeLIDs[e]]);
01792                edgeLeafToGIDMapping_[nrEdgeLeafGID_] = edgeIDs[e];
01793                edgeGIDToLeafMapping_[edgeIDs[e]] = nrEdgeLeafGID_;
01794                nrEdgeLeafGID_++;
01795              }
01796            }
01797            // create leaf index for the leaf cell
01798        SUNDANCE_MSG3(verb() , " createLeafGIDNumbering CELL cellID:" << ind << " , nrCellLeafGID_:" << nrCellLeafGID_ );
01799            cellLeafToGIDMapping_[nrCellLeafGID_] = ind;
01800            cellGIDToLeafMapping_[ind] = nrCellLeafGID_;
01801            nrCellLeafGID_++;
01802 
01803            // LID numbering
01804            // create leaf LID numbering , if this cell needs to be processed
01805            if (hasCellLID[ind]){
01806              // vertex
01807                  for (int v = 0; v < 4 ; v++)
01808                  {
01809                   if (vertexLIDToLeafMapping_[vertexIDs[v]] < 0)
01810                   {
01811                      SUNDANCE_MSG3(verb() , " createLeafLIDNumbering -> VertexID:" << vertexIDs[v] << " , nrVertexLeafLID_:" << nrVertexLeafLID_ );
01812                      vertexLeafToLIDMapping_[nrVertexLeafLID_] = vertexIDs[v];
01813                      vertexLIDToLeafMapping_[vertexIDs[v]] = nrVertexLeafLID_;
01814                      nrVertexLeafLID_++;
01815                   }
01816                  }
01817                // for each edge check weather it already has a leaf index, if not create one
01818                for (int e = 0; e < 4 ; e++)
01819                {
01820                  if (edgeLIDToLeafMapping_[edgeIDs[e]] < 0)
01821                  {
01822                    SUNDANCE_MSG3(verb() , " createLeafLIDNumbering -> edgeID:" << edgeIDs[e] << " , nrEdgeLeafLID_:" << nrEdgeLeafLID_ );
01823                    edgeLeafToLIDMapping_[nrEdgeLeafLID_] = edgeIDs[e];
01824                    edgeLIDToLeafMapping_[edgeIDs[e]] = nrEdgeLeafLID_;
01825                    nrEdgeLeafLID_++;
01826                  }
01827                }
01828                // create leaf index for the leaf cell
01829                SUNDANCE_MSG3(verb() , " createLeafLIDNumbering CELL cellID:" << ind << " , nrCellLeafLID_:" << nrCellLeafLID_ );
01830                cellLeafToLIDMapping_[nrCellLeafLID_] = ind;
01831                cellLIDToLeafMapping_[ind] = nrCellLeafLID_;
01832                nrCellLeafLID_++;
01833            }
01834          }
01835   }
01836   SUNDANCE_MSG3(verb() , "HNMesh2D::createLeafNumbering , DONE");
01837 }

Site Contact