00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <EpetraExt_BlockAdjacencyGraph.h>
00030
00031 #include <Epetra_CrsMatrix.h>
00032 #include <Epetra_CrsGraph.h>
00033 #include <Epetra_Map.h>
00034 #include <Epetra_Comm.h>
00035
00036 #include <math.h>
00037 #include <stdlib.h>
00038
00039 namespace EpetraExt {
00040
00041 int compare_ints(const void *a, const void *b)
00042 {
00043 return(*((int *) a) - *((int *) b));
00044 }
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 Teuchos::RCP<Epetra_CrsGraph> BlockAdjacencyGraph::compute( Epetra_CrsGraph& B, int nbrr, std::vector<int>&r, std::vector<double>& weights)
00057 {
00058
00059 int myMatProc = -1, matProc = -1;
00060 int myPID = B.Comm().MyPID();
00061 for (int proc=0; proc<B.Comm().NumProc(); proc++)
00062 {
00063 if (B.NumGlobalEntries() == B.NumMyEntries())
00064 myMatProc = myPID;
00065 }
00066 B.Comm().MaxAll( &myMatProc, &matProc, 1 );
00067
00068 if( matProc == -1)
00069 { cout << "FAIL for Global! All CrsGraph entries must be on one processor!\n"; abort(); }
00070
00071 int i= 0, j = 0, k, l = 0, p, pm, q = -1, ns, log2nbrr = 20;
00072 int error = -1;
00073 int nrr;
00074 int nzM = 0;
00075 int m = 0;
00076 int* colstack = 0;
00077 int* bstree = 0;
00078 std::vector<int> Mi, Mj, Mnum(nbrr+1,0);
00079 nrr = B.NumMyRows();
00080 if ( matProc == myPID )
00081 std::printf(" nrr = %d nbrr = %d\n",nrr, nbrr);
00082 else
00083 nrr = -1;
00084 bstree = csr_bst(nbrr);
00085 error = -1;
00086 l = 0; j = 0; m = 0;
00087 for( i = 0; i < nrr; i++ ){
00088 if( i >= r[l+1] ){
00089 ++l;
00090 m = EPETRA_MAX(m,j) ;
00091 j = B.NumGlobalIndices(i);
00092 }else{
00093 j += B.NumGlobalIndices(i);
00094 }
00095 }
00096
00097 m = EPETRA_MAX(m,j) ;
00098
00099 colstack = (int*) malloc( EPETRA_MAX(m,1) * sizeof(int) );
00100 nzM = 0; q = -1; l = 0;
00101 int * indices;
00102 int numEntries;
00103 for( i = 0; i <= nrr; i++ ){
00104 if( i >= r[l+1] ){
00105 if( q > 0 ) qsort(colstack,q+1,sizeof(int),compare_ints);
00106 if( q >= 0 ) ns = 1;
00107 for( j=1; j<=q ; j++ ){
00108 if( colstack[j] > colstack[j-1] ) ++ns;
00109 }
00110 nzM += ns;
00111 ++l;
00112 q = -1;
00113 }
00114 if( i < nrr ){
00115 B.ExtractMyRowView( i, numEntries, indices );
00116 for( k = 0; k < numEntries; k++){
00117 j = indices[k]; ns = 0; p = 0;
00118 while( (r[bstree[p]] > j) || (j >= r[bstree[p]+1]) ){
00119 if( r[bstree[p]] > j){
00120 p = 2*p+1;
00121 }else{
00122 if( r[bstree[p]+1] <= j) p = 2*p+2;
00123 }
00124 ++ns;
00125 if( p > nbrr || ns > 20 ) {
00126 error = j;
00127 std::printf("error: p %d nbrr %d ns %d %d\n",p,nbrr,ns,j); break;
00128 }
00129 }
00130 colstack[++q] = bstree[p];
00131 }
00132 if( error >-1 ){ std::printf("%d\n",error); break; }
00133 }
00134 }
00135
00136 if ( matProc == myPID )
00137 std::printf("nzM = %d \n", nzM );
00138 Mi.resize( nzM );
00139 Mj.resize( nzM );
00140 q = -1; l = 0; pm = -1;
00141 for( i = 0; i <= nrr; i++ ){
00142 if( i >= r[l+1] ){
00143 if( q > 0 ) qsort(colstack,q+1,sizeof(colstack[0]),compare_ints);
00144 if( q >= 0 ){
00145 Mi[++pm] = l;
00146 Mj[pm] = colstack[0];
00147 }
00148 for( j=1; j<=q ; j++ ){
00149 if( colstack[j] > colstack[j-1] ){
00150 Mi[++pm] = l;
00151 Mj[pm] = colstack[j];
00152 }
00153 }
00154 ++l;
00155 Mnum[l] = pm + 1;
00156
00157
00158 q = -1;
00159 }
00160 if( i < nrr ){
00161 B.ExtractMyRowView( i, numEntries, indices );
00162 for( k = 0; k < numEntries; k++){
00163 j = indices[k]; ns = 0; p = 0;
00164 while( (r[bstree[p]] > j) || (j >= r[bstree[p]+1]) ){
00165 if( r[bstree[p]] > j){
00166 p = 2*p+1;
00167 }else{
00168 if( r[bstree[p]+1] <= j) p = 2*p+2;
00169 }
00170 ++ns;
00171 if( p > nbrr || ns > 14 ) {
00172 error = j;
00173 std::printf("error: p %d nbrr %d ns %d %d\n",p,nbrr,ns,j); break;
00174 }
00175 }
00176 colstack[++q] = bstree[p];
00177 }
00178 if( error >-1 ){ std::printf("%d\n",error); break; }
00179 }
00180 }
00181 if ( bstree ) free ( bstree );
00182 if ( colstack ) free( colstack );
00183
00184
00185 weights.resize( nbrr );
00186 for( l=0; l<nbrr; l++) weights[l] = r[l+1] - r[l];
00187
00188
00189 Teuchos::RCP<Epetra_Map> newMap;
00190 if ( matProc == myPID )
00191 newMap = Teuchos::rcp( new Epetra_Map(nbrr, nbrr, 0, B.Comm() ) );
00192 else
00193 newMap = Teuchos::rcp( new Epetra_Map( nbrr, 0, 0, B.Comm() ) );
00194 Teuchos::RCP<Epetra_CrsGraph> newGraph = Teuchos::rcp( new Epetra_CrsGraph( Copy, *newMap, 0 ) );
00195 for( l=0; l<newGraph->NumMyRows(); l++) {
00196 newGraph->InsertGlobalIndices( l, Mnum[l+1]-Mnum[l], &Mj[Mnum[l]] );
00197 }
00198 newGraph->FillComplete();
00199
00200 return (newGraph);
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 int* BlockAdjacencyGraph::csr_bst( int n )
00213 {
00214 int i, l=1, m, nstack = 0, nexp=0, os, *array, *stack;
00215 int max_nstack = 0;
00216 if( n == 0 ) return(NULL);
00217 while( l <= n ){
00218 l = 2*l;
00219 ++nexp;
00220 }
00221 array = (int *) malloc( n * sizeof(int) );
00222 stack = (int *) malloc(3*nexp * sizeof(int) );
00223 stack[3*nstack] = 0; stack[3*nstack+1] = 0; stack[3*nstack+2] = n;
00224 ++nstack;
00225
00226 while( nstack > 0 ){
00227 --nstack;
00228 i = stack[3*nstack]; os = stack[3*nstack+1]; m = stack[3*nstack+2];
00229 array[i] = csr_bstrootindex(m) + os;
00230 if( 2*i+2 < n){
00231 stack[3*nstack] = 2*i+2; stack[3*nstack+1] = array[i] + 1 ; stack[3*nstack+2] = m-array[i]-1+os;
00232 ++nstack;
00233 }
00234 if( 2*i+1 < n){
00235 stack[3*nstack] = 2*i+1; stack[3*nstack+1] = os; stack[3*nstack+2] = array[i] - os;
00236 ++nstack;
00237 }
00238 if( nstack > max_nstack ) max_nstack = nstack;
00239 }
00240 free( stack );
00241 return(array);
00242 }
00243
00244
00245
00246
00247
00248
00249 int BlockAdjacencyGraph::csr_bstrootindex( int n )
00250 {
00251 int l = 1, nexp = 0, i;
00252 if( n == 0) return(-1);
00253 while( l <= n ){
00254 l = 2*l;
00255 ++nexp;
00256 }
00257 i = l/2 - 1;
00258 if(n<4) return(i);
00259 if (n-i < l/4)
00260 return( n - l/4 );
00261 else
00262 return(i);
00263 }
00264
00265 }
00266