$search
00001 /* 00002 * OpenNL: Numerical Library 00003 * Copyright (C) 2004 Bruno Levy 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 * 00019 * If you modify this software, you should include a notice giving the 00020 * name of the person performing the modification, the date of modification, 00021 * and the reason for such modification. 00022 * 00023 * Contact: Bruno Levy 00024 * 00025 * levy@loria.fr 00026 * 00027 * ISA Project 00028 * LORIA, INRIA Lorraine, 00029 * Campus Scientifique, BP 239 00030 * 54506 VANDOEUVRE LES NANCY CEDEX 00031 * FRANCE 00032 * 00033 * Note that the GNU General Public License does not permit incorporating 00034 * the Software into proprietary programs. 00035 */ 00036 00037 #include <NL/nl_superlu.h> 00038 #include <NL/nl_context.h> 00039 00040 /************************************************************************/ 00041 /* SuperLU wrapper */ 00042 00043 #ifdef NL_USE_SUPERLU 00044 00045 /* SuperLU includes */ 00046 #include <slu_ddefs.h> 00047 00048 /* Note: SuperLU is difficult to call, but it is worth it. */ 00049 /* Here is a driver inspired by A. Sheffer's "cow flattener". */ 00050 NLboolean nlSolve_SUPERLU() { 00051 00052 /* OpenNL Context */ 00053 NLSparseMatrix* M = &(nlCurrentContext->M) ; 00054 NLdouble* b = nlCurrentContext->b ; 00055 NLdouble* x = nlCurrentContext->x ; 00056 00057 /* Compressed Row Storage matrix representation */ 00058 NLuint n = nlCurrentContext->n ; 00059 NLuint nnz = nlSparseMatrixNNZ(M) ; /* Number of Non-Zero coeffs */ 00060 NLint* xa = NL_NEW_ARRAY(NLint, n+1) ; 00061 NLdouble* rhs = NL_NEW_ARRAY(NLdouble, n) ; 00062 NLdouble* a = NL_NEW_ARRAY(NLdouble, nnz) ; 00063 NLint* asub = NL_NEW_ARRAY(NLint, nnz) ; 00064 00065 /* Permutation vector */ 00066 NLint* perm_r = NL_NEW_ARRAY(NLint, n) ; 00067 NLint* perm = NL_NEW_ARRAY(NLint, n) ; 00068 00069 /* SuperLU variables */ 00070 SuperMatrix A, B ; /* System */ 00071 SuperMatrix L, U ; /* Inverse of A */ 00072 NLint info ; /* status code */ 00073 DNformat *vals = NULL ; /* access to result */ 00074 double *rvals = NULL ; /* access to result */ 00075 00076 /* SuperLU options and stats */ 00077 superlu_options_t options ; 00078 SuperLUStat_t stat ; 00079 00080 /* Temporary variables */ 00081 NLRowColumn* Ri = NULL ; 00082 NLuint i,jj,count ; 00083 00084 /* Sanity checks */ 00085 nl_assert(!(M->storage & NL_MATRIX_STORE_SYMMETRIC)) ; 00086 nl_assert(M->storage & NL_MATRIX_STORE_ROWS) ; 00087 nl_assert(M->m == M->n) ; 00088 00089 /* 00090 * Step 1: convert matrix M into SuperLU compressed column 00091 * representation. 00092 * ------------------------------------------------------- 00093 */ 00094 00095 count = 0 ; 00096 for(i=0; i<n; i++) { 00097 Ri = &(M->row[i]) ; 00098 xa[i] = count ; 00099 for(jj=0; jj<Ri->size; jj++) { 00100 a[count] = Ri->coeff[jj].value ; 00101 asub[count] = Ri->coeff[jj].index ; 00102 count++ ; 00103 } 00104 } 00105 xa[n] = nnz ; 00106 00107 /* Save memory for SuperLU */ 00108 nlSparseMatrixClear(M) ; 00109 00110 00111 /* 00112 * Rem: SuperLU does not support symmetric storage. 00113 * In fact, for symmetric matrix, what we need 00114 * is a SuperLLt algorithm (SuperNodal sparse Cholesky), 00115 * but it does not exist, anybody wants to implement it ? 00116 * However, this is not a big problem (SuperLU is just 00117 * a superset of what we really need. 00118 */ 00119 dCreate_CompCol_Matrix( 00120 &A, n, n, nnz, a, asub, xa, 00121 SLU_NR, /* Row_wise, no supernode */ 00122 SLU_D, /* doubles */ 00123 SLU_GE /* general storage */ 00124 ); 00125 00126 /* Step 2: create vector */ 00127 dCreate_Dense_Matrix( 00128 &B, n, 1, b, n, 00129 SLU_DN, /* Fortran-type column-wise storage */ 00130 SLU_D, /* doubles */ 00131 SLU_GE /* general */ 00132 ); 00133 00134 00135 /* Step 3: set SuperLU options 00136 * ------------------------------ 00137 */ 00138 00139 set_default_options(&options) ; 00140 00141 switch(nlCurrentContext->solver) { 00142 case NL_SUPERLU_EXT: { 00143 options.ColPerm = NATURAL ; 00144 } break ; 00145 case NL_PERM_SUPERLU_EXT: { 00146 options.ColPerm = COLAMD ; 00147 } break ; 00148 case NL_SYMMETRIC_SUPERLU_EXT: { 00149 options.ColPerm = MMD_AT_PLUS_A ; 00150 options.SymmetricMode = YES ; 00151 } break ; 00152 default: { 00153 nl_assert_not_reached ; 00154 } break ; 00155 } 00156 00157 StatInit(&stat) ; 00158 00159 /* Step 4: call SuperLU main routine 00160 * --------------------------------- 00161 */ 00162 00163 dgssv(&options, &A, perm, perm_r, &L, &U, &B, &stat, &info); 00164 00165 /* Step 5: get the solution 00166 * ------------------------ 00167 * Fortran-type column-wise storage 00168 */ 00169 vals = (DNformat*)B.Store; 00170 rvals = (double*)(vals->nzval); 00171 if(info == 0) { 00172 for(i = 0; i < n; i++){ 00173 x[i] = rvals[i]; 00174 } 00175 } else { 00176 nlError("nlSolve()", "SuperLU failed") ; 00177 } 00178 00179 /* Step 6: cleanup 00180 * --------------- 00181 */ 00182 00183 /* 00184 * For these two ones, only the "store" structure 00185 * needs to be deallocated (the arrays have been allocated 00186 * by us). 00187 */ 00188 Destroy_SuperMatrix_Store(&A) ; 00189 Destroy_SuperMatrix_Store(&B) ; 00190 00191 /* 00192 * These ones need to be fully deallocated (they have been 00193 * allocated by SuperLU). 00194 */ 00195 Destroy_SuperNode_Matrix(&L); 00196 Destroy_CompCol_Matrix(&U); 00197 00198 /* There are some dynamically allocated vectors in the stats */ 00199 StatFree(&stat) ; 00200 00201 NL_DELETE_ARRAY(xa) ; 00202 NL_DELETE_ARRAY(rhs) ; 00203 NL_DELETE_ARRAY(a) ; 00204 NL_DELETE_ARRAY(asub) ; 00205 NL_DELETE_ARRAY(perm_r) ; 00206 NL_DELETE_ARRAY(perm) ; 00207 00208 return (info == 0) ; 00209 } 00210 00211 #else 00212 00213 NLboolean nlSolve_SUPERLU() { 00214 nl_assert_not_reached ; 00215 } 00216 00217 #endif 00218