![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
00001 /************************************************************************ 00002 * MechSys - Open Library for Mechanical Systems * 00003 * Copyright (C) 2005 Dorival M. Pedroso, Raul Durand * 00004 * Copyright (C) 2009 Sergio Galindo * 00005 * * 00006 * This program is free software: you can redistribute it and/or modify * 00007 * it under the terms of the GNU General Public License as published by * 00008 * the Free Software Foundation, either version 3 of the License, or * 00009 * any later version. * 00010 * * 00011 * This program is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00014 * GNU General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU General Public License * 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> * 00018 ************************************************************************/ 00019 00020 #ifndef MECHSYS_SUPERLUD_H 00021 #define MECHSYS_SUPERLUD_H 00022 00023 // SuperLU_DIST 00024 #include <superlu_ddefs.h> 00025 00026 // MechSys 00027 #include <mechsys/linalg/matvec.h> 00028 #include <mechsys/linalg/sparse_crmatrix.h> 00029 #include <mechsys/util/fatal.h> 00030 #include <mechsys/util/util.h> 00031 00032 #ifdef DO_DEBUG 00033 #include <iostream> 00034 #include <sstream> 00035 using std::cout; 00036 using std::endl; 00037 #endif 00038 00039 namespace SuperLUd 00040 { 00041 00056 inline void Solve(int MyMinEq, int MyMaxEq, int MyNumEqs, int nProcs, int nDOFs, Sparse::CRMatrix<double,int> & AugLocalA, Vec_t & GlobalB) 00057 { 00058 00059 // Sizes 00060 int m_loc = MyNumEqs; // local number of rows (equations) 00061 int m = nDOFs; // global number of rows 00062 int n = nDOFs; // global number of cols (must be equal to m for SuperLU_DIST) 00063 00064 // 1) Set SuperLU distributed matrix ------------------------------------------------ 00065 00066 // Local Aq array 00067 int * Aq = new int [m_loc+1]; 00068 for (int i=0; i<m_loc+1; ++i) Aq[i] = AugLocalA.Aq(MyMinEq+i)-AugLocalA.Aq(MyMinEq); 00069 int nz_loc = Aq[m_loc]; // number of non-zeros in the local matrix 00070 00071 // Create matrix A in the format expected by SuperLU_DIST 00072 int start = AugLocalA.Aq(MyMinEq); 00073 double const * Ay = &AugLocalA.GetAyPtr()[start]; 00074 int const * Aj = &AugLocalA.GetAjPtr()[start]; 00075 NRformat_loc nrfl = { nz_loc, m_loc, MyMinEq, const_cast<double*>(Ay), Aq, const_cast<int*>(Aj) }; // Note: The initialization order of Aq and Aj is different of the order of Ai and Ap for the NCformat! 00076 SuperMatrix a = { /*Stype=CRMatrix_dist*/SLU_NR_loc, /*Dtype=double*/SLU_D, /*Mtype=general*/SLU_GE, m, n, &nrfl }; 00077 00078 // 2) Initialize the SuperLU process grid ------------------------------------------- 00079 00080 gridinfo_t grid; // grid info 00081 int nprow; // number of processors in each row of grid 00082 int npcol; // number of processors in each column of grid 00083 Util::FindBestSquare (nProcs, nprow,npcol); 00084 superlu_gridinit (MPI::COMM_WORLD, nprow, npcol, &grid); 00085 00086 // Bail out if I do not belong in the grid 00087 if (grid.iam>=nprow*npcol) throw new Fatal(_("SuperLUd::Gesv: SuperLU's grid was not created properly: grid.iam=%d > nprow*npcol=%d"),grid.iam,nprow*npcol); 00088 00089 // 3) Solve the linear system ------------------------------------------------------- 00090 00091 // Set the input options 00092 superlu_options_t opts; 00093 opts.Fact = DOFACT; 00094 opts.Equil = YES; 00095 opts.ColPerm = MMD_AT_PLUS_A; // NATURAL 00096 opts.Trans = NOTRANS; 00097 opts.IterRefine = NOREFINE; // DOUBLE 00098 opts.PrintStat = NO; 00099 opts.RowPerm = NOROWPERM; // LargeDiag 00100 opts.ReplaceTinyPivot = YES; 00101 opts.SolveInitialized = NO; 00102 opts.RefineInitialized = NO; 00103 00104 // Initialize ScalePermstruct and LUstruct 00105 ScalePermstruct_t scp; 00106 LUstruct_t lus; 00107 ScalePermstructInit (m, n, &scp); 00108 LUstructInit (m, n, &lus); 00109 00110 // Initialize the statistics variables 00111 SuperLUStat_t stat; 00112 PStatInit (&stat); 00113 00114 // Call the linear equation solver 00115 int info; 00116 double berr; // size == nrhs 00117 SOLVEstruct_t svs; 00118 pdgssvx (&opts, &a, &scp, &GlobalB.data[MyMinEq], /*ldb*/m, /*nrhs*/1, &grid, &lus, &svs, &berr, &stat, &info); 00119 00120 #ifdef DO_DEBUGx 00121 int rank = MPI::COMM_WORLD.Get_rank(); 00122 //LinAlg::Matrix<double> D; AugLocalA.GetDense(D); 00123 std::ostringstream oss; 00124 //oss << "Processor #" << rank << " LocalA=\n" << D << endl; 00125 //oss << "Processor #" << rank << " LocalA=\n" << AugLocalA << endl; 00126 oss<<"Processor #" << rank << " "; 00127 oss<<"Aq={"; for (int i=0; i<m_loc+1; ++i) { oss<<Aq[i]; if (i!=m_loc) oss<<","; }; oss<<"} "; 00128 oss<<"Aj={"; for (int i=0; i<nz_loc; ++i) { oss<<AugLocalA.Aj(start+i); if (i!=nz_loc-1) oss<<","; }; oss<<"} "; 00129 oss<<"Ay={"; for (int i=0; i<nz_loc; ++i) { oss<<AugLocalA.Ay(start+i); if (i!=nz_loc-1) oss<<","; }; oss<<"} "; 00130 oss<<"B={"; for (int i=0; i<m_loc; ++i) { oss<<GlobalB(MyMinEq+i); if (i!=m_loc-1) oss<<","; }; oss<<"}\n"; 00131 cout<<oss.str(); 00132 //dPrint_CompRowLoc_Matrix_dist(&a); 00133 #endif 00134 00135 // Print the statistics 00136 //PStatPrint (&opts, &stat, &grid); 00137 00138 // 4) Deallocate storage ------------------------------------------------------------ 00139 00140 PStatFree (&stat); 00141 ScalePermstructFree (&scp); 00142 Destroy_LU (n, &grid, &lus); 00143 LUstructFree (&lus); 00144 if (opts.SolveInitialized) dSolveFinalize (&opts, &svs); 00145 delete [] Aq; 00146 00147 // 5) Release the SuperLU process grid ---------------------------------------------- 00148 00149 superlu_gridexit (&grid); 00150 00151 } 00152 00153 }; // namespace SuperLU 00154 00155 #endif // MECHSYS_SUPERLUD_H