Actual source code: mkl_cpardiso.c

      2: #include <petscsys.h>
      3: #include <../src/mat/impls/aij/mpi/mpiaij.h>
      4: #include <../src/mat/impls/sbaij/mpi/mpisbaij.h>

      6: #if defined(PETSC_HAVE_MKL_INTEL_ILP64)
      7: #define MKL_ILP64
      8: #endif
      9: #include <mkl.h>
     10: #include <mkl_cluster_sparse_solver.h>

     12: /*
     13:  *  Possible mkl_cpardiso phases that controls the execution of the solver.
     14:  *  For more information check mkl_cpardiso manual.
     15:  */
     16: #define JOB_ANALYSIS 11
     17: #define JOB_ANALYSIS_NUMERICAL_FACTORIZATION 12
     18: #define JOB_ANALYSIS_NUMERICAL_FACTORIZATION_SOLVE_ITERATIVE_REFINEMENT 13
     19: #define JOB_NUMERICAL_FACTORIZATION 22
     20: #define JOB_NUMERICAL_FACTORIZATION_SOLVE_ITERATIVE_REFINEMENT 23
     21: #define JOB_SOLVE_ITERATIVE_REFINEMENT 33
     22: #define JOB_SOLVE_FORWARD_SUBSTITUTION 331
     23: #define JOB_SOLVE_DIAGONAL_SUBSTITUTION 332
     24: #define JOB_SOLVE_BACKWARD_SUBSTITUTION 333
     25: #define JOB_RELEASE_OF_LU_MEMORY 0
     26: #define JOB_RELEASE_OF_ALL_MEMORY -1

     28: #define IPARM_SIZE 64
     29: #define INT_TYPE MKL_INT

     31: static const char *Err_MSG_CPardiso(int errNo) {
     32:   switch (errNo) {
     33:     case -1:
     34:       return "input inconsistent"; break;
     35:     case -2:
     36:       return "not enough memory"; break;
     37:     case -3:
     38:       return "reordering problem"; break;
     39:     case -4:
     40:       return "zero pivot, numerical factorization or iterative refinement problem"; break;
     41:     case -5:
     42:       return "unclassified (internal) error"; break;
     43:     case -6:
     44:       return "preordering failed (matrix types 11, 13 only)"; break;
     45:     case -7:
     46:       return "diagonal matrix problem"; break;
     47:     case -8:
     48:       return "32-bit integer overflow problem"; break;
     49:     case -9:
     50:       return "not enough memory for OOC"; break;
     51:     case -10:
     52:       return "problems with opening OOC temporary files"; break;
     53:     case -11:
     54:       return "read/write problems with the OOC data file"; break;
     55:     default :
     56:       return "unknown error";
     57:   }
     58: }

     60: /*
     61:  *  Internal data structure.
     62:  *  For more information check mkl_cpardiso manual.
     63:  */

     65: typedef struct {

     67:   /* Configuration vector */
     68:   INT_TYPE     iparm[IPARM_SIZE];

     70:   /*
     71:    * Internal mkl_cpardiso memory location.
     72:    * After the first call to mkl_cpardiso do not modify pt, as that could cause a serious memory leak.
     73:    */
     74:   void         *pt[IPARM_SIZE];

     76:   MPI_Fint     comm_mkl_cpardiso;

     78:   /* Basic mkl_cpardiso info*/
     79:   INT_TYPE     phase, maxfct, mnum, mtype, n, nrhs, msglvl, err;

     81:   /* Matrix structure */
     82:   PetscScalar  *a;

     84:   INT_TYPE     *ia, *ja;

     86:   /* Number of non-zero elements */
     87:   INT_TYPE     nz;

     89:   /* Row permutaton vector*/
     90:   INT_TYPE     *perm;

     92:   /* Define is matrix preserve sparce structure. */
     93:   MatStructure matstruc;

     95:   PetscErrorCode (*ConvertToTriples)(Mat, MatReuse, PetscInt*, PetscInt**, PetscInt**, PetscScalar**);

     97:   /* True if mkl_cpardiso function have been used. */
     98:   PetscBool CleanUp;
     99: } Mat_MKL_CPARDISO;

    101: /*
    102:  * Copy the elements of matrix A.
    103:  * Input:
    104:  *   - Mat A: MATSEQAIJ matrix
    105:  *   - int shift: matrix index.
    106:  *     - 0 for c representation
    107:  *     - 1 for fortran representation
    108:  *   - MatReuse reuse:
    109:  *     - MAT_INITIAL_MATRIX: Create a new aij representation
    110:  *     - MAT_REUSE_MATRIX: Reuse all aij representation and just change values
    111:  * Output:
    112:  *   - int *nnz: Number of nonzero-elements.
    113:  *   - int **r pointer to i index
    114:  *   - int **c pointer to j elements
    115:  *   - MATRIXTYPE **v: Non-zero elements
    116:  */
    117: PetscErrorCode MatCopy_seqaij_seqaij_MKL_CPARDISO(Mat A, MatReuse reuse, PetscInt *nnz, PetscInt **r, PetscInt **c, PetscScalar **v)
    118: {
    119:   Mat_SeqAIJ *aa=(Mat_SeqAIJ*)A->data;

    121:   *v=aa->a;
    122:   if (reuse == MAT_INITIAL_MATRIX) {
    123:     *r   = (INT_TYPE*)aa->i;
    124:     *c   = (INT_TYPE*)aa->j;
    125:     *nnz = aa->nz;
    126:   }
    127:   return 0;
    128: }

    130: PetscErrorCode MatConvertToTriples_mpiaij_mpiaij_MKL_CPARDISO(Mat A, MatReuse reuse, PetscInt *nnz, PetscInt **r, PetscInt **c, PetscScalar **v)
    131: {
    132:   const PetscInt    *ai, *aj, *bi, *bj,*garray,m=A->rmap->n,*ajj,*bjj;
    133:   PetscInt          rstart,nz,i,j,countA,countB;
    134:   PetscInt          *row,*col;
    135:   const PetscScalar *av, *bv;
    136:   PetscScalar       *val;
    137:   Mat_MPIAIJ        *mat = (Mat_MPIAIJ*)A->data;
    138:   Mat_SeqAIJ        *aa  = (Mat_SeqAIJ*)(mat->A)->data;
    139:   Mat_SeqAIJ        *bb  = (Mat_SeqAIJ*)(mat->B)->data;
    140:   PetscInt          colA_start,jB,jcol;

    142:   ai=aa->i; aj=aa->j; bi=bb->i; bj=bb->j; rstart=A->rmap->rstart;
    143:   av=aa->a; bv=bb->a;

    145:   garray = mat->garray;

    147:   if (reuse == MAT_INITIAL_MATRIX) {
    148:     nz   = aa->nz + bb->nz;
    149:     *nnz = nz;
    150:     PetscMalloc3(m+1,&row,nz,&col,nz,&val);
    151:     *r = row; *c = col; *v = val;
    152:   } else {
    153:     row = *r; col = *c; val = *v;
    154:   }

    156:   nz = 0;
    157:   for (i=0; i<m; i++) {
    158:     row[i] = nz;
    159:     countA     = ai[i+1] - ai[i];
    160:     countB     = bi[i+1] - bi[i];
    161:     ajj        = aj + ai[i]; /* ptr to the beginning of this row */
    162:     bjj        = bj + bi[i];

    164:     /* B part, smaller col index */
    165:     colA_start = rstart + ajj[0]; /* the smallest global col index of A */
    166:     jB         = 0;
    167:     for (j=0; j<countB; j++) {
    168:       jcol = garray[bjj[j]];
    169:       if (jcol > colA_start) break;
    170:       col[nz]   = jcol;
    171:       val[nz++] = *bv++;
    172:     }
    173:     jB = j;

    175:     /* A part */
    176:     for (j=0; j<countA; j++) {
    177:       col[nz]   = rstart + ajj[j];
    178:       val[nz++] = *av++;
    179:     }

    181:     /* B part, larger col index */
    182:     for (j=jB; j<countB; j++) {
    183:       col[nz]   = garray[bjj[j]];
    184:       val[nz++] = *bv++;
    185:     }
    186:   }
    187:   row[m] = nz;

    189:   return 0;
    190: }

    192: PetscErrorCode MatConvertToTriples_mpibaij_mpibaij_MKL_CPARDISO(Mat A, MatReuse reuse, PetscInt *nnz, PetscInt **r, PetscInt **c, PetscScalar **v)
    193: {
    194:   const PetscInt    *ai, *aj, *bi, *bj,*garray,bs=A->rmap->bs,bs2=bs*bs,m=A->rmap->n/bs,*ajj,*bjj;
    195:   PetscInt          rstart,nz,i,j,countA,countB;
    196:   PetscInt          *row,*col;
    197:   const PetscScalar *av, *bv;
    198:   PetscScalar       *val;
    199:   Mat_MPIBAIJ       *mat = (Mat_MPIBAIJ*)A->data;
    200:   Mat_SeqBAIJ       *aa  = (Mat_SeqBAIJ*)(mat->A)->data;
    201:   Mat_SeqBAIJ       *bb  = (Mat_SeqBAIJ*)(mat->B)->data;
    202:   PetscInt          colA_start,jB,jcol;

    204:   ai=aa->i; aj=aa->j; bi=bb->i; bj=bb->j; rstart=A->rmap->rstart/bs;
    205:   av=aa->a; bv=bb->a;

    207:   garray = mat->garray;

    209:   if (reuse == MAT_INITIAL_MATRIX) {
    210:     nz   = aa->nz + bb->nz;
    211:     *nnz = nz;
    212:     PetscMalloc3(m+1,&row,nz,&col,nz*bs2,&val);
    213:     *r = row; *c = col; *v = val;
    214:   } else {
    215:     row = *r; col = *c; val = *v;
    216:   }

    218:   nz = 0;
    219:   for (i=0; i<m; i++) {
    220:     row[i]     = nz+1;
    221:     countA     = ai[i+1] - ai[i];
    222:     countB     = bi[i+1] - bi[i];
    223:     ajj        = aj + ai[i]; /* ptr to the beginning of this row */
    224:     bjj        = bj + bi[i];

    226:     /* B part, smaller col index */
    227:     colA_start = rstart + (countA > 0 ? ajj[0] : 0); /* the smallest global col index of A */
    228:     jB         = 0;
    229:     for (j=0; j<countB; j++) {
    230:       jcol = garray[bjj[j]];
    231:       if (jcol > colA_start) break;
    232:       col[nz++] = jcol + 1;
    233:     }
    234:     jB = j;
    235:     PetscArraycpy(val,bv,jB*bs2);
    236:     val += jB*bs2;
    237:     bv  += jB*bs2;

    239:     /* A part */
    240:     for (j=0; j<countA; j++) col[nz++] = rstart + ajj[j] + 1;
    241:     PetscArraycpy(val,av,countA*bs2);
    242:     val += countA*bs2;
    243:     av  += countA*bs2;

    245:     /* B part, larger col index */
    246:     for (j=jB; j<countB; j++) col[nz++] = garray[bjj[j]] + 1;
    247:     PetscArraycpy(val,bv,(countB-jB)*bs2);
    248:     val += (countB-jB)*bs2;
    249:     bv  += (countB-jB)*bs2;
    250:   }
    251:   row[m] = nz+1;

    253:   return 0;
    254: }

    256: PetscErrorCode MatConvertToTriples_mpisbaij_mpisbaij_MKL_CPARDISO(Mat A, MatReuse reuse, PetscInt *nnz, PetscInt **r, PetscInt **c, PetscScalar **v)
    257: {
    258:   const PetscInt    *ai, *aj, *bi, *bj,*garray,bs=A->rmap->bs,bs2=bs*bs,m=A->rmap->n/bs,*ajj,*bjj;
    259:   PetscInt          rstart,nz,i,j,countA,countB;
    260:   PetscInt          *row,*col;
    261:   const PetscScalar *av, *bv;
    262:   PetscScalar       *val;
    263:   Mat_MPISBAIJ      *mat = (Mat_MPISBAIJ*)A->data;
    264:   Mat_SeqSBAIJ      *aa  = (Mat_SeqSBAIJ*)(mat->A)->data;
    265:   Mat_SeqBAIJ       *bb  = (Mat_SeqBAIJ*)(mat->B)->data;

    267:   ai=aa->i; aj=aa->j; bi=bb->i; bj=bb->j; rstart=A->rmap->rstart/bs;
    268:   av=aa->a; bv=bb->a;

    270:   garray = mat->garray;

    272:   if (reuse == MAT_INITIAL_MATRIX) {
    273:     nz   = aa->nz + bb->nz;
    274:     *nnz = nz;
    275:     PetscMalloc3(m+1,&row,nz,&col,nz*bs2,&val);
    276:     *r = row; *c = col; *v = val;
    277:   } else {
    278:     row = *r; col = *c; val = *v;
    279:   }

    281:   nz = 0;
    282:   for (i=0; i<m; i++) {
    283:     row[i]     = nz+1;
    284:     countA     = ai[i+1] - ai[i];
    285:     countB     = bi[i+1] - bi[i];
    286:     ajj        = aj + ai[i]; /* ptr to the beginning of this row */
    287:     bjj        = bj + bi[i];

    289:     /* A part */
    290:     for (j=0; j<countA; j++) col[nz++] = rstart + ajj[j] + 1;
    291:     PetscArraycpy(val,av,countA*bs2);
    292:     val += countA*bs2;
    293:     av  += countA*bs2;

    295:     /* B part, larger col index */
    296:     for (j=0; j<countB; j++) col[nz++] = garray[bjj[j]] + 1;
    297:     PetscArraycpy(val,bv,countB*bs2);
    298:     val += countB*bs2;
    299:     bv  += countB*bs2;
    300:   }
    301:   row[m] = nz+1;

    303:   return 0;
    304: }

    306: /*
    307:  * Free memory for Mat_MKL_CPARDISO structure and pointers to objects.
    308:  */
    309: PetscErrorCode MatDestroy_MKL_CPARDISO(Mat A)
    310: {
    311:   Mat_MKL_CPARDISO *mat_mkl_cpardiso=(Mat_MKL_CPARDISO*)A->data;
    312:   MPI_Comm         comm;

    314:   /* Terminate instance, deallocate memories */
    315:   if (mat_mkl_cpardiso->CleanUp) {
    316:     mat_mkl_cpardiso->phase = JOB_RELEASE_OF_ALL_MEMORY;

    318:     cluster_sparse_solver (
    319:       mat_mkl_cpardiso->pt,
    320:       &mat_mkl_cpardiso->maxfct,
    321:       &mat_mkl_cpardiso->mnum,
    322:       &mat_mkl_cpardiso->mtype,
    323:       &mat_mkl_cpardiso->phase,
    324:       &mat_mkl_cpardiso->n,
    325:       NULL,
    326:       NULL,
    327:       NULL,
    328:       mat_mkl_cpardiso->perm,
    329:       &mat_mkl_cpardiso->nrhs,
    330:       mat_mkl_cpardiso->iparm,
    331:       &mat_mkl_cpardiso->msglvl,
    332:       NULL,
    333:       NULL,
    334:       &mat_mkl_cpardiso->comm_mkl_cpardiso,
    335:       (PetscInt*)&mat_mkl_cpardiso->err);
    336:   }

    338:   if (mat_mkl_cpardiso->ConvertToTriples != MatCopy_seqaij_seqaij_MKL_CPARDISO) {
    339:     PetscFree3(mat_mkl_cpardiso->ia,mat_mkl_cpardiso->ja,mat_mkl_cpardiso->a);
    340:   }
    341:   comm = MPI_Comm_f2c(mat_mkl_cpardiso->comm_mkl_cpardiso);
    342:   MPI_Comm_free(&comm);
    343:   PetscFree(A->data);

    345:   /* clear composed functions */
    346:   PetscObjectComposeFunction((PetscObject)A,"MatFactorGetSolverType_C",NULL);
    347:   PetscObjectComposeFunction((PetscObject)A,"MatMkl_CPardisoSetCntl_C",NULL);
    348:   return 0;
    349: }

    351: /*
    352:  * Computes Ax = b
    353:  */
    354: PetscErrorCode MatSolve_MKL_CPARDISO(Mat A,Vec b,Vec x)
    355: {
    356:   Mat_MKL_CPARDISO   *mat_mkl_cpardiso=(Mat_MKL_CPARDISO*)(A)->data;
    357:   PetscScalar       *xarray;
    358:   const PetscScalar *barray;

    360:   mat_mkl_cpardiso->nrhs = 1;
    361:   VecGetArray(x,&xarray);
    362:   VecGetArrayRead(b,&barray);

    364:   /* solve phase */
    365:   /*-------------*/
    366:   mat_mkl_cpardiso->phase = JOB_SOLVE_ITERATIVE_REFINEMENT;
    367:   cluster_sparse_solver (
    368:     mat_mkl_cpardiso->pt,
    369:     &mat_mkl_cpardiso->maxfct,
    370:     &mat_mkl_cpardiso->mnum,
    371:     &mat_mkl_cpardiso->mtype,
    372:     &mat_mkl_cpardiso->phase,
    373:     &mat_mkl_cpardiso->n,
    374:     mat_mkl_cpardiso->a,
    375:     mat_mkl_cpardiso->ia,
    376:     mat_mkl_cpardiso->ja,
    377:     mat_mkl_cpardiso->perm,
    378:     &mat_mkl_cpardiso->nrhs,
    379:     mat_mkl_cpardiso->iparm,
    380:     &mat_mkl_cpardiso->msglvl,
    381:     (void*)barray,
    382:     (void*)xarray,
    383:     &mat_mkl_cpardiso->comm_mkl_cpardiso,
    384:     (PetscInt*)&mat_mkl_cpardiso->err);

    388:   VecRestoreArray(x,&xarray);
    389:   VecRestoreArrayRead(b,&barray);
    390:   mat_mkl_cpardiso->CleanUp = PETSC_TRUE;
    391:   return 0;
    392: }

    394: PetscErrorCode MatSolveTranspose_MKL_CPARDISO(Mat A,Vec b,Vec x)
    395: {
    396:   Mat_MKL_CPARDISO *mat_mkl_cpardiso=(Mat_MKL_CPARDISO*)A->data;

    398: #if defined(PETSC_USE_COMPLEX)
    399:   mat_mkl_cpardiso->iparm[12 - 1] = 1;
    400: #else
    401:   mat_mkl_cpardiso->iparm[12 - 1] = 2;
    402: #endif
    403:   MatSolve_MKL_CPARDISO(A,b,x);
    404:   mat_mkl_cpardiso->iparm[12 - 1] = 0;
    405:   return 0;
    406: }

    408: PetscErrorCode MatMatSolve_MKL_CPARDISO(Mat A,Mat B,Mat X)
    409: {
    410:   Mat_MKL_CPARDISO  *mat_mkl_cpardiso=(Mat_MKL_CPARDISO*)(A)->data;
    411:   PetscScalar       *xarray;
    412:   const PetscScalar *barray;

    414:   MatGetSize(B,NULL,(PetscInt*)&mat_mkl_cpardiso->nrhs);

    416:   if (mat_mkl_cpardiso->nrhs > 0) {
    417:     MatDenseGetArrayRead(B,&barray);
    418:     MatDenseGetArray(X,&xarray);

    422:     /* solve phase */
    423:     /*-------------*/
    424:     mat_mkl_cpardiso->phase = JOB_SOLVE_ITERATIVE_REFINEMENT;
    425:     cluster_sparse_solver (
    426:       mat_mkl_cpardiso->pt,
    427:       &mat_mkl_cpardiso->maxfct,
    428:       &mat_mkl_cpardiso->mnum,
    429:       &mat_mkl_cpardiso->mtype,
    430:       &mat_mkl_cpardiso->phase,
    431:       &mat_mkl_cpardiso->n,
    432:       mat_mkl_cpardiso->a,
    433:       mat_mkl_cpardiso->ia,
    434:       mat_mkl_cpardiso->ja,
    435:       mat_mkl_cpardiso->perm,
    436:       &mat_mkl_cpardiso->nrhs,
    437:       mat_mkl_cpardiso->iparm,
    438:       &mat_mkl_cpardiso->msglvl,
    439:       (void*)barray,
    440:       (void*)xarray,
    441:       &mat_mkl_cpardiso->comm_mkl_cpardiso,
    442:       (PetscInt*)&mat_mkl_cpardiso->err);
    444:     MatDenseRestoreArrayRead(B,&barray);
    445:     MatDenseRestoreArray(X,&xarray);

    447:   }
    448:   mat_mkl_cpardiso->CleanUp = PETSC_TRUE;
    449:   return 0;
    450: }

    452: /*
    453:  * LU Decomposition
    454:  */
    455: PetscErrorCode MatFactorNumeric_MKL_CPARDISO(Mat F,Mat A,const MatFactorInfo *info)
    456: {
    457:   Mat_MKL_CPARDISO *mat_mkl_cpardiso=(Mat_MKL_CPARDISO*)(F)->data;

    459:   mat_mkl_cpardiso->matstruc = SAME_NONZERO_PATTERN;
    460:   (*mat_mkl_cpardiso->ConvertToTriples)(A, MAT_REUSE_MATRIX,&mat_mkl_cpardiso->nz,&mat_mkl_cpardiso->ia,&mat_mkl_cpardiso->ja,&mat_mkl_cpardiso->a);

    462:   mat_mkl_cpardiso->phase = JOB_NUMERICAL_FACTORIZATION;
    463:   cluster_sparse_solver (
    464:     mat_mkl_cpardiso->pt,
    465:     &mat_mkl_cpardiso->maxfct,
    466:     &mat_mkl_cpardiso->mnum,
    467:     &mat_mkl_cpardiso->mtype,
    468:     &mat_mkl_cpardiso->phase,
    469:     &mat_mkl_cpardiso->n,
    470:     mat_mkl_cpardiso->a,
    471:     mat_mkl_cpardiso->ia,
    472:     mat_mkl_cpardiso->ja,
    473:     mat_mkl_cpardiso->perm,
    474:     &mat_mkl_cpardiso->nrhs,
    475:     mat_mkl_cpardiso->iparm,
    476:     &mat_mkl_cpardiso->msglvl,
    477:     NULL,
    478:     NULL,
    479:     &mat_mkl_cpardiso->comm_mkl_cpardiso,
    480:     &mat_mkl_cpardiso->err);

    483:   mat_mkl_cpardiso->matstruc = SAME_NONZERO_PATTERN;
    484:   mat_mkl_cpardiso->CleanUp  = PETSC_TRUE;
    485:   return 0;
    486: }

    488: /* Sets mkl_cpardiso options from the options database */
    489: PetscErrorCode PetscSetMKL_CPARDISOFromOptions(Mat F, Mat A)
    490: {
    491:   Mat_MKL_CPARDISO    *mat_mkl_cpardiso = (Mat_MKL_CPARDISO*)F->data;
    492:   PetscErrorCode      ierr;
    493:   PetscInt            icntl,threads;
    494:   PetscBool           flg;

    496:   PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"MKL_CPARDISO Options","Mat");
    497:   PetscOptionsInt("-mat_mkl_cpardiso_65","Suggested number of threads to use within MKL_CPARDISO","None",threads,&threads,&flg);
    498:   if (flg) mkl_set_num_threads((int)threads);

    500:   PetscOptionsInt("-mat_mkl_cpardiso_66","Maximum number of factors with identical sparsity structure that must be kept in memory at the same time","None",mat_mkl_cpardiso->maxfct,&icntl,&flg);
    501:   if (flg) mat_mkl_cpardiso->maxfct = icntl;

    503:   PetscOptionsInt("-mat_mkl_cpardiso_67","Indicates the actual matrix for the solution phase","None",mat_mkl_cpardiso->mnum,&icntl,&flg);
    504:   if (flg) mat_mkl_cpardiso->mnum = icntl;

    506:   PetscOptionsInt("-mat_mkl_cpardiso_68","Message level information","None",mat_mkl_cpardiso->msglvl,&icntl,&flg);
    507:   if (flg) mat_mkl_cpardiso->msglvl = icntl;

    509:   PetscOptionsInt("-mat_mkl_cpardiso_69","Defines the matrix type","None",mat_mkl_cpardiso->mtype,&icntl,&flg);
    510:   if (flg) mat_mkl_cpardiso->mtype = icntl;
    511:   PetscOptionsInt("-mat_mkl_cpardiso_1","Use default values","None",mat_mkl_cpardiso->iparm[0],&icntl,&flg);

    513:   if (flg && icntl != 0) {
    514:     PetscOptionsInt("-mat_mkl_cpardiso_2","Fill-in reducing ordering for the input matrix","None",mat_mkl_cpardiso->iparm[1],&icntl,&flg);
    515:     if (flg) mat_mkl_cpardiso->iparm[1] = icntl;

    517:     PetscOptionsInt("-mat_mkl_cpardiso_4","Preconditioned CGS/CG","None",mat_mkl_cpardiso->iparm[3],&icntl,&flg);
    518:     if (flg) mat_mkl_cpardiso->iparm[3] = icntl;

    520:     PetscOptionsInt("-mat_mkl_cpardiso_5","User permutation","None",mat_mkl_cpardiso->iparm[4],&icntl,&flg);
    521:     if (flg) mat_mkl_cpardiso->iparm[4] = icntl;

    523:     PetscOptionsInt("-mat_mkl_cpardiso_6","Write solution on x","None",mat_mkl_cpardiso->iparm[5],&icntl,&flg);
    524:     if (flg) mat_mkl_cpardiso->iparm[5] = icntl;

    526:     PetscOptionsInt("-mat_mkl_cpardiso_8","Iterative refinement step","None",mat_mkl_cpardiso->iparm[7],&icntl,&flg);
    527:     if (flg) mat_mkl_cpardiso->iparm[7] = icntl;

    529:     PetscOptionsInt("-mat_mkl_cpardiso_10","Pivoting perturbation","None",mat_mkl_cpardiso->iparm[9],&icntl,&flg);
    530:     if (flg) mat_mkl_cpardiso->iparm[9] = icntl;

    532:     PetscOptionsInt("-mat_mkl_cpardiso_11","Scaling vectors","None",mat_mkl_cpardiso->iparm[10],&icntl,&flg);
    533:     if (flg) mat_mkl_cpardiso->iparm[10] = icntl;

    535:     PetscOptionsInt("-mat_mkl_cpardiso_12","Solve with transposed or conjugate transposed matrix A","None",mat_mkl_cpardiso->iparm[11],&icntl,&flg);
    536:     if (flg) mat_mkl_cpardiso->iparm[11] = icntl;

    538:     PetscOptionsInt("-mat_mkl_cpardiso_13","Improved accuracy using (non-) symmetric weighted matching","None",mat_mkl_cpardiso->iparm[12],&icntl,
    539:       &flg);
    540:     if (flg) mat_mkl_cpardiso->iparm[12] = icntl;

    542:     PetscOptionsInt("-mat_mkl_cpardiso_18","Numbers of non-zero elements","None",mat_mkl_cpardiso->iparm[17],&icntl,
    543:       &flg);
    544:     if (flg) mat_mkl_cpardiso->iparm[17] = icntl;

    546:     PetscOptionsInt("-mat_mkl_cpardiso_19","Report number of floating point operations","None",mat_mkl_cpardiso->iparm[18],&icntl,&flg);
    547:     if (flg) mat_mkl_cpardiso->iparm[18] = icntl;

    549:     PetscOptionsInt("-mat_mkl_cpardiso_21","Pivoting for symmetric indefinite matrices","None",mat_mkl_cpardiso->iparm[20],&icntl,&flg);
    550:     if (flg) mat_mkl_cpardiso->iparm[20] = icntl;

    552:     PetscOptionsInt("-mat_mkl_cpardiso_24","Parallel factorization control","None",mat_mkl_cpardiso->iparm[23],&icntl,&flg);
    553:     if (flg) mat_mkl_cpardiso->iparm[23] = icntl;

    555:     PetscOptionsInt("-mat_mkl_cpardiso_25","Parallel forward/backward solve control","None",mat_mkl_cpardiso->iparm[24],&icntl,&flg);
    556:     if (flg) mat_mkl_cpardiso->iparm[24] = icntl;

    558:     PetscOptionsInt("-mat_mkl_cpardiso_27","Matrix checker","None",mat_mkl_cpardiso->iparm[26],&icntl,&flg);
    559:     if (flg) mat_mkl_cpardiso->iparm[26] = icntl;

    561:     PetscOptionsInt("-mat_mkl_cpardiso_31","Partial solve and computing selected components of the solution vectors","None",mat_mkl_cpardiso->iparm[30],&icntl,&flg);
    562:     if (flg) mat_mkl_cpardiso->iparm[30] = icntl;

    564:     PetscOptionsInt("-mat_mkl_cpardiso_34","Optimal number of threads for conditional numerical reproducibility (CNR) mode","None",mat_mkl_cpardiso->iparm[33],&icntl,&flg);
    565:     if (flg) mat_mkl_cpardiso->iparm[33] = icntl;

    567:     PetscOptionsInt("-mat_mkl_cpardiso_60","Intel MKL_CPARDISO mode","None",mat_mkl_cpardiso->iparm[59],&icntl,&flg);
    568:     if (flg) mat_mkl_cpardiso->iparm[59] = icntl;
    569:   }

    571:   PetscOptionsEnd();
    572:   return 0;
    573: }

    575: PetscErrorCode PetscInitialize_MKL_CPARDISO(Mat A, Mat_MKL_CPARDISO *mat_mkl_cpardiso)
    576: {
    577:   PetscInt        bs;
    578:   PetscBool       match;
    579:   PetscMPIInt     size;
    580:   MPI_Comm        comm;

    583:   MPI_Comm_dup(PetscObjectComm((PetscObject)A),&comm);
    584:   MPI_Comm_size(comm, &size);
    585:   mat_mkl_cpardiso->comm_mkl_cpardiso = MPI_Comm_c2f(comm);

    587:   mat_mkl_cpardiso->CleanUp = PETSC_FALSE;
    588:   mat_mkl_cpardiso->maxfct = 1;
    589:   mat_mkl_cpardiso->mnum = 1;
    590:   mat_mkl_cpardiso->n = A->rmap->N;
    591:   if (mat_mkl_cpardiso->iparm[36]) mat_mkl_cpardiso->n /= mat_mkl_cpardiso->iparm[36];
    592:   mat_mkl_cpardiso->msglvl = 0;
    593:   mat_mkl_cpardiso->nrhs = 1;
    594:   mat_mkl_cpardiso->err = 0;
    595:   mat_mkl_cpardiso->phase = -1;
    596: #if defined(PETSC_USE_COMPLEX)
    597:   mat_mkl_cpardiso->mtype = 13;
    598: #else
    599:   mat_mkl_cpardiso->mtype = 11;
    600: #endif

    602: #if defined(PETSC_USE_REAL_SINGLE)
    603:   mat_mkl_cpardiso->iparm[27] = 1;
    604: #else
    605:   mat_mkl_cpardiso->iparm[27] = 0;
    606: #endif

    608:   mat_mkl_cpardiso->iparm[ 0] =  1; /* Solver default parameters overriden with provided by iparm */
    609:   mat_mkl_cpardiso->iparm[ 1] =  2; /* Use METIS for fill-in reordering */
    610:   mat_mkl_cpardiso->iparm[ 5] =  0; /* Write solution into x */
    611:   mat_mkl_cpardiso->iparm[ 7] =  2; /* Max number of iterative refinement steps */
    612:   mat_mkl_cpardiso->iparm[ 9] = 13; /* Perturb the pivot elements with 1E-13 */
    613:   mat_mkl_cpardiso->iparm[10] =  1; /* Use nonsymmetric permutation and scaling MPS */
    614:   mat_mkl_cpardiso->iparm[12] =  1; /* Switch on Maximum Weighted Matching algorithm (default for non-symmetric) */
    615:   mat_mkl_cpardiso->iparm[17] = -1; /* Output: Number of nonzeros in the factor LU */
    616:   mat_mkl_cpardiso->iparm[18] = -1; /* Output: Mflops for LU factorization */
    617:   mat_mkl_cpardiso->iparm[26] =  1; /* Check input data for correctness */

    619:   mat_mkl_cpardiso->iparm[39] = 0;
    620:   if (size > 1) {
    621:     mat_mkl_cpardiso->iparm[39] = 2;
    622:     mat_mkl_cpardiso->iparm[40] = A->rmap->rstart;
    623:     mat_mkl_cpardiso->iparm[41] = A->rmap->rend-1;
    624:   }
    625:   PetscObjectTypeCompareAny((PetscObject)A,&match,MATMPIBAIJ,MATMPISBAIJ,"");
    626:   if (match) {
    627:     MatGetBlockSize(A,&bs);
    628:     mat_mkl_cpardiso->iparm[36] = bs;
    629:     mat_mkl_cpardiso->iparm[40] /= bs;
    630:     mat_mkl_cpardiso->iparm[41] /= bs;
    631:     mat_mkl_cpardiso->iparm[40]++;
    632:     mat_mkl_cpardiso->iparm[41]++;
    633:     mat_mkl_cpardiso->iparm[34] = 0;  /* Fortran style */
    634:   } else {
    635:     mat_mkl_cpardiso->iparm[34] = 1;  /* C style */
    636:   }

    638:   mat_mkl_cpardiso->perm = 0;
    639:   return 0;
    640: }

    642: /*
    643:  * Symbolic decomposition. Mkl_Pardiso analysis phase.
    644:  */
    645: PetscErrorCode MatLUFactorSymbolic_AIJMKL_CPARDISO(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
    646: {
    647:   Mat_MKL_CPARDISO *mat_mkl_cpardiso = (Mat_MKL_CPARDISO*)F->data;

    649:   mat_mkl_cpardiso->matstruc = DIFFERENT_NONZERO_PATTERN;

    651:   /* Set MKL_CPARDISO options from the options database */
    652:   PetscSetMKL_CPARDISOFromOptions(F,A);
    653:   (*mat_mkl_cpardiso->ConvertToTriples)(A,MAT_INITIAL_MATRIX,&mat_mkl_cpardiso->nz,&mat_mkl_cpardiso->ia,&mat_mkl_cpardiso->ja,&mat_mkl_cpardiso->a);

    655:   mat_mkl_cpardiso->n = A->rmap->N;
    656:   if (mat_mkl_cpardiso->iparm[36]) mat_mkl_cpardiso->n /= mat_mkl_cpardiso->iparm[36];

    658:   /* analysis phase */
    659:   /*----------------*/
    660:   mat_mkl_cpardiso->phase = JOB_ANALYSIS;

    662:   cluster_sparse_solver (
    663:     mat_mkl_cpardiso->pt,
    664:     &mat_mkl_cpardiso->maxfct,
    665:     &mat_mkl_cpardiso->mnum,
    666:     &mat_mkl_cpardiso->mtype,
    667:     &mat_mkl_cpardiso->phase,
    668:     &mat_mkl_cpardiso->n,
    669:     mat_mkl_cpardiso->a,
    670:     mat_mkl_cpardiso->ia,
    671:     mat_mkl_cpardiso->ja,
    672:     mat_mkl_cpardiso->perm,
    673:     &mat_mkl_cpardiso->nrhs,
    674:     mat_mkl_cpardiso->iparm,
    675:     &mat_mkl_cpardiso->msglvl,
    676:     NULL,
    677:     NULL,
    678:     &mat_mkl_cpardiso->comm_mkl_cpardiso,
    679:     (PetscInt*)&mat_mkl_cpardiso->err);

    683:   mat_mkl_cpardiso->CleanUp = PETSC_TRUE;
    684:   F->ops->lufactornumeric = MatFactorNumeric_MKL_CPARDISO;
    685:   F->ops->solve           = MatSolve_MKL_CPARDISO;
    686:   F->ops->solvetranspose  = MatSolveTranspose_MKL_CPARDISO;
    687:   F->ops->matsolve        = MatMatSolve_MKL_CPARDISO;
    688:   return 0;
    689: }

    691: PetscErrorCode MatCholeskyFactorSymbolic_AIJMKL_CPARDISO(Mat F,Mat A,IS perm,const MatFactorInfo *info)
    692: {
    693:   Mat_MKL_CPARDISO *mat_mkl_cpardiso = (Mat_MKL_CPARDISO*)F->data;

    695:   mat_mkl_cpardiso->matstruc = DIFFERENT_NONZERO_PATTERN;

    697:   /* Set MKL_CPARDISO options from the options database */
    698:   PetscSetMKL_CPARDISOFromOptions(F,A);
    699:   (*mat_mkl_cpardiso->ConvertToTriples)(A,MAT_INITIAL_MATRIX,&mat_mkl_cpardiso->nz,&mat_mkl_cpardiso->ia,&mat_mkl_cpardiso->ja,&mat_mkl_cpardiso->a);

    701:   mat_mkl_cpardiso->n = A->rmap->N;
    702:   if (mat_mkl_cpardiso->iparm[36]) mat_mkl_cpardiso->n /= mat_mkl_cpardiso->iparm[36];
    703: #if defined(PETSC_USE_COMPLEX)
    704:   SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for PARDISO CHOLESKY with complex scalars! Use MAT_FACTOR_LU instead",((PetscObject)A)->type_name);
    705: #endif
    706:   if (A->spd_set && A->spd) mat_mkl_cpardiso->mtype = 2;
    707:   else                      mat_mkl_cpardiso->mtype = -2;

    709:   /* analysis phase */
    710:   /*----------------*/
    711:   mat_mkl_cpardiso->phase = JOB_ANALYSIS;

    713:   cluster_sparse_solver (
    714:     mat_mkl_cpardiso->pt,
    715:     &mat_mkl_cpardiso->maxfct,
    716:     &mat_mkl_cpardiso->mnum,
    717:     &mat_mkl_cpardiso->mtype,
    718:     &mat_mkl_cpardiso->phase,
    719:     &mat_mkl_cpardiso->n,
    720:     mat_mkl_cpardiso->a,
    721:     mat_mkl_cpardiso->ia,
    722:     mat_mkl_cpardiso->ja,
    723:     mat_mkl_cpardiso->perm,
    724:     &mat_mkl_cpardiso->nrhs,
    725:     mat_mkl_cpardiso->iparm,
    726:     &mat_mkl_cpardiso->msglvl,
    727:     NULL,
    728:     NULL,
    729:     &mat_mkl_cpardiso->comm_mkl_cpardiso,
    730:     (PetscInt*)&mat_mkl_cpardiso->err);

    734:   mat_mkl_cpardiso->CleanUp = PETSC_TRUE;
    735:   F->ops->choleskyfactornumeric = MatFactorNumeric_MKL_CPARDISO;
    736:   F->ops->solve                 = MatSolve_MKL_CPARDISO;
    737:   F->ops->solvetranspose        = MatSolveTranspose_MKL_CPARDISO;
    738:   F->ops->matsolve              = MatMatSolve_MKL_CPARDISO;
    739:   return 0;
    740: }

    742: PetscErrorCode MatView_MKL_CPARDISO(Mat A, PetscViewer viewer)
    743: {
    744:   PetscBool         iascii;
    745:   PetscViewerFormat format;
    746:   Mat_MKL_CPARDISO  *mat_mkl_cpardiso=(Mat_MKL_CPARDISO*)A->data;
    747:   PetscInt          i;

    749:   /* check if matrix is mkl_cpardiso type */
    750:   if (A->ops->solve != MatSolve_MKL_CPARDISO) return 0;

    752:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    753:   if (iascii) {
    754:     PetscViewerGetFormat(viewer,&format);
    755:     if (format == PETSC_VIEWER_ASCII_INFO) {
    756:       PetscViewerASCIIPrintf(viewer,"MKL_CPARDISO run parameters:\n");
    757:       PetscViewerASCIIPrintf(viewer,"MKL_CPARDISO phase:             %d \n",mat_mkl_cpardiso->phase);
    758:       for (i = 1; i <= 64; i++) {
    759:         PetscViewerASCIIPrintf(viewer,"MKL_CPARDISO iparm[%d]:     %d \n",i, mat_mkl_cpardiso->iparm[i - 1]);
    760:       }
    761:       PetscViewerASCIIPrintf(viewer,"MKL_CPARDISO maxfct:     %d \n", mat_mkl_cpardiso->maxfct);
    762:       PetscViewerASCIIPrintf(viewer,"MKL_CPARDISO mnum:     %d \n", mat_mkl_cpardiso->mnum);
    763:       PetscViewerASCIIPrintf(viewer,"MKL_CPARDISO mtype:     %d \n", mat_mkl_cpardiso->mtype);
    764:       PetscViewerASCIIPrintf(viewer,"MKL_CPARDISO n:     %d \n", mat_mkl_cpardiso->n);
    765:       PetscViewerASCIIPrintf(viewer,"MKL_CPARDISO nrhs:     %d \n", mat_mkl_cpardiso->nrhs);
    766:       PetscViewerASCIIPrintf(viewer,"MKL_CPARDISO msglvl:     %d \n", mat_mkl_cpardiso->msglvl);
    767:     }
    768:   }
    769:   return 0;
    770: }

    772: PetscErrorCode MatGetInfo_MKL_CPARDISO(Mat A, MatInfoType flag, MatInfo *info)
    773: {
    774:   Mat_MKL_CPARDISO *mat_mkl_cpardiso=(Mat_MKL_CPARDISO*)A->data;

    776:   info->block_size        = 1.0;
    777:   info->nz_allocated      = mat_mkl_cpardiso->nz + 0.0;
    778:   info->nz_unneeded       = 0.0;
    779:   info->assemblies        = 0.0;
    780:   info->mallocs           = 0.0;
    781:   info->memory            = 0.0;
    782:   info->fill_ratio_given  = 0;
    783:   info->fill_ratio_needed = 0;
    784:   info->factor_mallocs    = 0;
    785:   return 0;
    786: }

    788: PetscErrorCode MatMkl_CPardisoSetCntl_MKL_CPARDISO(Mat F,PetscInt icntl,PetscInt ival)
    789: {
    790:   Mat_MKL_CPARDISO *mat_mkl_cpardiso=(Mat_MKL_CPARDISO*)F->data;

    792:   if (icntl <= 64) {
    793:     mat_mkl_cpardiso->iparm[icntl - 1] = ival;
    794:   } else {
    795:     if (icntl == 65) mkl_set_num_threads((int)ival);
    796:     else if (icntl == 66) mat_mkl_cpardiso->maxfct = ival;
    797:     else if (icntl == 67) mat_mkl_cpardiso->mnum = ival;
    798:     else if (icntl == 68) mat_mkl_cpardiso->msglvl = ival;
    799:     else if (icntl == 69) mat_mkl_cpardiso->mtype = ival;
    800:   }
    801:   return 0;
    802: }

    804: /*@
    805:   MatMkl_CPardisoSetCntl - Set Mkl_Pardiso parameters

    807:    Logically Collective on Mat

    809:    Input Parameters:
    810: +  F - the factored matrix obtained by calling MatGetFactor()
    811: .  icntl - index of Mkl_Pardiso parameter
    812: -  ival - value of Mkl_Pardiso parameter

    814:   Options Database:
    815: .   -mat_mkl_cpardiso_<icntl> <ival> - set the option numbered icntl to ival

    817:    Level: Intermediate

    819:    Notes:
    820:     This routine cannot be used if you are solving the linear system with TS, SNES, or KSP, only if you directly call MatGetFactor() so use the options
    821:           database approach when working with TS, SNES, or KSP.

    823:    References:
    824: .  * - Mkl_Pardiso Users' Guide

    826: .seealso: MatGetFactor()
    827: @*/
    828: PetscErrorCode MatMkl_CPardisoSetCntl(Mat F,PetscInt icntl,PetscInt ival)
    829: {
    830:   PetscTryMethod(F,"MatMkl_CPardisoSetCntl_C",(Mat,PetscInt,PetscInt),(F,icntl,ival));
    831:   return 0;
    832: }

    834: /*MC
    835:   MATSOLVERMKL_CPARDISO -  A matrix type providing direct solvers (LU) for parallel matrices via the external package MKL_CPARDISO.

    837:   Works with MATMPIAIJ matrices

    839:   Use -pc_type lu -pc_factor_mat_solver_type mkl_cpardiso to use this direct solver

    841:   Options Database Keys:
    842: + -mat_mkl_cpardiso_65 - Suggested number of threads to use within MKL_CPARDISO
    843: . -mat_mkl_cpardiso_66 - Maximum number of factors with identical sparsity structure that must be kept in memory at the same time
    844: . -mat_mkl_cpardiso_67 - Indicates the actual matrix for the solution phase
    845: . -mat_mkl_cpardiso_68 - Message level information, use 1 to get detailed information on the solver options
    846: . -mat_mkl_cpardiso_69 - Defines the matrix type. IMPORTANT: When you set this flag, iparm parameters are going to be set to the default ones for the matrix type
    847: . -mat_mkl_cpardiso_1  - Use default values
    848: . -mat_mkl_cpardiso_2  - Fill-in reducing ordering for the input matrix
    849: . -mat_mkl_cpardiso_4  - Preconditioned CGS/CG
    850: . -mat_mkl_cpardiso_5  - User permutation
    851: . -mat_mkl_cpardiso_6  - Write solution on x
    852: . -mat_mkl_cpardiso_8  - Iterative refinement step
    853: . -mat_mkl_cpardiso_10 - Pivoting perturbation
    854: . -mat_mkl_cpardiso_11 - Scaling vectors
    855: . -mat_mkl_cpardiso_12 - Solve with transposed or conjugate transposed matrix A
    856: . -mat_mkl_cpardiso_13 - Improved accuracy using (non-) symmetric weighted matching
    857: . -mat_mkl_cpardiso_18 - Numbers of non-zero elements
    858: . -mat_mkl_cpardiso_19 - Report number of floating point operations
    859: . -mat_mkl_cpardiso_21 - Pivoting for symmetric indefinite matrices
    860: . -mat_mkl_cpardiso_24 - Parallel factorization control
    861: . -mat_mkl_cpardiso_25 - Parallel forward/backward solve control
    862: . -mat_mkl_cpardiso_27 - Matrix checker
    863: . -mat_mkl_cpardiso_31 - Partial solve and computing selected components of the solution vectors
    864: . -mat_mkl_cpardiso_34 - Optimal number of threads for conditional numerical reproducibility (CNR) mode
    865: - -mat_mkl_cpardiso_60 - Intel MKL_CPARDISO mode

    867:   Level: beginner

    869:   Notes:
    870:     Use -mat_mkl_cpardiso_68 1 to display the number of threads the solver is using. MKL does not provide a way to directly access this
    871:     information.

    873:     For more information on the options check the MKL_CPARDISO manual

    875: .seealso: PCFactorSetMatSolverType(), MatSolverType

    877: M*/

    879: static PetscErrorCode MatFactorGetSolverType_mkl_cpardiso(Mat A, MatSolverType *type)
    880: {
    881:   *type = MATSOLVERMKL_CPARDISO;
    882:   return 0;
    883: }

    885: /* MatGetFactor for MPI AIJ matrices */
    886: static PetscErrorCode MatGetFactor_mpiaij_mkl_cpardiso(Mat A,MatFactorType ftype,Mat *F)
    887: {
    888:   Mat              B;
    889:   Mat_MKL_CPARDISO *mat_mkl_cpardiso;
    890:   PetscBool        isSeqAIJ,isMPIBAIJ,isMPISBAIJ;

    892:   /* Create the factorization matrix */

    894:   PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isSeqAIJ);
    895:   PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&isMPIBAIJ);
    896:   PetscObjectTypeCompare((PetscObject)A,MATMPISBAIJ,&isMPISBAIJ);
    897:   MatCreate(PetscObjectComm((PetscObject)A),&B);
    898:   MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);
    899:   PetscStrallocpy("mkl_cpardiso",&((PetscObject)B)->type_name);
    900:   MatSetUp(B);

    902:   PetscNewLog(B,&mat_mkl_cpardiso);

    904:   if (isSeqAIJ)        mat_mkl_cpardiso->ConvertToTriples = MatCopy_seqaij_seqaij_MKL_CPARDISO;
    905:   else if (isMPIBAIJ)  mat_mkl_cpardiso->ConvertToTriples = MatConvertToTriples_mpibaij_mpibaij_MKL_CPARDISO;
    906:   else if (isMPISBAIJ) mat_mkl_cpardiso->ConvertToTriples = MatConvertToTriples_mpisbaij_mpisbaij_MKL_CPARDISO;
    907:   else                 mat_mkl_cpardiso->ConvertToTriples = MatConvertToTriples_mpiaij_mpiaij_MKL_CPARDISO;

    909:   if (ftype == MAT_FACTOR_LU) B->ops->lufactorsymbolic = MatLUFactorSymbolic_AIJMKL_CPARDISO;
    910:   else B->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_AIJMKL_CPARDISO;
    911:   B->ops->destroy = MatDestroy_MKL_CPARDISO;

    913:   B->ops->view    = MatView_MKL_CPARDISO;
    914:   B->ops->getinfo = MatGetInfo_MKL_CPARDISO;

    916:   B->factortype   = ftype;
    917:   B->assembled    = PETSC_TRUE;           /* required by -ksp_view */

    919:   B->data = mat_mkl_cpardiso;

    921:   /* set solvertype */
    922:   PetscFree(B->solvertype);
    923:   PetscStrallocpy(MATSOLVERMKL_CPARDISO,&B->solvertype);

    925:   PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_mkl_cpardiso);
    926:   PetscObjectComposeFunction((PetscObject)B,"MatMkl_CPardisoSetCntl_C",MatMkl_CPardisoSetCntl_MKL_CPARDISO);
    927:   PetscInitialize_MKL_CPARDISO(A, mat_mkl_cpardiso);

    929:   *F = B;
    930:   return 0;
    931: }

    933: PETSC_EXTERN PetscErrorCode MatSolverTypeRegister_MKL_CPardiso(void)
    934: {
    935:   MatSolverTypeRegister(MATSOLVERMKL_CPARDISO,MATMPIAIJ,MAT_FACTOR_LU,MatGetFactor_mpiaij_mkl_cpardiso);
    936:   MatSolverTypeRegister(MATSOLVERMKL_CPARDISO,MATSEQAIJ,MAT_FACTOR_LU,MatGetFactor_mpiaij_mkl_cpardiso);
    937:   MatSolverTypeRegister(MATSOLVERMKL_CPARDISO,MATMPIBAIJ,MAT_FACTOR_LU,MatGetFactor_mpiaij_mkl_cpardiso);
    938:   MatSolverTypeRegister(MATSOLVERMKL_CPARDISO,MATMPISBAIJ,MAT_FACTOR_CHOLESKY,MatGetFactor_mpiaij_mkl_cpardiso);
    939:   return 0;
    940: }