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 #ifndef EpetraExt_PERMUTATION_CPP
00029 #define EpetraExt_PERMUTATION_CPP
00030
00031 #include <EpetraExt_ConfigDefs.h>
00032
00033 #include <EpetraExt_Permutation.h>
00034
00035 #include <Epetra_Export.h>
00036 #include <Epetra_Map.h>
00037 #include <Epetra_Comm.h>
00038 #include <Epetra_MultiVector.h>
00039 #include <Epetra_CrsGraph.h>
00040 #include <Epetra_CrsMatrix.h>
00041
00042 namespace EpetraExt {
00043
00062 template<class T>
00063 struct Perm_traits {
00065 static const char* typeName()
00066 { static const char name[] = "unknown"; return( name ); }
00067
00075 static T* clone(T* example,
00076 Epetra_DataAccess CV,
00077 const Epetra_BlockMap& map,
00078 int int_argument)
00079 { return( NULL ); }
00080
00084 static void replaceMap(T* obj, const Epetra_BlockMap& map)
00085 { cerr << "not implemented for unknown type"<<endl; }
00086
00088 static T*
00089 produceColumnPermutation(Permutation<T>* perm,
00090 T* srcObj)
00091 { cerr << "not implemented for unknown type"<<endl; }
00092
00093 };
00094
00095
00096
00100 template<>
00101 struct Perm_traits<Epetra_CrsMatrix> {
00102
00104 static const char* typeName()
00105 { static const char name[] = "Epetra_CrsMatrix"; return( name ); }
00106
00107
00109 static Epetra_CrsMatrix* clone(Epetra_CrsMatrix* example,
00110 Epetra_DataAccess CV,
00111 const Epetra_BlockMap& map,
00112 int rowLength)
00113 {
00114
00115 (void)example;
00116
00117
00118
00119
00120 const Epetra_Map* pointmap =
00121 dynamic_cast<const Epetra_Map*>(&map);
00122 if (pointmap == NULL) {
00123 cerr << "dynamic_cast<const Epetra_Map*> failed."<<endl;
00124 return(NULL);
00125 }
00126
00127 return( new Epetra_CrsMatrix(CV, *pointmap, rowLength) );
00128 }
00129
00130
00132 static void replaceMap(Epetra_CrsMatrix* mat, const Epetra_BlockMap& map)
00133 { mat->ReplaceRowMap(map); }
00134
00136 static Epetra_CrsMatrix*
00137 produceColumnPermutation(Permutation<Epetra_CrsMatrix>* perm,
00138 Epetra_CrsMatrix* srcObj)
00139 {
00140
00141
00142
00143
00144
00145 const Epetra_Map& origColMap = srcObj->ColMap();
00146
00147 Permutation<Epetra_CrsMatrix>* colperm =
00148 new Permutation<Epetra_CrsMatrix>(origColMap);
00149 colperm->PutValue(0);
00150
00151 Epetra_Export p_exporter(perm->Map(), origColMap);
00152 colperm->Export(*perm, p_exporter, Add);
00153
00154 const Epetra_Map& origRowMap = srcObj->RowMap();
00155 int numMyRows = origRowMap.NumMyElements();
00156 const int* myGlobalRows = origRowMap.MyGlobalElements();
00157
00158
00159
00160 Epetra_CrsMatrix* result = new Epetra_CrsMatrix(Copy, origRowMap, 1);
00161
00162 for(int i=0; i<numMyRows; ++i) {
00163 int globalRow = myGlobalRows[i];
00164 int len = srcObj->NumGlobalEntries(globalRow);
00165
00166 int numIndices;
00167 double* src_values = new double[len];
00168 int* src_indices = new int[len];
00169 int err = srcObj->ExtractGlobalRowCopy(globalRow, len, numIndices,
00170 src_values, src_indices);
00171 if (err < 0 || numIndices != len) {
00172 cerr<<"Perm_traits<CrsMatrix>::produceColumnPermutation err("<<err<<") row "
00173 <<globalRow<<", len "<<len<<", numIndices "<<numIndices<<endl;
00174 }
00175
00176 int* pindices = new int[len];
00177
00178 const Epetra_BlockMap& pmap = colperm->Map();
00179 int* p = colperm->Values();
00180
00181 for(int j=0; j<len; ++j) {
00182 int old_col = src_indices[j];
00183
00184 int lid = pmap.LID(old_col);
00185 if (lid<0) {
00186 cerr << "Perm_traits<CrsMatrix>::permuteColumnIndices GID("<<old_col
00187 <<") not found"<<endl;
00188 break;
00189 }
00190
00191 pindices[j] = p[lid];
00192 }
00193
00194 err = result->InsertGlobalValues(globalRow, len, src_values, pindices);
00195 if (err < 0) {
00196 cerr << "Perm_traits<CrsMatrix>::permuteColumnIndices err("<<err
00197 <<") row "<<globalRow<<endl;
00198 }
00199
00200 delete [] pindices;
00201 delete [] src_indices;
00202 delete [] src_values;
00203 }
00204
00205 result->FillComplete();
00206
00207 delete colperm;
00208
00209 return(result);
00210 }
00211
00212 };
00213
00214
00215
00219 template<>
00220 struct Perm_traits<Epetra_CrsGraph> {
00221
00223 static const char* typeName()
00224 { static const char name[] = "Epetra_CrsGraph"; return( name ); }
00225
00226
00228 static Epetra_CrsGraph* clone(Epetra_CrsGraph* example,
00229 Epetra_DataAccess CV,
00230 const Epetra_BlockMap& map,
00231 int rowLength)
00232 {
00233
00234 (void)example;
00235
00236 return( new Epetra_CrsGraph(CV, map, rowLength) );
00237 }
00238
00239
00241 static void replaceMap(Epetra_CrsGraph* graph, const Epetra_BlockMap& map)
00242 { graph->ReplaceRowMap(map); }
00243
00245 static Epetra_CrsGraph*
00246 produceColumnPermutation(Permutation<Epetra_CrsGraph>* perm,
00247 Epetra_CrsGraph* srcObj)
00248 {
00249
00250
00251
00252
00253
00254 const Epetra_BlockMap& origColMap = srcObj->ColMap();
00255
00256 Permutation<Epetra_CrsGraph>* colperm =
00257 new Permutation<Epetra_CrsGraph>(origColMap);
00258 colperm->PutValue(0);
00259
00260 Epetra_Export p_exporter(perm->Map(), origColMap);
00261 colperm->Export(*perm, p_exporter, Add);
00262
00263 const Epetra_BlockMap& origRowMap = srcObj->RowMap();
00264 int numMyRows = origRowMap.NumMyElements();
00265 const int* myGlobalRows = origRowMap.MyGlobalElements();
00266
00267
00268
00269 Epetra_CrsGraph* result = new Epetra_CrsGraph(Copy, origRowMap, 1);
00270
00271 for(int i=0; i<numMyRows; ++i) {
00272 int globalRow = myGlobalRows[i];
00273 int len = srcObj->NumGlobalIndices(globalRow);
00274
00275 int numIndices;
00276 int* src_indices = new int[len];
00277 int err = srcObj->ExtractGlobalRowCopy(globalRow, len, numIndices, src_indices);
00278 if (err < 0 || numIndices != len) {
00279 cerr<<"Perm_traits<CrsGraph>::produceColumnPermutation err("<<err<<") row "
00280 <<globalRow<<", len "<<len<<", numIndices "<<numIndices<<endl;
00281 }
00282
00283 int* pindices = new int[len];
00284
00285 const Epetra_BlockMap& pmap = colperm->Map();
00286 int* p = colperm->Values();
00287
00288 for(int j=0; j<len; ++j) {
00289 int old_col = src_indices[j];
00290
00291 int lid = pmap.LID(old_col);
00292 if (lid<0) {
00293 cerr << "Perm_traits<CrsGraph>::permuteColumnIndices GID("<<old_col
00294 <<") not found"<<endl;
00295 break;
00296 }
00297
00298 pindices[j] = p[lid];
00299 }
00300
00301 err = result->InsertGlobalIndices(globalRow, len, pindices);
00302 if (err < 0) {
00303 cerr << "Perm_traits<CrsGraph>::produceColumnPermutation err("<<err
00304 <<") row "<<globalRow<<endl;
00305 }
00306
00307 delete [] pindices;
00308 delete [] src_indices;
00309 }
00310
00311 result->FillComplete();
00312
00313 delete colperm;
00314
00315 return(result);
00316 }
00317
00318 };
00319
00320
00324 template<>
00325 struct Perm_traits<Epetra_MultiVector> {
00326
00328 static const char* typeName()
00329 { static const char name[] = "Epetra_MultiVector"; return( name ); }
00330
00331
00333 static Epetra_MultiVector* clone(Epetra_MultiVector* example,
00334 Epetra_DataAccess CV,
00335 const Epetra_BlockMap& map,
00336 int numVectors)
00337 {
00338 return( new Epetra_MultiVector(map, example->NumVectors()) );
00339 }
00340
00341
00343 static void replaceMap(Epetra_MultiVector* mvec, const Epetra_BlockMap& map)
00344 { mvec->ReplaceMap(map); }
00345
00347 static Epetra_MultiVector*
00348 produceColumnPermutation(Permutation<Epetra_MultiVector>* perm,
00349 Epetra_MultiVector* srcObj)
00350 {
00351 cerr << "col-permutation not implemented for Epetra_MultiVector"<<endl;
00352 return(NULL);
00353 }
00354
00355 };
00356
00357
00358
00359
00360
00361
00362 template<typename T>
00363 Permutation<T>::Permutation(Epetra_DataAccess CV,
00364 const Epetra_BlockMap& map,
00365 int* permutation)
00366 : Epetra_IntVector(CV, map, permutation),
00367 newObj_(NULL),
00368 origObj_(NULL)
00369 {
00370 if (!isTypeSupported()) {
00371 cerr << "unsupported type for permutation, aborting" << endl;
00372 abort();
00373 }
00374 }
00375
00376 template<typename T>
00377 Permutation<T>::Permutation(const Epetra_BlockMap& map)
00378 : Epetra_IntVector(map),
00379 newObj_(NULL),
00380 origObj_(NULL)
00381 {
00382 if (!isTypeSupported()) {
00383 cerr << "unsupported type for permutation, aborting" << endl;
00384 abort();
00385 }
00386 }
00387
00388 template<typename T>
00389 Permutation<T>::Permutation(const Permutation& src)
00390 : Epetra_IntVector((const Epetra_IntVector&)src),
00391 newObj_(NULL),
00392 origObj_(NULL)
00393 {
00394 if (!isTypeSupported()) {
00395 cerr << "unsupported type for permutation, aborting" << endl;
00396 abort();
00397 }
00398 }
00399
00400 template<typename T>
00401 Permutation<T>::~Permutation()
00402 {
00403 if (newObj_ != NULL) delete newObj_;
00404 }
00405
00406 template<typename T>
00407 bool Permutation<T>::isTypeSupported()
00408 {
00409 const char* type_name = Perm_traits<T>::typeName();
00410 if (!strcmp(type_name, "unknown")) {
00411 return(false);
00412 }
00413
00414 return( true );
00415 }
00416
00417 template<typename T>
00418 typename Permutation<T>::OutputRef
00419 Permutation<T>::operator()( typename Permutation<T>::InputRef orig )
00420 {
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 origObj_ = &orig;
00437
00438
00439
00440
00441
00442
00443 const Epetra_BlockMap& origMap = orig.Map();
00444
00445
00446
00447 Epetra_Map* pmap = new Epetra_Map(Map().NumGlobalPoints(),
00448 Map().NumMyPoints(),
00449 Values(),
00450 Map().IndexBase(),
00451 Map().Comm());
00452
00453 Permutation* p = this;
00454
00455
00456
00457
00458 if (!pmap->PointSameAs(origMap)) {
00459 Epetra_Export p_exporter(Map(), origMap);
00460 Permutation* newp = new Permutation(origMap);
00461 newp->Export(*p, p_exporter, Add);
00462 p = newp;
00463
00464 delete pmap;
00465 pmap = new Epetra_Map(p->Map().NumGlobalPoints(),
00466 p->Map().NumMyPoints(),
00467 p->Values(),
00468 p->Map().IndexBase(),
00469 p->Map().Comm());
00470 }
00471
00472
00473
00474
00475 newObj_ = Perm_traits<T>::clone(origObj_, Copy, *pmap, 1);
00476
00477
00478
00479
00480 Epetra_Export exporter(origMap, *pmap);
00481
00482
00483
00484 newObj_->Export(orig, exporter, Add);
00485
00486
00487
00488
00489
00490
00491 Perm_traits<T>::replaceMap(newObj_, origMap);
00492
00493 delete pmap;
00494
00495 if (p != this) {
00496 delete p;
00497 }
00498
00499 return( *newObj_ );
00500 }
00501
00502 template<typename T>
00503 typename Permutation<T>::OutputRef
00504 Permutation<T>::operator()( typename Permutation<T>::InputRef orig,
00505 bool column_permutation )
00506 {
00507 origObj_ = &orig;
00508 newObj_ = NULL;
00509
00510 if (!column_permutation) {
00511 return( operator()(orig) );
00512 }
00513
00514 if (strcmp("Epetra_CrsMatrix", Perm_traits<T>::typeName()) &&
00515 strcmp("Epetra_CrsGraph", Perm_traits<T>::typeName())) {
00516 cerr << "Permutation: column-permutation only implemented for"
00517 << "CrsMatrix and CrsGraph." << endl;
00518 assert(0);
00519 }
00520
00521 newObj_ = Perm_traits<T>::produceColumnPermutation(this, &orig);
00522
00523 return( *newObj_ );
00524 }
00525
00526 }
00527
00528
00529
00530
00531 template class EpetraExt::Permutation<Epetra_MultiVector>;
00532 template class EpetraExt::Permutation<Epetra_CrsMatrix>;
00533 template class EpetraExt::Permutation<Epetra_CrsGraph>;
00534
00535 #endif //EpetraExt_PERMUTATION_CPP