Example #1
0
//============================================================================
Epetra_CrsGraph* Ifpack_CreateOverlappingCrsMatrix(const Epetra_CrsGraph* Graph,
                                                   const int OverlappingLevel)
{

  if (OverlappingLevel == 0)
    return(0); // All done
  if (Graph->Comm().NumProc() == 1)
    return(0); // All done

  Epetra_CrsGraph* OverlappingGraph;
  Epetra_BlockMap* OverlappingMap;
  OverlappingGraph = const_cast<Epetra_CrsGraph*>(Graph);
  OverlappingMap = const_cast<Epetra_BlockMap*>(&(Graph->RowMap()));

  Epetra_CrsGraph* OldGraph;
  Epetra_BlockMap* OldMap;
  const Epetra_BlockMap* DomainMap = &(Graph->DomainMap());
  const Epetra_BlockMap* RangeMap = &(Graph->RangeMap());

  for (int level = 1; level <= OverlappingLevel ; ++level) {

    OldGraph = OverlappingGraph;
    OldMap = OverlappingMap;

    Epetra_Import* OverlappingImporter;
    OverlappingImporter = const_cast<Epetra_Import*>(OldGraph->Importer());
    OverlappingMap = new Epetra_BlockMap(OverlappingImporter->TargetMap());

    if (level < OverlappingLevel)
      OverlappingGraph = new Epetra_CrsGraph(Copy, *OverlappingMap, 0);
    else
      // On last iteration, we want to filter out all columns except
      // those that correspond
      // to rows in the graph.  This assures that our matrix is square
      OverlappingGraph = new Epetra_CrsGraph(Copy, *OverlappingMap,
                                          *OverlappingMap, 0);

    OverlappingGraph->Import(*OldGraph, *OverlappingImporter, Insert);
    if (level < OverlappingLevel)
      OverlappingGraph->FillComplete(*DomainMap, *RangeMap);
    else {
      // Copy last OverlapImporter because we will use it later
      OverlappingImporter = new Epetra_Import(*OverlappingMap, *DomainMap);
      OverlappingGraph->FillComplete(*DomainMap, *RangeMap);
    }

    if (level > 1) {
      delete OldGraph;
      delete OldMap;
    }

    delete OverlappingMap;
    OverlappingGraph->FillComplete();

  }

  return(OverlappingGraph);
}
Zoltan_CrsGraph::NewTypeRef
Zoltan_CrsGraph::
operator()( OriginalTypeRef orig )
{
  origObj_ = &orig;

  int err;

  //Setup Load Balance Object
  float version;
  char * dummy = 0;
  Zoltan::LoadBalance LB( 0, &dummy, &version );
  err = LB.Create( dynamic_cast<const Epetra_MpiComm&>(orig.Comm()).Comm() );
  if( err == ZOLTAN_OK ) err = LB.Set_Param( "LB_METHOD", "GRAPH" );
#ifdef HAVE_LIBPARMETIS
  if( err == ZOLTAN_OK ) err = LB.Set_Param( "GRAPH_PACKAGE", "PARMETIS" );
  if( err == ZOLTAN_OK ) err = LB.Set_Param( "PARMETIS_METHOD", partitionMethod_ );
#endif

  //Setup Query Object
  CrsGraph_Transpose transposeTransform;
  Epetra_CrsGraph & TransGraph = transposeTransform( orig );
  ZoltanQuery Query( orig, &TransGraph );
  if( err == ZOLTAN_OK ) err = LB.Set_QueryObject( &Query );

  if( err != ZOLTAN_OK )
  { cout << "Setup of Zoltan Load Balancing Objects FAILED!\n"; exit(0); }

  //Generate Load Balance
  int changes;
  int num_gid_entries, num_lid_entries;
  int num_import;
  ZOLTAN_ID_PTR import_global_ids, import_local_ids;
  int * import_procs;
  int num_export;
  ZOLTAN_ID_PTR export_global_ids, export_local_ids;
  int * export_procs;

  orig.Comm().Barrier();
  err = LB.Balance( &changes,
                     &num_gid_entries, &num_lid_entries,
                     &num_import, &import_global_ids, &import_local_ids, &import_procs,
                     &num_export, &export_global_ids, &export_local_ids, &export_procs );
  LB.Evaluate( 1, 0, 0, 0, 0, 0, 0 );
  orig.Comm().Barrier();

  //Generate New Element List
  int numMyElements = orig.RowMap().NumMyElements();
  vector<int> elementList( numMyElements );
  orig.RowMap().MyGlobalElements( &elementList[0] );

  int newNumMyElements = numMyElements - num_export + num_import;
  vector<int> newElementList( newNumMyElements );

  set<int> gidSet;
  for( int i = 0; i < num_export; ++i )
    gidSet.insert( export_global_ids[i] );

  //Add unmoved indices to new list
  int loc = 0;
  for( int i = 0; i < numMyElements; ++i )
    if( !gidSet.count( elementList[i] ) )
      newElementList[loc++] = elementList[i];
  
  //Add imports to end of list
  for( int i = 0; i < num_import; ++i )
    newElementList[loc+i] = import_global_ids[i];

  //Free Zoltan Data
  if( err == ZOLTAN_OK )
    err = LB.Free_Data( &import_global_ids, &import_local_ids, &import_procs,
                         &export_global_ids, &export_local_ids, &export_procs );

  //Create Import Map
  NewRowMap_ = new Epetra_Map( orig.RowMap().NumGlobalElements(),
                                           newNumMyElements,
                                           &newElementList[0],
                                           orig.RowMap().IndexBase(),
                                           orig.RowMap().Comm() );

  //Create Importer
  Epetra_Import Importer( *NewRowMap_, orig.RowMap() );

  //Create New Graph
  Epetra_CrsGraph * NewGraph = new Epetra_CrsGraph( Copy, *NewRowMap_, 0 );
  NewGraph->Import( orig, Importer, Insert );
  NewGraph->FillComplete();

  Zoltan::LoadBalance LB2( 0, &dummy, &version );
  err = LB2.Create( dynamic_cast<const Epetra_MpiComm&>(orig.Comm()).Comm() );
  if( err == ZOLTAN_OK ) err = LB2.Set_Param( "LB_METHOD", "GRAPH" );
#ifdef HAVE_LIBPARMETIS
  if( err == ZOLTAN_OK ) err = LB2.Set_Param( "GRAPH_PACKAGE", "PARMETIS" );
  if( err == ZOLTAN_OK ) err = LB2.Set_Param( "PARMETIS_METHOD", partitionMethod_ );
#endif
  CrsGraph_Transpose transTrans;
  Epetra_CrsGraph & trans2 = transTrans( *NewGraph );
  ZoltanQuery query( *NewGraph, &trans2 );
  if( err == ZOLTAN_OK ) err = LB2.Set_QueryObject( &query );
  //err = LB2.Balance( &changes,
  //                   &num_gid_entries, &num_lid_entries,
  //                   &num_import, &import_global_ids, &import_local_ids, &import_procs,
  //                   &num_export, &export_global_ids, &export_local_ids, &export_procs );
  LB2.Evaluate( 1, 0, 0, 0, 0, 0, 0 );

  newObj_ = NewGraph;

  return *NewGraph;
}
CrsGraph_SymmRCM::NewTypeRef
CrsGraph_SymmRCM::
operator()( CrsGraph_SymmRCM::OriginalTypeRef orig )
{
  origObj_ = &orig;

  int err;

  //Generate Local Transpose Graph
  CrsGraph_Transpose transposeTransform;
  Epetra_CrsGraph & trans = transposeTransform( orig );

  //Generate Local Symmetric Adj. List
  //Find Min Degree Node While at it
  int NumNodes = orig.NumMyRows();
  int * LocalRow;
  int * LocalRowTrans;
  int RowSize, RowSizeTrans;
  std::vector< std::vector<int> > AdjList( NumNodes );
  int MinDegree = NumNodes;
  int MinDegreeNode;
  for( int i = 0; i < NumNodes; ++i )
  {
    orig.ExtractMyRowView( i, RowSize, LocalRow );
    trans.ExtractMyRowView( i, RowSizeTrans, LocalRowTrans );

    std::set<int> adjSet;
    for( int j = 0; j < RowSize; ++j )
     if( LocalRow[j] < NumNodes ) adjSet.insert( LocalRow[j] );
    for( int j = 0; j < RowSizeTrans; ++j )
     if( LocalRowTrans[j] < NumNodes ) adjSet.insert( LocalRowTrans[j] );

    std::set<int>::iterator iterS = adjSet.begin();
    std::set<int>::iterator endS = adjSet.end();
    AdjList[i].resize( adjSet.size() );
    for( int j = 0; iterS != endS; ++iterS, ++j ) AdjList[i][j] = *iterS;
    
    if( AdjList[i].size() < MinDegree )
    {
      MinDegree = AdjList[i].size();
      MinDegreeNode = i;
    }
  }

  BFT * BestBFT;
  bool TooWide;

  //std::cout << "SymmRCM::bruteForce_ : " << bruteForce_ << std::endl;

  if( bruteForce_ )
  {
    int bestWidth = NumNodes;
    int bestDepth = 0;
    
    for( int i = 0; i < NumNodes; ++i )
    {
      BFT * TestBFT = new BFT( AdjList, i, NumNodes, TooWide );
      if( TestBFT->Depth() > bestDepth ||
          ( TestBFT->Depth() == bestDepth && TestBFT->Width() < bestWidth ) )
      {
        BestBFT = TestBFT;
        bestDepth = TestBFT->Depth();
        bestWidth = TestBFT->Width();
      }
      else
        delete TestBFT;
    }
  }
  else
  {
    //Construct BFT for first
    BestBFT = new BFT( AdjList, MinDegreeNode, NumNodes, TooWide );

    int MinWidth = BestBFT->Width();
    int BestWidth = MinWidth;
    int Diameter = BestBFT->Depth();
    std::vector<int> Leaves;
    BestBFT->NonNeighborLeaves( Leaves, AdjList, testLeafWidth_ );

    bool DeeperFound;
    bool NarrowerFound;
  
    bool Finished = false;

    while( !Finished )
    {
      DeeperFound = false;
      NarrowerFound = false;

      for( int i = 0; i < Leaves.size(); ++i )
      {

        BFT * TestBFT = new BFT( AdjList, Leaves[i], MinWidth, TooWide );

        if( TooWide )
          delete TestBFT;
        else
        {
          if( TestBFT->Width() < MinWidth ) MinWidth = TestBFT->Width();

          if( TestBFT->Depth() > Diameter )
          {
            delete BestBFT;
            Diameter = TestBFT->Depth();
            BestWidth = TestBFT->Width();
            BestBFT = TestBFT;
            DeeperFound = true;
            NarrowerFound = false;
          }
          else if( (TestBFT->Depth()==Diameter) && (TestBFT->Width()<BestWidth) )
          {
            delete BestBFT;
            BestWidth = TestBFT->Width();
            BestBFT = TestBFT;
            NarrowerFound = true;
          }
          else delete TestBFT;
        }
      }

      if( DeeperFound )
        BestBFT->NonNeighborLeaves( Leaves, AdjList, testLeafWidth_ );
      else if( NarrowerFound )
        Finished = true;
      else Finished = true;
    }
  }

  //std::cout << "\nSymmRCM:\n";
  //std::cout << "----------------------------\n";
  //std::cout << " Depth: " << BestBFT->Depth() << std::endl;
  //std::cout << " Width: " << BestBFT->Width() << std::endl;
  //std::cout << "----------------------------\n\n";

  std::vector<int> RCM;
  BestBFT->ReverseVector( RCM );
  for( int i = 0; i < NumNodes; ++i )
    RCM[i] = orig.RowMap().GID( RCM[i] );

  //Generate New Row Map
  RCMMap_ = new Epetra_Map( orig.RowMap().NumGlobalElements(),
                                        NumNodes,
                                        &RCM[0],
                                        orig.RowMap().IndexBase(),
                                        orig.RowMap().Comm() );

  //Generate New Col Map
  if( RCMMap_->DistributedGlobal() )
  {
    std::vector<int> colIndices = RCM;
    const Epetra_BlockMap & origColMap = orig.ColMap();

    if( origColMap.NumMyElements() > RCMMap_->NumMyElements() )
    {
      for( int i = RCMMap_->NumMyElements(); i < origColMap.NumMyElements(); ++i )
        colIndices.push_back( origColMap.GID(i) );
    }

    RCMColMap_ = new Epetra_Map( orig.ColMap().NumGlobalElements(),
                                 colIndices.size(),
                                 &colIndices[0],
                                 orig.ColMap().IndexBase(),
                                 orig.ColMap().Comm() );
  }
  else
    RCMColMap_ = RCMMap_;

  //Create New Graph
  Epetra_Import Importer( *RCMMap_, orig.RowMap() );
  Epetra_CrsGraph * RCMGraph = new Epetra_CrsGraph( Copy, *RCMMap_, *RCMColMap_, 0 );
  RCMGraph->Import( orig, Importer, Insert );
  RCMGraph->FillComplete();

/*
  std::cout << "origGraph\n";
  std::cout << orig;
  std::cout << "RCMGraph\n";
  std::cout << *RCMGraph;
*/

  newObj_ = RCMGraph;
  
  return *RCMGraph;
}