Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Amesos_Superludist.cpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Amesos: Direct Sparse Solver Package
5 // Copyright (2004) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // This library is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as
12 // published by the Free Software Foundation; either version 2.1 of the
13 // License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
23 // USA
24 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
25 //
26 // ***********************************************************************
27 // @HEADER
28 
29 // TO DO: use Stat structure to print statistics???
30 // allow users to specify usermap ???
31 
32 #include "Amesos_Superludist.h"
33 #include "Epetra_Map.h"
34 #include "Epetra_Import.h"
35 #include "Epetra_CrsMatrix.h"
36 #include "Epetra_Util.h"
37 // #include "CrsMatrixTranspose.h"
38 #include "superlu_ddefs.h"
39 #include "supermatrix.h"
40 // SuperLU defines Reduce to be a macro in util.h, this conflicts with Reduce() in Epetra_MultiVector.h
41 #undef Reduce
42 
44 public:
45  // Teuchos::RCP<trilinos_klu_symbolic> Symbolic_ ;
46  // Teuchos::RCP<trilinos_klu_numeric> Numeric_ ;
47  fact_t FactOption_;
48  // Here are the structures used by Superlu
49  SuperMatrix SuperluA_;
50  ScalePermstruct_t ScalePermstruct_;
51  LUstruct_t LUstruct_;
52  SOLVEstruct_t SOLVEstruct_;
54  gridinfo_t grid_;
56 #if SUPERLU_DIST_MAJOR_VERSION > 4
57  //Note we may add the need for minor or patch version as need
58  superlu_dist_options_t options_;
59 #else
60  superlu_options_t options_;
61 #endif
62 
63 } ;
64 
65 
66 // ======================================================================
67 int Superludist_NumProcRows( int NumProcs ) {
68 #ifdef TFLOP
69  // Else, parameter 6 of DTRSV CTNLU is incorrect
70  return 1;
71 #else
72  int i;
73  int NumProcRows ;
74  for ( i = 1; i*i <= NumProcs; i++ )
75  ;
76  bool done = false ;
77  for ( NumProcRows = i-1 ; done == false ; ) {
78  int NumCols = NumProcs / NumProcRows ;
79  if ( NumProcRows * NumCols == NumProcs )
80  done = true;
81  else
82  NumProcRows-- ;
83  }
84  return NumProcRows;
85 #endif
86 }
87 
88 // ======================================================================
89 int SetNPRowAndCol(const int MaxProcesses, int& nprow, int& npcol)
90 {
91  nprow = Superludist_NumProcRows(MaxProcesses);
92  if (nprow < 1 ) nprow = 1;
93  npcol = MaxProcesses / nprow;
94 
95  if( nprow <=0 || npcol <= 0 || MaxProcesses <=0 ) {
96  std::cerr << "Amesos_Superludist: wrong value for MaxProcs ("
97  << MaxProcesses << "), or nprow (" << nprow
98  << ") or npcol (" << npcol << ")" << std::endl;
99  AMESOS_CHK_ERR(-1);
100  }
101  return(0);
102 }
103 
104 //=============================================================================
106  PrivateSuperluData_( rcp( new Amesos_Superlu_Pimpl() ) ),
107  Problem_(&prob),
108  RowMatrixA_(0),
109  GridCreated_(0),
110  FactorizationDone_(0),
111  FactorizationOK_(false),
112  NumGlobalRows_(0),
113  nprow_(0),
114  npcol_(0),
115  PrintNonzeros_(false),
116  ColPerm_("NOT SET"),
117  RowPerm_("NOT SET"),
118  perm_c_(0),
119  perm_r_(0),
120  IterRefine_("NOT SET"),
121  ReplaceTinyPivot_(true),
122  MtxConvTime_(-1),
123  MtxRedistTime_(-1),
124  VecRedistTime_(-1),
125  NumFactTime_(-1),
126  SolveTime_(-1),
127  OverheadTime_(-1)
128 {
129  Redistribute_ = true;
130  AddZeroToDiag_ = false;
131  PrivateSuperluData_->FactOption_ = SamePattern_SameRowPerm ;
132  ReuseSymbolic_ = false ;
133 
134  MaxProcesses_ = - 1;
135  Equil_ = true;
136  ColPerm_ = "MMD_AT_PLUS_A";
137  perm_c_ = 0;
138 #if (SUPERLU_DIST_MAJOR_VERSION > 5) || ( SUPERLU_DIST_MAJOR_VERSION == 5 && SUPERLU_DIST_MINOR_VERSION > 3)
139  RowPerm_ = "LargeDiag_MC64";
140 #else
141  RowPerm_ = "LargeDiag";
142 #endif
143  perm_r_ = 0;
144  IterRefine_ = "DOUBLE";
145  ReplaceTinyPivot_ = true;
146 
147  PrintNonzeros_ = false;
148 
149  ComputeTrueResidual_ = false;
150  ComputeVectorNorms_ = false;
151  PrintStatus_ = false ;
152  PrintTiming_ = false ;
153 
154  Teuchos::ParameterList ParamList;
155  SetParameters(ParamList);
156 }
157 
158 //=============================================================================
160 {
161  if (PrintTiming_) PrintTiming();
162  if (PrintStatus_) PrintStatus();
163 
164  if ( FactorizationDone_ ) {
165  SUPERLU_FREE( PrivateSuperluData_->SuperluA_.Store );
166  ScalePermstructFree(&PrivateSuperluData_->ScalePermstruct_);
168  LUstructFree(&PrivateSuperluData_->LUstruct_);
169  if ( PrivateSuperluData_->options_.SolveInitialized ) {
171  }
172  }
173  if ( GridCreated_ ) {
174  superlu_gridexit(&PrivateSuperluData_->grid_);
175  }
176 }
177 
178 // ======================================================================
180 {
181  // retrive general parameters
182 
183  SetStatusParameters( ParameterList );
184 
185  SetControlParameters( ParameterList );
186 
187  if (ParameterList.isParameter("Redistribute"))
188  Redistribute_ = ParameterList.get<bool>("Redistribute");
189 
190  // parameters for Superludist only
191 
192  if (ParameterList.isSublist("Superludist") )
193  {
194  const Teuchos::ParameterList& SuperludistParams =
195  ParameterList.sublist("Superludist") ;
196 
197  if( SuperludistParams.isParameter("ReuseSymbolic") )
198  ReuseSymbolic_ = SuperludistParams.get<bool>("ReuseSymbolic");
199  std::string FactOption = "NotSet";
200 
201  if( SuperludistParams.isParameter("Fact") )
202  FactOption = SuperludistParams.get<std::string>("Fact");
203 
204  if( FactOption == "SamePattern_SameRowPerm" ) PrivateSuperluData_->FactOption_ = SamePattern_SameRowPerm;
205  else if( FactOption == "SamePattern" ) PrivateSuperluData_->FactOption_ = SamePattern;
206  else if ( FactOption != "NotSet" )
207  AMESOS_CHK_ERR(-2); // input not valid
208 
209  if (SuperludistParams.isParameter("Equil"))
210  Equil_ = SuperludistParams.get<bool>("Equil");
211 
212  if (SuperludistParams.isParameter("ColPerm"))
213  ColPerm_ = SuperludistParams.get<std::string>("ColPerm");
214 
215  if (ColPerm_ == "MY_PERMC")
216  if( SuperludistParams.isParameter("perm_c"))
217  perm_c_ = SuperludistParams.get<int*>("perm_c");
218 
219  if (SuperludistParams.isParameter("RowPerm"))
220  RowPerm_ = SuperludistParams.get<std::string>("RowPerm");
221  if( RowPerm_ == "MY_PERMR" ) {
222  if (SuperludistParams.isParameter("perm_r"))
223  perm_r_ = SuperludistParams.get<int*>("perm_r");
224  }
225 
226  if (SuperludistParams.isParameter("IterRefine"))
227  IterRefine_ = SuperludistParams.get<std::string>("IterRefine");
228 
229  if (SuperludistParams.isParameter("ReplaceTinyPivot"))
230  ReplaceTinyPivot_ = SuperludistParams.get<bool>("ReplaceTinyPivot");
231 
232  if (SuperludistParams.isParameter("PrintNonzeros"))
233  PrintNonzeros_ = SuperludistParams.get<bool>("PrintNonzeros");
234  }
235 
236  return(0);
237 }
238 
239 // ======================================================================
240 // Tasks of this method:
241 // 1) To set the required number of processes;
242 // 2) To set nprow_ and npcol_
243 // 3) To create a linear distribution (map) with elements only in the
244 // active processes
245 // 4) To redistribute the matrix from the original to the linear map.
246 // ======================================================================
248 {
249  ResetTimer(0);
250 
252  AMESOS_CHK_ERR(-1); // something has changed
253 
254  int iam = Comm().MyPID();
255 
258 
259  int m_per_p = NumGlobalRows_ / MaxProcesses_ ;
260  int remainder = NumGlobalRows_ - ( m_per_p * MaxProcesses_ );
261  int MyFirstElement = iam * m_per_p + EPETRA_MIN( iam, remainder );
262  int MyFirstNonElement = (iam+1) * m_per_p + EPETRA_MIN( iam+1, remainder );
263  int NumExpectedElements = MyFirstNonElement - MyFirstElement ;
264 
265  if (iam >= MaxProcesses_)
266  NumExpectedElements = 0;
267 
269  AMESOS_CHK_ERR(-1);
270 
271  const Epetra_Map &OriginalMap = RowMatrixA_->RowMatrixRowMap();
272 
273  UniformMap_ = rcp(new Epetra_Map(NumGlobalRows_, NumExpectedElements,
274  0, Comm()));
276  UniformMatrix_ = rcp(&CrsUniformMatrix(), false);
277  Importer_ = rcp(new Epetra_Import(*UniformMap_, OriginalMap));
278 
279  CrsUniformMatrix_->Import(*RowMatrixA_, Importer(), Add);
280  // int TracebackMode = Comm().GetTracebackMode();
281  // UniformMatrix_->SetTracebackMode(0);
282  if (AddZeroToDiag_ ) {
283  //
284  // Add 0.0 to each diagonal entry to avoid empty diagonal entries;
285  //
286  int OriginalTracebackMode = CrsUniformMatrix_->GetTracebackMode() ;
287  CrsUniformMatrix_->SetTracebackMode( EPETRA_MIN( OriginalTracebackMode, 0) ) ;
288  double zero = 0.0;
289  for ( int i = 0 ; i < UniformMap_->NumGlobalElements(); i++ )
290  if ( CrsUniformMatrix_->LRID(i) >= 0 )
291  CrsUniformMatrix_->InsertGlobalValues( i, 1, &zero, &i ) ;
292  CrsUniformMatrix_->SetTracebackMode( OriginalTracebackMode ) ;
293  }
294  // UniformMatrix_->SetTracebackMode(TracebackMode);
295 
296 
298 
299  MtxConvTime_ = AddTime("Total matrix conversion time", MtxConvTime_, 0);
300 
301 
302 
303  return(0);
304 }
305 
306 
307 // ======================================================================
309 {
310  ResetTimer(1); // for "overhead"
311 
312  // FIXME????
313  // For now, if you change the shape of a matrix, you need to
314  // create a new Amesos instance.
315  //
316  //
318  AMESOS_CHK_ERR(-5);
319 
321 
322  if (Comm().NumProc() == 1)
323  Redistribute_ = false;
324 
325  // Set the matrix and grid shapes. Time is tracked within
326  // the RedistributeA() function
327 
328  if (Redistribute_)
329  RedistributeA() ;
330  else
331  {
332  if (Comm().NumProc() == 1)
333  {
334  nprow_ = 1;
335  npcol_ = 1;
336  }
337  else
338  {
340  AMESOS_CHK_ERR(-2);
341  SetNPRowAndCol(Comm().NumProc(), nprow_, npcol_);
342  }
343 
344  UniformMatrix_ = rcp(RowMatrixA_, false);
345  }
346 
347  // Extract Ai_, Ap_ and Aval_ from UniformMatrix_
348 
349  ResetTimer(0);
350 
351  int MyActualFirstElement = UniformMatrix().RowMatrixRowMap().MinMyGID() ;
352  int NumMyElements = UniformMatrix().NumMyRows() ;
353  int nnz_loc = UniformMatrix().NumMyNonzeros() ;
354  Ap_.resize( NumMyElements+1 );
355  Ai_.resize( EPETRA_MAX( NumMyElements, nnz_loc) ) ;
356  Aval_.resize( EPETRA_MAX( NumMyElements, nnz_loc) ) ;
357 
358  int NzThisRow ;
359  int Ai_index = 0 ;
360  int MyRow;
361  //int num_my_cols = UniformMatrix().NumMyCols() ;
362  double *RowValues;
363  int *ColIndices;
364  int MaxNumEntries_ = UniformMatrix().MaxNumEntries();
365  std::vector<double> RowValuesV_(MaxNumEntries_);
366  std::vector<int> ColIndicesV_(MaxNumEntries_);
367 
369 
370  const Epetra_CrsMatrix *SuperluCrs = dynamic_cast<const Epetra_CrsMatrix *>(&UniformMatrix());
371 
372  int ierr;
373 
374  for (MyRow = 0; MyRow < NumMyElements ; MyRow++)
375  {
376  if (SuperluCrs != 0)
377  {
378  ierr = SuperluCrs->ExtractMyRowView(MyRow, NzThisRow, RowValues,
379  ColIndices);
380 
381  }
382  else {
383  ierr = UniformMatrix().ExtractMyRowCopy(MyRow, MaxNumEntries_, NzThisRow,
384  &RowValuesV_[0], &ColIndicesV_[0]);
385  RowValues = &RowValuesV_[0];
386  ColIndices = &ColIndicesV_[0];
387  }
388 
389  AMESOS_CHK_ERR(ierr);
390 
391  // MS // Added on 15-Mar-05
392  if (AddToDiag_ != 0.0 || AddZeroToDiag_) {
393  for (int i = 0 ; i < NzThisRow ; ++i) {
394  if (ColIndices[i] == MyRow) {
395  RowValues[i] += AddToDiag_;
396  break;
397  }
398  }
399  }
400 
401  Ap_[MyRow] = Ai_index ;
402  for ( int j = 0; j < NzThisRow; j++ ) {
403  Ai_[Ai_index] = Global_Columns_[ColIndices[j]] ;
404  Aval_[Ai_index] = RowValues[j] ;
405  Ai_index++;
406  }
407  }
408  assert( NumMyElements == MyRow );
409  Ap_[ NumMyElements ] = Ai_index ;
410 
411  OverheadTime_ = AddTime("Total Amesos overhead time", OverheadTime_, 1);
412 
413  //
414  // Setup Superlu's grid
415  //
416  const Epetra_MpiComm & comm1 = dynamic_cast<const Epetra_MpiComm &> (Comm());
417 
418  if ( ! GridCreated_ ) {
419  // NOTE: nprow_ and npcol_ cannot be changed by the user
420  GridCreated_ = true;
421  superlu_gridinit(comm1.Comm(), nprow_, npcol_, &PrivateSuperluData_->grid_);
422  }
423 
424  if ( FactorizationDone_ ) {
425  SUPERLU_FREE( PrivateSuperluData_->SuperluA_.Store );
426  ScalePermstructFree(&PrivateSuperluData_->ScalePermstruct_);
428  LUstructFree(&PrivateSuperluData_->LUstruct_);
429  if ( PrivateSuperluData_->options_.SolveInitialized ) {
431  }
432  }
433 
434  MtxConvTime_ = AddTime("Total matrix conversion time", MtxConvTime_, 0);
435  ResetTimer(0);
436 
437  //
438  // Only those processes in the grid participate from here on
439  //
440  if (Comm().MyPID() < nprow_ * npcol_) {
441  //
442  // Set up Superlu's data structures
443  //
444  set_default_options_dist(&PrivateSuperluData_->options_);
445 
446  dCreate_CompRowLoc_Matrix_dist( &PrivateSuperluData_->SuperluA_, NumGlobalRows_, NumGlobalRows_,
447  nnz_loc, NumMyElements, MyActualFirstElement,
448  &Aval_[0], &Ai_[0], &Ap_[0],
449  SLU_NR_loc, SLU_D, SLU_GE );
450 
451  FactorizationDone_ = true; // i.e. clean up Superlu data structures in the destructor
452 
454 #ifdef HAVE_SUPERLUDIST_LUSTRUCTINIT_2ARG
456 #else
458 #endif
459 
460  // stick options from ParameterList to options_ structure
461  // Here we follow the same order of the SuperLU_dist 2.0 manual (pag 55/56)
462 
463  assert( PrivateSuperluData_->options_.Fact == DOFACT );
464  PrivateSuperluData_->options_.Fact = DOFACT ;
465 
466  if( Equil_ ) PrivateSuperluData_->options_.Equil = (yes_no_t)YES;
467  else PrivateSuperluData_->options_.Equil = NO;
468 
469  if( ColPerm_ == "NATURAL" ) PrivateSuperluData_->options_.ColPerm = NATURAL;
470  else if( ColPerm_ == "MMD_AT_PLUS_A" ) PrivateSuperluData_->options_.ColPerm = MMD_AT_PLUS_A;
471  else if( ColPerm_ == "MMD_ATA" ) PrivateSuperluData_->options_.ColPerm = MMD_ATA;
472  // else if( ColPerm_ == "COLAMD" ) PrivateSuperluData_->options_.ColPerm = COLAMD; // COLAMD no longer supported in Superludist, as of July 2005
473  else if( ColPerm_ == "MY_PERMC" ) {
474  PrivateSuperluData_->options_.ColPerm = MY_PERMC;
476  }
477 
478  if( RowPerm_ == "NATURAL" ) PrivateSuperluData_->options_.RowPerm = (rowperm_t)NATURAL;
479 #if (SUPERLU_DIST_MAJOR_VERSION > 5) || ( SUPERLU_DIST_MAJOR_VERSION == 5 && SUPERLU_DIST_MINOR_VERSION > 3)
480  if( RowPerm_ == "LargeDiag_MC64" ) PrivateSuperluData_->options_.RowPerm = LargeDiag_MC64;
481 #else
482  if( RowPerm_ == "LargeDiag" ) PrivateSuperluData_->options_.RowPerm = LargeDiag;
483 #endif
484  else if( ColPerm_ == "MY_PERMR" ) {
485  PrivateSuperluData_->options_.RowPerm = MY_PERMR;
487  }
488 
489  if( ReplaceTinyPivot_ ) PrivateSuperluData_->options_.ReplaceTinyPivot = (yes_no_t)YES;
490  else PrivateSuperluData_->options_.ReplaceTinyPivot = (yes_no_t)NO;
491 
492  if( IterRefine_ == "NO" ) PrivateSuperluData_->options_.IterRefine = (IterRefine_t)NO;
493  else if( IterRefine_ == "DOUBLE" ) {
494  PrivateSuperluData_->options_.IterRefine =
495 #ifdef HAVE_SUPERLUDIST_ENUM_NAMESPACE
496  SLU_DOUBLE
497 #else
498  DOUBLE
499 #endif
500  ;
501  }
502  else if( IterRefine_ == "EXTRA" ) {
503  PrivateSuperluData_->options_.IterRefine =
504 #ifdef HAVE_SUPERLUDIST_ENUM_NAMESPACE
505  SLU_EXTRA
506 #else
507  EXTRA
508 #endif
509  ;
510  }
511 
512  // Without the following two lines, SuperLU_DIST cannot be made
513  // quiet.
514 
515  if (PrintNonzeros_) PrivateSuperluData_->options_.PrintStat = (yes_no_t)YES;
516  else PrivateSuperluData_->options_.PrintStat = (yes_no_t)NO;
517 
518  SuperLUStat_t stat;
519  PStatInit(&stat); /* Initialize the statistics variables. */
520 
521  //
522  // Factor A using Superludsit (via a call to pdgssvx)
523  //
524  int info ;
525  double berr ; // Should be untouched
526  double xValues; // Should be untouched
527  int nrhs = 0 ; // Prevents forward and back solves
528  int ldx = NumGlobalRows_; // Should be untouched
529 
532 
533  if ( PrivateSuperluData_->options_.SolveInitialized ) {
535  }
536  AMESOS_CHK_ERR(info);
537 
538  PStatFree(&stat);
539  }
540 
541  NumFactTime_ = AddTime("Total numeric factorization time", NumFactTime_, 0);
542 
543  return 0;
544 }
545 
546 // ======================================================================
547 // Refactor - Refactor the matrix
548 //
549 // Preconditions:
550 // The non-zero pattern of the matrix must not have changed since the
551 // previous call to Factor(). Refactor ensures that each process owns
552 // the same number of columns that it did on the previous call to Factor()
553 // and returns -4 if a discrepancy is found. However, that check does not
554 // guarantee that no change was made to the non-zero structure of the matrix.
555 // No call to SetParameters should be made between the call to Factor()
556 // and the call to Refactor(). If the user does not call SetParameters,
557 // as they need never do, they are safe on this.
558 //
559 // Postconditions:
560 // The matrix specified by Problem_->Operator() will have been redistributed,
561 // converted to the form needed by Superludist and factored.
562 // Ai_, Aval_
563 // SuperluA_
564 // SuperLU internal data structures reflecting the LU factorization
565 // ScalePermstruct_
566 // LUstructInit_
567 //
568 // Performance notes:
569 // Refactor does not allocate or de-allocate memory.
570 //
571 // Return codes:
572 // -4 if we detect a change to the non-zero structure of the matrix.
573 //
575 {
576  ResetTimer(0);
577  ResetTimer(1);
578 
579  //
580  // Update Ai_ and Aval_ (while double checking Ap_)
581  //
582  if (Redistribute_)
583  if(CrsUniformMatrix().Import(*RowMatrixA_, Importer(), Insert))
584  AMESOS_CHK_ERR(-4);
585 
586  MtxRedistTime_ = AddTime("Total matrix redistribution time", MtxRedistTime_, 0);
587  ResetTimer(0);
588 
589  const Epetra_CrsMatrix *SuperluCrs = dynamic_cast<const Epetra_CrsMatrix *>(&UniformMatrix());
590 
591  double *RowValues;
592  int *ColIndices;
593  int MaxNumEntries_ = UniformMatrix().MaxNumEntries();
594  int NumMyElements = UniformMatrix().NumMyRows() ;
595  std::vector<int> ColIndicesV_(MaxNumEntries_);
596  std::vector<double> RowValuesV_(MaxNumEntries_);
597 
598  int NzThisRow ;
599  int Ai_index = 0 ;
600  int MyRow;
601  int ierr;
602 
603  for ( MyRow = 0; MyRow < NumMyElements ; MyRow++ ) {
604  if ( SuperluCrs != 0 ) {
605  ierr = SuperluCrs->ExtractMyRowView(MyRow, NzThisRow, RowValues,
606  ColIndices);
607  }
608  else {
609  ierr = UniformMatrix().ExtractMyRowCopy( MyRow, MaxNumEntries_,
610  NzThisRow, &RowValuesV_[0],
611  &ColIndicesV_[0]);
612  RowValues = &RowValuesV_[0];
613  ColIndices = &ColIndicesV_[0];
614  }
615 
616  AMESOS_CHK_ERR(ierr);
617 
618  if ( Ap_[MyRow] != Ai_index ) AMESOS_CHK_ERR(-4);
619  for ( int j = 0; j < NzThisRow; j++ ) {
620  // pdgssvx alters Ai_, so we have to set it again.
621  Ai_[Ai_index] = Global_Columns_[ColIndices[j]];
622  Aval_[Ai_index] = RowValues[j] ;
623  Ai_index++;
624  }
625  }
626  if( Ap_[ NumMyElements ] != Ai_index ) AMESOS_CHK_ERR(-4);
627 
628  MtxConvTime_ = AddTime("Total matrix conversion time", MtxConvTime_, 0);
629  OverheadTime_ = AddTime("Total Amesos overhead time", OverheadTime_, 1);
630  ResetTimer(0);
631 
632  if (Comm().MyPID() < nprow_ * npcol_) {
633 
634 
635  // If we reuse the same options, the code fails on multiprocess runs
636  set_default_options_dist(&PrivateSuperluData_->options_);
637 
638  if (PrintNonzeros_) PrivateSuperluData_->options_.PrintStat = (yes_no_t)YES;
639  else PrivateSuperluData_->options_.PrintStat = (yes_no_t)NO;
640 
641 
643  SuperLUStat_t stat;
644  PStatInit(&stat); /* Initialize the statistics variables. */
645  int info ;
646  double berr ; // Should be untouched
647  double xValues; // Should be untouched
648  int nrhs = 0 ; // Prevents forward and back solves
649  int ldx = NumGlobalRows_; // Should be untouched
652  PStatFree(&stat);
653  AMESOS_CHK_ERR( info ) ;
654  }
655 
656  NumFactTime_ = AddTime("Total numeric factorization time", NumFactTime_, 0);
657 
658  return 0;
659 }
660 
661 // ======================================================================
663 {
664  if (GetProblem()->GetOperator()->OperatorRangeMap().NumGlobalPoints() !=
665  GetProblem()->GetOperator()->OperatorDomainMap().NumGlobalPoints())
666  return(false);
667  else
668  return(true);
669 }
670 
671 // ======================================================================
673 {
674  FactorizationOK_ = false ;
675 
676  return(0);
677 }
678 
679 // ======================================================================
681 {
682  RowMatrixA_ = dynamic_cast<Epetra_RowMatrix *>(Problem_->GetOperator());
683  if (RowMatrixA_ == 0)
684  AMESOS_CHK_ERR(-1); // Linear problem does not contain Epetra_RowMatrix
685 
686  // reset factorization
687  // FactorizationOK_ = false;
688 
689  if (!MatrixShapeOK())
690  AMESOS_CHK_ERR(-1); // matrix not square
691 
692  CreateTimer(Comm(), 2);
693 
695  ReFactor();
696  else
697  Factor();
698 
699  FactorizationOK_ = true;
700 
701  NumNumericFact_++;
702 
703  return(0);
704 }
705 
706 // ======================================================================
707 // We proceed as follows:
708 // - perform numeric factorization if not done;
709 // - extract solution and right-hand side;
710 // - redistribute them if necessary by creating additional
711 // working vectors, or use vecX and vecB otherwise;
712 // - call SuperLU_DIST's solve routine;
713 // - re-ship data if necessary.
714 // ======================================================================
716 {
717  if (!FactorizationOK_)
719 
720  ResetTimer(1);
721 
722  Epetra_MultiVector* vecX = Problem_->GetLHS();
723  Epetra_MultiVector* vecB = Problem_->GetRHS();
724 
725  if (vecX == 0 || vecB == 0)
726  AMESOS_CHK_ERR(-1);
727 
728  int nrhs = vecX->NumVectors() ;
729  if (vecB->NumVectors() != nrhs)
730  AMESOS_CHK_ERR(-1);
731 
732  double *values;
733  int ldx;
734 
735  RCP<Epetra_MultiVector> vec_uni;
736 
737  if (Redistribute_)
738  {
739  vec_uni = Teuchos::rcp(new Epetra_MultiVector(*UniformMap_, nrhs));
740  ResetTimer(0);
741  vec_uni->Import(*vecB, Importer(), Insert);
742  VecRedistTime_ = AddTime("Total vector redistribution time", VecRedistTime_, 0);
743  }
744  else
745  {
746  vecX->Update(1.0, *vecB, 0.0);
747  vec_uni = Teuchos::rcp(vecX, false);
748  }
749 
750  //int NumMyElements = vec_uni->MyLength();
751  AMESOS_CHK_ERR(vec_uni->ExtractView(&values, &ldx));
752 
753  OverheadTime_ = AddTime("Total Amesos overhead time", OverheadTime_, 1);
754 
755  ResetTimer(0);
756 
757  /* Bail out if I do not belong in the grid. */
758  if (Comm().MyPID() < nprow_ * npcol_)
759  {
760  int info ;
761  std::vector<double>berr(nrhs);
762  SuperLUStat_t stat;
763  PStatInit(&stat); /* Initialize the statistics variables. */
764 
766  AMESOS_CHK_ERR(-1); // internal error
767  PrivateSuperluData_->options_.Fact = FACTORED ;
768 
769  //bool BlockSolve = true ;
772  &stat, &info);
773  AMESOS_CHK_ERR(info);
774 
775  PStatFree(&stat);
776  }
777 
778  SolveTime_ = AddTime("Total solve time", SolveTime_, 0);
779 
780  ResetTimer(1);
781 
782  if (Redistribute_)
783  {
784  ResetTimer(0);
785  vecX->Export(*vec_uni, Importer(), Insert);
786  VecRedistTime_ = AddTime("Total vector redistribution time", VecRedistTime_, 0);
787  }
788 
790  ComputeTrueResidual(*RowMatrixA_, *vecX, *vecB, UseTranspose(),
791  "Amesos_Superludist");
792 
794  ComputeVectorNorms(*vecX, *vecB, "Amesos_Superludist");
795 
796  OverheadTime_ = AddTime("Total Amesos overhead time", OverheadTime_, 1);
797  NumSolve_++;
798 
799  return(0);
800 }
801 
802 // ======================================================================
804 {
805  if (Problem_->GetOperator() == 0 || Comm().MyPID() != 0)
806  return;
807 
808  std::string p = "Amesos_Superludist : ";
809  int NNZ = RowMatrixA_->NumGlobalNonzeros();
810 
811  PrintLine();
812 
813  std::cout << p << "Matrix has " << NumGlobalRows_ << " rows"
814  << " and " << NNZ << " nonzeros" << std::endl;
815  std::cout << p << "Nonzero elements per row = "
816  << 1.0 * NNZ / NumGlobalRows_ << std::endl;
817  std::cout << p << "Percentage of nonzero elements = "
818  << 100.0 * NNZ /pow(NumGlobalRows_, 2.0) << std::endl;
819  std::cout << p << "Use transpose = " << UseTranspose() << std::endl;
820  std::cout << p << "Redistribute = " << Redistribute_ << std::endl;
821  std::cout << p << "# available processes = " << Comm().NumProc() << std::endl;
822  std::cout << p << "# processes used in computation = " << nprow_ * npcol_
823  << " ( = " << nprow_ << "x" << npcol_ << ")" << std::endl;
824  std::cout << p << "Equil = " << Equil_ << std::endl;
825  std::cout << p << "ColPerm = " << ColPerm_ << std::endl;
826  std::cout << p << "RowPerm = " << RowPerm_ << std::endl;
827  std::cout << p << "IterRefine = " << IterRefine_ << std::endl;
828  std::cout << p << "ReplaceTinyPivot = " << ReplaceTinyPivot_ << std::endl;
829  std::cout << p << "AddZeroToDiag = " << AddZeroToDiag_ << std::endl;
830  std::cout << p << "Redistribute = " << Redistribute_ << std::endl;
831 
832  PrintLine();
833 
834  return;
835 }
836 
837 // ======================================================================
839 {
840  if (Problem_->GetOperator() == 0 || Comm().MyPID() != 0)
841  return;
842 
843  double ConTime = GetTime(MtxConvTime_);
844  double MatTime = GetTime(MtxRedistTime_);
845  double VecTime = GetTime(VecRedistTime_);
846  double NumTime = GetTime(NumFactTime_);
847  double SolTime = GetTime(SolveTime_);
848  double OveTime = GetTime(OverheadTime_);
849 
850  if (NumNumericFact_)
851  NumTime /= NumNumericFact_;
852 
853  if (NumSolve_)
854  SolTime /= NumSolve_;
855 
856  std::string p = "Amesos_Superludist : ";
857  PrintLine();
858 
859  std::cout << p << "Time to convert matrix to Superludist format = "
860  << ConTime << " (s)" << std::endl;
861  std::cout << p << "Time to redistribute matrix = "
862  << MatTime << " (s)" << std::endl;
863  std::cout << p << "Time to redistribute vectors = "
864  << VecTime << " (s)" << std::endl;
865  std::cout << p << "Number of symbolic factorizations = "
866  << NumSymbolicFact_ << std::endl;
867  std::cout << p << "Time for sym fact = 0.0 (s), avg = 0.0 (s)" << std::endl;
868  std::cout << p << "Number of numeric factorizations = "
869  << NumNumericFact_ << std::endl;
870  std::cout << p << "Time for num fact = "
871  << NumTime * NumNumericFact_ << " (s), avg = " << NumTime << " (s)" << std::endl;
872  std::cout << p << "Number of solve phases = "
873  << NumSolve_ << std::endl;
874  std::cout << p << "Time for solve = "
875  << SolTime * NumSolve_ << " (s), avg = " << SolTime << " (s)" << std::endl;
876 
877  double tt = NumTime * NumNumericFact_ + SolTime * NumSolve_;
878  if (tt != 0)
879  {
880  std::cout << p << "Total time spent in Amesos = " << tt << " (s) " << std::endl;
881  std::cout << p << "Total time spent in the Amesos interface = " << OveTime << " (s)" << std::endl;
882  std::cout << p << "(the above time does not include SuperLU_DIST time)" << std::endl;
883  std::cout << p << "Amesos interface time / total time = " << OveTime / tt << std::endl;
884  }
885 
886  PrintLine();
887 
888  return;
889 }
int NumSymbolicFact_
Number of symbolic factorization phases.
Definition: Amesos_Status.h:67
bool UseTranspose() const
Always returns false. Superludist doesn&#39;t support transpose solve.
int LRID(int GRID_in) const
int NumGlobalElements() const
virtual const Epetra_Map & RowMatrixRowMap() const =0
void PrintLine() const
Prints line on std::cout.
Definition: Amesos_Utils.h:71
int Solve()
Solves A X = B (or AT x = B)
bool ReuseSymbolic_
Allows FactOption to be used on subsequent calls to pdgssvx from NumericFactorization.
Epetra_MultiVector * GetLHS() const
Epetra_MultiVector * GetRHS() const
bool MatrixShapeOK() const
Returns true if SUPERLUDIST can handle this matrix shape.
bool FactorizationOK_
true if NumericFactorization() has been successfully called.
std::vector< int > Ap_
int MyGlobalElements(int *MyGlobalElementList) const
T & get(ParameterList &l, const std::string &name)
~Amesos_Superludist(void)
Amesos_Superludist Destructor.
bool Redistribute_
redistribute the input matrix prior to calling Superludist
virtual int InsertGlobalValues(int GlobalRow, int NumEntries, const double *Values, const int *Indices)
const Epetra_Import & Importer() const
ScalePermstruct_t ScalePermstruct_
bool AddZeroToDiag_
Adds zero to diagonal of redistributed matrix (some solvers choke on a matrix with a partly empty dia...
RCP< ParameterList > sublist(const RCP< ParameterList > &paramList, const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
int SymbolicFactorization()
Performs SymbolicFactorization on the matrix A.
void SetMaxProcesses(int &MaxProcesses, const Epetra_RowMatrix &A)
Definition: Amesos_Utils.h:77
void CreateTimer(const Epetra_Comm &Comm, int size=1)
Initializes the Time object.
Definition: Amesos_Time.h:64
#define EPETRA_MIN(x, y)
const Epetra_RowMatrix & UniformMatrix() const
int NumNumericFact_
Number of numeric factorization phases.
Definition: Amesos_Status.h:69
virtual int NumGlobalNonzeros() const =0
int GridCreated_
true if the SuperLU_DIST&#39;s grid has been created (and has to be free&#39;d)
virtual int MyPID() const =0
int FillComplete(bool OptimizeDataStorage=true)
int SetParameters(Teuchos::ParameterList &ParameterList)
Updates internal variables.
int ExtractMyRowView(int MyRow, int &NumEntries, double *&Values, int *&Indices) const
int NumSolve_
Number of solves.
Definition: Amesos_Status.h:71
bool isParameter(const std::string &name) const
Epetra_CrsMatrix & CrsUniformMatrix()
Epetra_RowMatrix * RowMatrixA_
virtual int MaxNumEntries() const =0
std::vector< double > Aval_
int NumericFactorization()
Performs NumericFactorization on the matrix A.
void SetStatusParameters(const Teuchos::ParameterList &ParameterList)
const Epetra_LinearProblem * GetProblem() const
Returns the Epetra_LinearProblem.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
bool ComputeVectorNorms_
If true, prints the norms of X and B in Solve().
Definition: Amesos_Status.h:56
void SetControlParameters(const Teuchos::ParameterList &ParameterList)
RCP< Epetra_Map > UniformMap_
#define AMESOS_CHK_ERR(a)
bool isSublist(const std::string &name) const
bool PrintTiming_
If true, prints timing information in the destructor.
Definition: Amesos_Status.h:52
virtual int NumMyRows() const =0
gridinfo_t grid_
SuperLU_DIST&#39;s grid information.
MPI_Comm Comm() const
int * Global_Columns_
Contains the global ID of local columns.
bool PrintStatus_
If true, print additional information in the destructor.
Definition: Amesos_Status.h:54
Teuchos::RCP< Amesos_Superlu_Pimpl > PrivateSuperluData_
int AddTime(const std::string what, int dataID, const int timerID=0)
Adds to field what the time elapsed since last call to ResetTimer().
Definition: Amesos_Time.h:80
int MinMyGID() const
bool LinearMap() const
RCP< Epetra_RowMatrix > UniformMatrix_
virtual int NumProc() const =0
void ComputeTrueResidual(const Epetra_RowMatrix &Matrix, const Epetra_MultiVector &X, const Epetra_MultiVector &B, const bool UseTranspose, const std::string prefix) const
Computes the true residual, B - Matrix * X, and prints the results.
Definition: Amesos_Utils.h:29
int NumGlobalRows_
Global dimension of the matrix.
int SetNPRowAndCol(const int MaxProcesses, int &nprow, int &npcol)
Amesos_Superludist(const Epetra_LinearProblem &LinearProblem)
Amesos_Superludist Constructor.
Teuchos::RCP< Epetra_Import > Importer_
const Epetra_Comm & Comm() const
Returns a pointer to the Epetra_Comm communicator associated with this operator.
void ResetTimer(const int timerID=0)
Resets the internally stored time object.
Definition: Amesos_Time.h:74
void PrintStatus() const
Print various information about the parameters used by Superludist.
virtual int ExtractMyRowCopy(int MyRow, int Length, int &NumEntries, double *Values, int *Indices) const =0
Epetra_Operator * GetOperator() const
virtual const Epetra_Map & RowMatrixColMap() const =0
double GetTime(const std::string what) const
Gets the cumulative time using the string.
Definition: Amesos_Time.h:102
int Superludist_NumProcRows(int NumProcs)
const Epetra_LinearProblem * Problem_
RCP< Epetra_CrsMatrix > CrsUniformMatrix_
virtual int NumGlobalRows() const =0
virtual int NumMyNonzeros() const =0
#define EPETRA_MAX(x, y)
std::vector< int > Ai_
void ComputeVectorNorms(const Epetra_MultiVector &X, const Epetra_MultiVector &B, const std::string prefix) const
Computes the norms of X and B and print the results.
Definition: Amesos_Utils.h:52
void PrintTiming() const
Print various timig.
bool ComputeTrueResidual_
If true, computes the true residual in Solve().
Definition: Amesos_Status.h:58
superlu_options_t options_
Vector of options.
double AddToDiag_
Add this value to the diagonal.