1 2 /* 3 Provides an interface to the LUSOL package of .... 4 5 */ 6 #include <../src/mat/impls/aij/seq/aij.h> 7 8 #if defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 9 #define LU1FAC lu1fac_ 10 #define LU6SOL lu6sol_ 11 #define M1PAGE m1page_ 12 #define M5SETX m5setx_ 13 #define M6RDEL m6rdel_ 14 #elif !defined(PETSC_HAVE_FORTRAN_CAPS) 15 #define LU1FAC lu1fac 16 #define LU6SOL lu6sol 17 #define M1PAGE m1page 18 #define M5SETX m5setx 19 #define M6RDEL m6rdel 20 #endif 21 22 EXTERN_C_BEGIN 23 /* 24 Dummy symbols that the MINOS files mi25bfac.f and mi15blas.f may require 25 */ 26 void PETSC_STDCALL M1PAGE() 27 { 28 ; 29 } 30 void PETSC_STDCALL M5SETX() 31 { 32 ; 33 } 34 35 void PETSC_STDCALL M6RDEL() 36 { 37 ; 38 } 39 40 extern void PETSC_STDCALL LU1FAC (int *m, int *n, int *nnz, int *size, int *luparm, 41 double *parmlu, double *data, int *indc, int *indr, 42 int *rowperm, int *colperm, int *collen, int *rowlen, 43 int *colstart, int *rowstart, int *rploc, int *cploc, 44 int *rpinv, int *cpinv, double *w, int *inform); 45 46 extern void PETSC_STDCALL LU6SOL (int *mode, int *m, int *n, double *rhs, double *x, 47 int *size, int *luparm, double *parmlu, double *data, 48 int *indc, int *indr, int *rowperm, int *colperm, 49 int *collen, int *rowlen, int *colstart, int *rowstart, 50 int *inform); 51 EXTERN_C_END 52 53 extern PetscErrorCode MatDuplicate_LUSOL(Mat,MatDuplicateOption,Mat*); 54 55 typedef struct { 56 double *data; 57 int *indc; 58 int *indr; 59 60 int *ip; 61 int *iq; 62 int *lenc; 63 int *lenr; 64 int *locc; 65 int *locr; 66 int *iploc; 67 int *iqloc; 68 int *ipinv; 69 int *iqinv; 70 double *mnsw; 71 double *mnsv; 72 73 double elbowroom; 74 double luroom; /* Extra space allocated when factor fails */ 75 double parmlu[30]; /* Input/output to LUSOL */ 76 77 int n; /* Number of rows/columns in matrix */ 78 int nz; /* Number of nonzeros */ 79 int nnz; /* Number of nonzeros allocated for factors */ 80 int luparm[30]; /* Input/output to LUSOL */ 81 82 PetscBool CleanUpLUSOL; 83 84 } Mat_LUSOL; 85 86 /* LUSOL input/Output Parameters (Description uses C-style indexes 87 * 88 * Input parameters Typical value 89 * 90 * luparm(0) = nout File number for printed messages. 6 91 * luparm(1) = lprint Print level. 0 92 * < 0 suppresses output. 93 * = 0 gives error messages. 94 * = 1 gives debug output from some of the 95 * other routines in LUSOL. 96 * >= 2 gives the pivot row and column and the 97 * no. of rows and columns involved at 98 * each elimination step in lu1fac. 99 * luparm(2) = maxcol lu1fac: maximum number of columns 5 100 * searched allowed in a Markowitz-type 101 * search for the next pivot element. 102 * For some of the factorization, the 103 * number of rows searched is 104 * maxrow = maxcol - 1. 105 * 106 * 107 * Output parameters 108 * 109 * luparm(9) = inform Return code from last call to any LU routine. 110 * luparm(10) = nsing No. of singularities marked in the 111 * output array w(*). 112 * luparm(11) = jsing Column index of last singularity. 113 * luparm(12) = minlen Minimum recommended value for lena. 114 * luparm(13) = maxlen ? 115 * luparm(14) = nupdat No. of updates performed by the lu8 routines. 116 * luparm(15) = nrank No. of nonempty rows of U. 117 * luparm(16) = ndens1 No. of columns remaining when the density of 118 * the matrix being factorized reached dens1. 119 * luparm(17) = ndens2 No. of columns remaining when the density of 120 * the matrix being factorized reached dens2. 121 * luparm(18) = jumin The column index associated with dumin. 122 * luparm(19) = numl0 No. of columns in initial L. 123 * luparm(20) = lenl0 Size of initial L (no. of nonzeros). 124 * luparm(21) = lenu0 Size of initial U. 125 * luparm(22) = lenl Size of current L. 126 * luparm(23) = lenu Size of current U. 127 * luparm(24) = lrow Length of row file. 128 * luparm(25) = ncp No. of compressions of LU data structures. 129 * luparm(26) = mersum lu1fac: sum of Markowitz merit counts. 130 * luparm(27) = nutri lu1fac: triangular rows in U. 131 * luparm(28) = nltri lu1fac: triangular rows in L. 132 * luparm(29) = 133 * 134 * 135 * Input parameters Typical value 136 * 137 * parmlu(0) = elmax1 Max multiplier allowed in L 10.0 138 * during factor. 139 * parmlu(1) = elmax2 Max multiplier allowed in L 10.0 140 * during updates. 141 * parmlu(2) = small Absolute tolerance for eps**0.8 142 * treating reals as zero. IBM double: 3.0d-13 143 * parmlu(3) = utol1 Absolute tol for flagging eps**0.66667 144 * small diagonals of U. IBM double: 3.7d-11 145 * parmlu(4) = utol2 Relative tol for flagging eps**0.66667 146 * small diagonals of U. IBM double: 3.7d-11 147 * parmlu(5) = uspace Factor limiting waste space in U. 3.0 148 * In lu1fac, the row or column lists 149 * are compressed if their length 150 * exceeds uspace times the length of 151 * either file after the last compression. 152 * parmlu(6) = dens1 The density at which the Markowitz 0.3 153 * strategy should search maxcol columns 154 * and no rows. 155 * parmlu(7) = dens2 the density at which the Markowitz 0.6 156 * strategy should search only 1 column 157 * or (preferably) use a dense LU for 158 * all the remaining rows and columns. 159 * 160 * 161 * Output parameters 162 * 163 * parmlu(9) = amax Maximum element in A. 164 * parmlu(10) = elmax Maximum multiplier in current L. 165 * parmlu(11) = umax Maximum element in current U. 166 * parmlu(12) = dumax Maximum diagonal in U. 167 * parmlu(13) = dumin Minimum diagonal in U. 168 * parmlu(14) = 169 * parmlu(15) = 170 * parmlu(16) = 171 * parmlu(17) = 172 * parmlu(18) = 173 * parmlu(19) = resid lu6sol: residual after solve with U or U'. 174 * ... 175 * parmlu(29) = 176 */ 177 178 #define Factorization_Tolerance 1e-1 179 #define Factorization_Pivot_Tolerance pow(2.2204460492503131E-16, 2.0 / 3.0) 180 #define Factorization_Small_Tolerance 1e-15 /* pow(DBL_EPSILON, 0.8) */ 181 182 #undef __FUNCT__ 183 #define __FUNCT__ "MatDestroy_LUSOL" 184 PetscErrorCode MatDestroy_LUSOL(Mat A) 185 { 186 PetscErrorCode ierr; 187 Mat_LUSOL *lusol=(Mat_LUSOL *)A->spptr; 188 189 PetscFunctionBegin; 190 if (lusol && lusol->CleanUpLUSOL) { 191 ierr = PetscFree(lusol->ip);CHKERRQ(ierr); 192 ierr = PetscFree(lusol->iq);CHKERRQ(ierr); 193 ierr = PetscFree(lusol->lenc);CHKERRQ(ierr); 194 ierr = PetscFree(lusol->lenr);CHKERRQ(ierr); 195 ierr = PetscFree(lusol->locc);CHKERRQ(ierr); 196 ierr = PetscFree(lusol->locr);CHKERRQ(ierr); 197 ierr = PetscFree(lusol->iploc);CHKERRQ(ierr); 198 ierr = PetscFree(lusol->iqloc);CHKERRQ(ierr); 199 ierr = PetscFree(lusol->ipinv);CHKERRQ(ierr); 200 ierr = PetscFree(lusol->iqinv);CHKERRQ(ierr); 201 ierr = PetscFree(lusol->mnsw);CHKERRQ(ierr); 202 ierr = PetscFree(lusol->mnsv);CHKERRQ(ierr); 203 ierr = PetscFree3(lusol->data,lusol->indc,lusol->indr);CHKERRQ(ierr); 204 } 205 ierr = PetscFree(A->spptr);CHKERRQ(ierr); 206 ierr = MatDestroy_SeqAIJ(A);CHKERRQ(ierr); 207 PetscFunctionReturn(0); 208 } 209 210 #undef __FUNCT__ 211 #define __FUNCT__ "MatSolve_LUSOL" 212 PetscErrorCode MatSolve_LUSOL(Mat A,Vec b,Vec x) 213 { 214 Mat_LUSOL *lusol=(Mat_LUSOL*)A->spptr; 215 double *bb,*xx; 216 int mode=5; 217 PetscErrorCode ierr; 218 int i,m,n,nnz,status; 219 220 PetscFunctionBegin; 221 ierr = VecGetArray(x, &xx);CHKERRQ(ierr); 222 ierr = VecGetArray(b, &bb);CHKERRQ(ierr); 223 224 m = n = lusol->n; 225 nnz = lusol->nnz; 226 227 for (i = 0; i < m; i++) 228 { 229 lusol->mnsv[i] = bb[i]; 230 } 231 232 LU6SOL(&mode, &m, &n, lusol->mnsv, xx, &nnz, 233 lusol->luparm, lusol->parmlu, lusol->data, 234 lusol->indc, lusol->indr, lusol->ip, lusol->iq, 235 lusol->lenc, lusol->lenr, lusol->locc, lusol->locr, &status); 236 237 if (status) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"solve failed, error code %d",status); 238 239 ierr = VecRestoreArray(x, &xx);CHKERRQ(ierr); 240 ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr); 241 PetscFunctionReturn(0); 242 } 243 244 #undef __FUNCT__ 245 #define __FUNCT__ "MatLUFactorNumeric_LUSOL" 246 PetscErrorCode MatLUFactorNumeric_LUSOL(Mat F,Mat A,const MatFactorInfo *info) 247 { 248 Mat_SeqAIJ *a; 249 Mat_LUSOL *lusol = (Mat_LUSOL*)F->spptr; 250 PetscErrorCode ierr; 251 int m, n, nz, nnz, status; 252 int i, rs, re; 253 int factorizations; 254 255 PetscFunctionBegin; 256 ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr);CHKERRQ(ierr); 257 a = (Mat_SeqAIJ *)A->data; 258 259 if (m != lusol->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"factorization struct inconsistent"); 260 261 factorizations = 0; 262 do 263 { 264 /*******************************************************************/ 265 /* Check the workspace allocation. */ 266 /*******************************************************************/ 267 268 nz = a->nz; 269 nnz = PetscMax(lusol->nnz, (int)(lusol->elbowroom*nz)); 270 nnz = PetscMax(nnz, 5*n); 271 272 if (nnz < lusol->luparm[12]) { 273 nnz = (int)(lusol->luroom * lusol->luparm[12]); 274 } else if ((factorizations > 0) && (lusol->luroom < 6)) { 275 lusol->luroom += 0.1; 276 } 277 278 nnz = PetscMax(nnz, (int)(lusol->luroom*(lusol->luparm[22] + lusol->luparm[23]))); 279 280 if (nnz > lusol->nnz) { 281 ierr = PetscFree3(lusol->data,lusol->indc,lusol->indr);CHKERRQ(ierr); 282 ierr = PetscMalloc3(nnz,double,&lusol->data,nnz,PetscInt,&lusol->indc,nnz,PetscInt,&lusol->indr);CHKERRQ(ierr); 283 lusol->nnz = nnz; 284 } 285 286 /*******************************************************************/ 287 /* Fill in the data for the problem. (1-based Fortran style) */ 288 /*******************************************************************/ 289 290 nz = 0; 291 for (i = 0; i < n; i++) 292 { 293 rs = a->i[i]; 294 re = a->i[i+1]; 295 296 while (rs < re) 297 { 298 if (a->a[rs] != 0.0) 299 { 300 lusol->indc[nz] = i + 1; 301 lusol->indr[nz] = a->j[rs] + 1; 302 lusol->data[nz] = a->a[rs]; 303 nz++; 304 } 305 rs++; 306 } 307 } 308 309 /*******************************************************************/ 310 /* Do the factorization. */ 311 /*******************************************************************/ 312 313 LU1FAC(&m, &n, &nz, &nnz, 314 lusol->luparm, lusol->parmlu, lusol->data, 315 lusol->indc, lusol->indr, lusol->ip, lusol->iq, 316 lusol->lenc, lusol->lenr, lusol->locc, lusol->locr, 317 lusol->iploc, lusol->iqloc, lusol->ipinv, 318 lusol->iqinv, lusol->mnsw, &status); 319 320 switch(status) 321 { 322 case 0: /* factored */ 323 break; 324 325 case 7: /* insufficient memory */ 326 break; 327 328 case 1: 329 case -1: /* singular */ 330 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Singular matrix"); 331 332 case 3: 333 case 4: /* error conditions */ 334 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"matrix error"); 335 336 default: /* unknown condition */ 337 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"matrix unknown return code"); 338 } 339 340 factorizations++; 341 } while (status == 7); 342 F->ops->solve = MatSolve_LUSOL; 343 F->assembled = PETSC_TRUE; 344 F->preallocated = PETSC_TRUE; 345 PetscFunctionReturn(0); 346 } 347 348 #undef __FUNCT__ 349 #define __FUNCT__ "MatLUFactorSymbolic_LUSOL" 350 PetscErrorCode MatLUFactorSymbolic_LUSOL(Mat F,Mat A, IS r, IS c,const MatFactorInfo *info) 351 { 352 /************************************************************************/ 353 /* Input */ 354 /* A - matrix to factor */ 355 /* r - row permutation (ignored) */ 356 /* c - column permutation (ignored) */ 357 /* */ 358 /* Output */ 359 /* F - matrix storing the factorization; */ 360 /************************************************************************/ 361 Mat_LUSOL *lusol; 362 PetscErrorCode ierr; 363 int i, m, n, nz, nnz; 364 365 PetscFunctionBegin; 366 367 /************************************************************************/ 368 /* Check the arguments. */ 369 /************************************************************************/ 370 371 ierr = MatGetSize(A, &m, &n);CHKERRQ(ierr); 372 nz = ((Mat_SeqAIJ *)A->data)->nz; 373 374 /************************************************************************/ 375 /* Create the factorization. */ 376 /************************************************************************/ 377 378 F->ops->lufactornumeric = MatLUFactorNumeric_LUSOL; 379 lusol = (Mat_LUSOL*)(F->spptr); 380 381 /************************************************************************/ 382 /* Initialize parameters */ 383 /************************************************************************/ 384 385 for (i = 0; i < 30; i++) 386 { 387 lusol->luparm[i] = 0; 388 lusol->parmlu[i] = 0; 389 } 390 391 lusol->luparm[1] = -1; 392 lusol->luparm[2] = 5; 393 lusol->luparm[7] = 1; 394 395 lusol->parmlu[0] = 1 / Factorization_Tolerance; 396 lusol->parmlu[1] = 1 / Factorization_Tolerance; 397 lusol->parmlu[2] = Factorization_Small_Tolerance; 398 lusol->parmlu[3] = Factorization_Pivot_Tolerance; 399 lusol->parmlu[4] = Factorization_Pivot_Tolerance; 400 lusol->parmlu[5] = 3.0; 401 lusol->parmlu[6] = 0.3; 402 lusol->parmlu[7] = 0.6; 403 404 /************************************************************************/ 405 /* Allocate the workspace needed by LUSOL. */ 406 /************************************************************************/ 407 408 lusol->elbowroom = PetscMax(lusol->elbowroom, info->fill); 409 nnz = PetscMax((int)(lusol->elbowroom*nz), 5*n); 410 411 lusol->n = n; 412 lusol->nz = nz; 413 lusol->nnz = nnz; 414 lusol->luroom = 1.75; 415 416 ierr = PetscMalloc(sizeof(int)*n,&lusol->ip); 417 ierr = PetscMalloc(sizeof(int)*n,&lusol->iq); 418 ierr = PetscMalloc(sizeof(int)*n,&lusol->lenc); 419 ierr = PetscMalloc(sizeof(int)*n,&lusol->lenr); 420 ierr = PetscMalloc(sizeof(int)*n,&lusol->locc); 421 ierr = PetscMalloc(sizeof(int)*n,&lusol->locr); 422 ierr = PetscMalloc(sizeof(int)*n,&lusol->iploc); 423 ierr = PetscMalloc(sizeof(int)*n,&lusol->iqloc); 424 ierr = PetscMalloc(sizeof(int)*n,&lusol->ipinv); 425 ierr = PetscMalloc(sizeof(int)*n,&lusol->iqinv); 426 ierr = PetscMalloc(sizeof(double)*n,&lusol->mnsw); 427 ierr = PetscMalloc(sizeof(double)*n,&lusol->mnsv); 428 429 ierr = PetscMalloc3(nnz,double,&lusol->data,nnz,PetscInt,&lusol->indc,nnz,PetscInt,&lusol->indr);CHKERRQ(ierr); 430 lusol->CleanUpLUSOL = PETSC_TRUE; 431 F->ops->lufactornumeric = MatLUFactorNumeric_LUSOL; 432 PetscFunctionReturn(0); 433 } 434 435 EXTERN_C_BEGIN 436 #undef __FUNCT__ 437 #define __FUNCT__ "MatFactorGetSolverPackage_seqaij_lusol" 438 PetscErrorCode MatFactorGetSolverPackage_seqaij_lusol(Mat A,const MatSolverPackage *type) 439 { 440 PetscFunctionBegin; 441 *type = MATSOLVERLUSOL; 442 PetscFunctionReturn(0); 443 } 444 EXTERN_C_END 445 446 #undef __FUNCT__ 447 #define __FUNCT__ "MatGetFactor_seqaij_lusol" 448 PetscErrorCode MatGetFactor_seqaij_lusol(Mat A,MatFactorType ftype,Mat *F) 449 { 450 Mat B; 451 Mat_LUSOL *lusol; 452 PetscErrorCode ierr; 453 int m, n; 454 455 PetscFunctionBegin; 456 ierr = MatGetSize(A, &m, &n);CHKERRQ(ierr); 457 ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr); 458 ierr = MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,m,n);CHKERRQ(ierr); 459 ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); 460 ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr); 461 462 ierr = PetscNewLog(B,Mat_LUSOL,&lusol);CHKERRQ(ierr); 463 B->spptr = lusol; 464 465 B->ops->lufactorsymbolic = MatLUFactorSymbolic_LUSOL; 466 B->ops->destroy = MatDestroy_LUSOL; 467 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatFactorGetSolverPackage_C","MatFactorGetSolverPackage_seqaij_lusol",MatFactorGetSolverPackage_seqaij_lusol);CHKERRQ(ierr); 468 B->factortype = MAT_FACTOR_LU; 469 PetscFunctionReturn(0); 470 } 471 472 /*MC 473 MATSOLVERLUSOL - "lusol" - Provides direct solvers (LU) for sequential matrices 474 via the external package LUSOL. 475 476 If LUSOL is installed (see the manual for 477 instructions on how to declare the existence of external packages), 478 479 Works with MATSEQAIJ matrices 480 481 Level: beginner 482 483 .seealso: PCLU, PCFactorSetMatSolverPackage(), MatSolverPackage 484 485 M*/ 486