413 long long rows = (*Matrix_).NumGlobalRows64();
414 long long cols = (*Matrix_).NumGlobalCols64();
415 int num_edges = ((*Matrix_).NumMyNonzeros() - (*Matrix_).NumMyDiagonals())/2;
416 std::cout <<
"global num rows " << rows << std::endl;
419 IFPACK_CHK_ERR((rows == cols));
421 if(rows > std::numeric_limits<int>::max())
423 std::cerr <<
"Ifpack_SupportGraph<T>::FindSupport: global num rows won't fit an int. " << rows << std::endl;
428 int num_verts = (int) rows;
431 E *edge_array =
new E[num_edges];
432 double *weights =
new double[num_edges];
435 int max_num_entries = (*Matrix_).MaxNumEntries();
436 double *values =
new double[max_num_entries];
437 int *indices =
new int[max_num_entries];
439 double * diagonal =
new double[num_verts];
442 for(
int i = 0; i < max_num_entries; i++)
450 for(
int i = 0; i < num_verts; i++)
452 (*Matrix_).ExtractMyRowCopy(i,max_num_entries,num_entries,values,indices);
454 for(
int j = 0; j < num_entries; j++)
459 diagonal[i] = values[j];
462 diagonal[i] *= DiagPertRel_;
464 diagonal[i] += DiagPertAbs_;
469 edge_array[k] = E(i,indices[j]);
470 weights[k] = values[j];
474 weights[k] *= (1.0 + 1e-8 * drand48());
483 Graph g(edge_array, edge_array + num_edges, weights, num_verts);
486 property_map < Graph, edge_weight_t >::type weight = get(edge_weight, g);
488 std::vector < Edge > spanning_tree;
491 kruskal_minimum_spanning_tree(g, std::back_inserter(spanning_tree));
494 std::vector<int> NumNz(num_verts,1);
497 for (std::vector < Edge >::iterator ei = spanning_tree.begin();
498 ei != spanning_tree.end(); ++ei)
500 NumNz[source(*ei,g)] = NumNz[source(*ei,g)] + 1;
501 NumNz[target(*ei,g)] = NumNz[target(*ei,g)] + 1;
506 std::vector< std::vector< int > > Indices(num_verts);
511 std::vector< std::vector< double > > Values(num_verts);
513 for(
int i = 0; i < num_verts; i++)
515 std::vector<int> temp(NumNz[i],0);
516 std::vector<double> temp2(NumNz[i],0);
521 int *l =
new int[num_verts];
522 for(
int i = 0; i < num_verts; i++)
530 for(
int i = 0; i < NumForests_; i++)
534 spanning_tree.clear();
535 kruskal_minimum_spanning_tree(g,std::back_inserter(spanning_tree));
536 for(std::vector < Edge >::iterator ei = spanning_tree.begin();
537 ei != spanning_tree.end(); ++ei)
539 NumNz[source(*ei,g)] = NumNz[source(*ei,g)] + 1;
540 NumNz[target(*ei,g)] = NumNz[target(*ei,g)] + 1;
542 for(
int i = 0; i < num_verts; i++)
544 Indices[i].resize(NumNz[i]);
545 Values[i].resize(NumNz[i]);
549 for (std::vector < Edge >::iterator ei = spanning_tree.begin();
550 ei != spanning_tree.end(); ++ei)
554 Indices[source(*ei,g)][0] = source(*ei,g);
555 Values[source(*ei,g)][0] = Values[source(*ei,g)][0] - weight[*ei];
556 Indices[target(*ei,g)][0] = target(*ei,g);
557 Values[target(*ei,g)][0] = Values[target(*ei,g)][0] - weight[*ei];
559 Indices[source(*ei,g)][l[source(*ei,g)]] = target(*ei,g);
560 Values[source(*ei,g)][l[source(*ei,g)]] = weight[*ei];
561 l[source(*ei,g)] = l[source(*ei,g)] + 1;
563 Indices[target(*ei,g)][l[target(*ei,g)]] = source(*ei,g);
564 Values[target(*ei,g)][l[target(*ei,g)]] = weight[*ei];
565 l[target(*ei,g)] = l[target(*ei,g)] + 1;
582 Matrix_->Multiply(
false, ones, surplus);
584 for(
int i = 0; i < num_verts; i++)
586 Values[i][0] += surplus[i];
587 Values[i][0] = KeepDiag_*diagonal[i] +
588 (1.-KeepDiag_) * Values[i][0];
594#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
595 if((*Matrix_).RowMatrixRowMap().GlobalIndicesLongLong())
598 for(
int i = 0; i < num_verts; i++)
600 std::vector<long long> IndicesLL(l[i]);
601 for(
int k = 0; k < l[i]; ++k)
602 IndicesLL[k] = Indices[i][k];
604 (*Support_).InsertGlobalValues(i,l[i],&Values[i][0],&IndicesLL[0]);
609#ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
610 if((*Matrix_).RowMatrixRowMap().GlobalIndicesInt())
613 for(
int i = 0; i < num_verts; i++)
615 (*Support_).InsertGlobalValues(i,l[i],&Values[i][0],&Indices[i][0]);
620 throw "Ifpack_SupportGraph::FindSupport: GlobalIndices unknown.";;
622 (*Support_).FillComplete();
745Print(std::ostream& os)
const
747 os <<
"================================================================================" << std::endl;
748 os <<
"Ifpack_SupportGraph: " << Label () << std::endl << std::endl;
749 os <<
"Condition number estimate = " << Condest() << std::endl;
750 os <<
"Global number of rows = " << Matrix_->NumGlobalRows64() << std::endl;
751 os <<
"Number of edges in support graph = " << (Support_->NumGlobalNonzeros64()-Support_->NumGlobalDiagonals64())/2 << std::endl;
752 os <<
"Fraction of off diagonals of support graph/off diagonals of original = "
753 << ((double)Support_->NumGlobalNonzeros64()-Support_->NumGlobalDiagonals64())/(Matrix_->NumGlobalNonzeros64()-Matrix_->NumGlobalDiagonals64());
755 os <<
"Phase # calls Total Time (s) Total MFlops MFlops/s" << std::endl;
756 os <<
"----- ------- -------------- ------------ --------" << std::endl;
757 os <<
"Initialize() " << std::setw(10) << NumInitialize_
758 <<
" " << std::setw(15) << InitializeTime_
759 <<
" 0.0 0.0" << std::endl;
760 os <<
"Compute() " << std::setw(10) << NumCompute_
761 <<
" " << std::setw(22) << ComputeTime_
762 <<
" " << std::setw(15) << 1.0e-6 * ComputeFlops_;
763 if (ComputeTime_ != 0.0)
764 os <<
" " << std::setw(15) << 1.0e-6 * ComputeFlops_ / ComputeTime_ << std::endl;
766 os <<
" " << std::setw(15) << 0.0 << std::endl;
767 os <<
"ApplyInverse() " << std::setw(10) << NumApplyInverse_
768 <<
" " << std::setw(22) << ApplyInverseTime_
769 <<
" " << std::setw(15) << 1.0e-6 * ApplyInverseFlops_;
770 if (ApplyInverseTime_ != 0.0)
771 os <<
" " << std::setw(15) << 1.0e-6 * ApplyInverseFlops_ / ApplyInverseTime_ << std::endl;
773 os <<
" " << std::setw(15) << 0.0 << std::endl;
775 os << std::endl << std::endl;
776 os <<
"Now calling the underlying preconditioner's print()" << std::endl;