xref: /petsc/src/mat/impls/baij/seq/baijmkl/baijmkl.c (revision 9c46acdfbc66b9187afcb21f11a82b85f21fce68)
17072be85SIrina Sokolova /*
27072be85SIrina Sokolova   Defines basic operations for the MATSEQBAIJMKL matrix class.
37072be85SIrina Sokolova   Uses sparse BLAS operations from the Intel Math Kernel Library (MKL)
47072be85SIrina Sokolova   wherever possible. If used MKL verion is older than 11.3 PETSc default
57072be85SIrina Sokolova   code for sparse matrix operations is used.
67072be85SIrina Sokolova */
77072be85SIrina Sokolova 
87072be85SIrina Sokolova #include <../src/mat/impls/baij/seq/baij.h>
97072be85SIrina Sokolova #include <../src/mat/impls/baij/seq/baijmkl/baijmkl.h>
107072be85SIrina Sokolova 
117072be85SIrina Sokolova 
127072be85SIrina Sokolova /* MKL include files. */
137072be85SIrina Sokolova #include <mkl_spblas.h>  /* Sparse BLAS */
147072be85SIrina Sokolova 
157072be85SIrina Sokolova #ifdef PETSC_HAVE_MKL_SPARSE_OPTIMIZE
167072be85SIrina Sokolova typedef struct {
177072be85SIrina Sokolova   PetscBool sparse_optimized; /* If PETSC_TRUE, then mkl_sparse_optimize() has been called. */
187072be85SIrina Sokolova   sparse_matrix_t bsrA; /* "Handle" used by SpMV2 inspector-executor routines. */
197072be85SIrina Sokolova   struct matrix_descr descr;
207072be85SIrina Sokolova #ifndef PETSC_MKL_SUPPORTS_BAIJ_ZERO_BASED
217072be85SIrina Sokolova   PetscInt *ai1;
227072be85SIrina Sokolova   PetscInt *aj1;
237072be85SIrina Sokolova #endif
247072be85SIrina Sokolova } Mat_SeqBAIJMKL;
257072be85SIrina Sokolova 
264d6dccb5SIrina Sokolova PetscErrorCode MatAssemblyEnd_SeqBAIJMKL(Mat A, MatAssemblyType mode);
277072be85SIrina Sokolova extern PetscErrorCode MatAssemblyEnd_SeqBAIJ(Mat,MatAssemblyType);
287072be85SIrina Sokolova 
297072be85SIrina Sokolova PETSC_INTERN PetscErrorCode MatConvert_SeqBAIJMKL_SeqBAIJ(Mat A,MatType type,MatReuse reuse,Mat *newmat)
307072be85SIrina Sokolova {
317072be85SIrina Sokolova   /* This routine is only called to convert a MATBAIJMKL to its base PETSc type, */
327072be85SIrina Sokolova   /* so we will ignore 'MatType type'. */
337072be85SIrina Sokolova   PetscErrorCode ierr;
347072be85SIrina Sokolova   Mat            B        = *newmat;
357072be85SIrina Sokolova   Mat_SeqBAIJMKL *baijmkl = (Mat_SeqBAIJMKL*)A->spptr;
367072be85SIrina Sokolova 
377072be85SIrina Sokolova   PetscFunctionBegin;
387072be85SIrina Sokolova   if (reuse == MAT_INITIAL_MATRIX) {
397072be85SIrina Sokolova     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
407072be85SIrina Sokolova   }
417072be85SIrina Sokolova 
427072be85SIrina Sokolova   /* Reset the original function pointers. */
437072be85SIrina Sokolova   B->ops->duplicate        = MatDuplicate_SeqBAIJ;
447072be85SIrina Sokolova   B->ops->assemblyend      = MatAssemblyEnd_SeqBAIJ;
457072be85SIrina Sokolova   B->ops->destroy          = MatDestroy_SeqBAIJ;
467072be85SIrina Sokolova   B->ops->multtranspose    = MatMultTranspose_SeqBAIJ;
477072be85SIrina Sokolova   B->ops->multtransposeadd = MatMultTransposeAdd_SeqBAIJ;
487072be85SIrina Sokolova   B->ops->scale            = MatScale_SeqBAIJ;
497072be85SIrina Sokolova   B->ops->diagonalscale    = MatDiagonalScale_SeqBAIJ;
507072be85SIrina Sokolova   B->ops->axpy             = MatAXPY_SeqBAIJ;
517072be85SIrina Sokolova 
527072be85SIrina Sokolova   switch (A->rmap->bs) {
537072be85SIrina Sokolova     case 1:
547072be85SIrina Sokolova       B->ops->mult    = MatMult_SeqBAIJ_1;
557072be85SIrina Sokolova       B->ops->multadd = MatMultAdd_SeqBAIJ_1;
567072be85SIrina Sokolova       break;
577072be85SIrina Sokolova     case 2:
587072be85SIrina Sokolova       B->ops->mult    = MatMult_SeqBAIJ_2;
597072be85SIrina Sokolova       B->ops->multadd = MatMultAdd_SeqBAIJ_2;
607072be85SIrina Sokolova       break;
617072be85SIrina Sokolova     case 3:
627072be85SIrina Sokolova       B->ops->mult    = MatMult_SeqBAIJ_3;
637072be85SIrina Sokolova       B->ops->multadd = MatMultAdd_SeqBAIJ_3;
647072be85SIrina Sokolova       break;
657072be85SIrina Sokolova     case 4:
667072be85SIrina Sokolova       B->ops->mult    = MatMult_SeqBAIJ_4;
677072be85SIrina Sokolova       B->ops->multadd = MatMultAdd_SeqBAIJ_4;
687072be85SIrina Sokolova       break;
697072be85SIrina Sokolova     case 5:
707072be85SIrina Sokolova       B->ops->mult    = MatMult_SeqBAIJ_5;
717072be85SIrina Sokolova       B->ops->multadd = MatMultAdd_SeqBAIJ_5;
727072be85SIrina Sokolova       break;
737072be85SIrina Sokolova     case 6:
747072be85SIrina Sokolova       B->ops->mult    = MatMult_SeqBAIJ_6;
757072be85SIrina Sokolova       B->ops->multadd = MatMultAdd_SeqBAIJ_6;
767072be85SIrina Sokolova       break;
777072be85SIrina Sokolova     case 7:
787072be85SIrina Sokolova       B->ops->mult    = MatMult_SeqBAIJ_7;
797072be85SIrina Sokolova       B->ops->multadd = MatMultAdd_SeqBAIJ_7;
807072be85SIrina Sokolova       break;
817072be85SIrina Sokolova     case 11:
827072be85SIrina Sokolova       B->ops->mult    = MatMult_SeqBAIJ_11;
837072be85SIrina Sokolova       B->ops->multadd = MatMultAdd_SeqBAIJ_11;
847072be85SIrina Sokolova       break;
857072be85SIrina Sokolova     case 15:
867072be85SIrina Sokolova       B->ops->mult    = MatMult_SeqBAIJ_15_ver1;
877072be85SIrina Sokolova       B->ops->multadd = MatMultAdd_SeqBAIJ_N;
887072be85SIrina Sokolova       break;
897072be85SIrina Sokolova     default:
907072be85SIrina Sokolova       B->ops->mult    = MatMult_SeqBAIJ_N;
917072be85SIrina Sokolova       B->ops->multadd = MatMultAdd_SeqBAIJ_N;
927072be85SIrina Sokolova       break;
937072be85SIrina Sokolova   }
947072be85SIrina Sokolova   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqbaijmkl_seqbaij_C",NULL);CHKERRQ(ierr);
957072be85SIrina Sokolova 
967072be85SIrina Sokolova   /* Free everything in the Mat_SeqBAIJMKL data structure. Currently, this
977072be85SIrina Sokolova    * simply involves destroying the MKL sparse matrix handle and then freeing
987072be85SIrina Sokolova    * the spptr pointer. */
997072be85SIrina Sokolova   if (reuse == MAT_INITIAL_MATRIX) baijmkl = (Mat_SeqBAIJMKL*)B->spptr;
1007072be85SIrina Sokolova 
1017072be85SIrina Sokolova   if (baijmkl->sparse_optimized) {
1027072be85SIrina Sokolova     sparse_status_t stat;
1037072be85SIrina Sokolova     stat = mkl_sparse_destroy(baijmkl->bsrA);
104*9c46acdfSRichard Tran Mills     if (stat != SPARSE_STATUS_SUCCESS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Intel MKL error: error in mkl_sparse_destroy");
1057072be85SIrina Sokolova   }
1067072be85SIrina Sokolova #ifndef PETSC_MKL_SUPPORTS_BAIJ_ZERO_BASED
1077072be85SIrina Sokolova    ierr = PetscFree(baijmkl->ai1);CHKERRQ(ierr);
1087072be85SIrina Sokolova    ierr = PetscFree(baijmkl->aj1);CHKERRQ(ierr);
1097072be85SIrina Sokolova #endif
1107072be85SIrina Sokolova   ierr = PetscFree(B->spptr);CHKERRQ(ierr);
1117072be85SIrina Sokolova 
1127072be85SIrina Sokolova   /* Change the type of B to MATSEQBAIJ. */
1137072be85SIrina Sokolova   ierr = PetscObjectChangeTypeName((PetscObject)B, MATSEQBAIJ);CHKERRQ(ierr);
1147072be85SIrina Sokolova 
1157072be85SIrina Sokolova   *newmat = B;
1167072be85SIrina Sokolova   PetscFunctionReturn(0);
1177072be85SIrina Sokolova }
1187072be85SIrina Sokolova 
1197072be85SIrina Sokolova PetscErrorCode MatDestroy_SeqBAIJMKL(Mat A)
1207072be85SIrina Sokolova {
1217072be85SIrina Sokolova   PetscErrorCode ierr;
1227072be85SIrina Sokolova   Mat_SeqBAIJMKL *baijmkl = (Mat_SeqBAIJMKL*) A->spptr;
1237072be85SIrina Sokolova 
1247072be85SIrina Sokolova   PetscFunctionBegin;
1257072be85SIrina Sokolova   if (baijmkl) {
1267072be85SIrina Sokolova     /* Clean up everything in the Mat_SeqBAIJMKL data structure, then free A->spptr. */
1277072be85SIrina Sokolova     if (baijmkl->sparse_optimized) {
1287072be85SIrina Sokolova       sparse_status_t stat = SPARSE_STATUS_SUCCESS;
1297072be85SIrina Sokolova       stat = mkl_sparse_destroy(baijmkl->bsrA);
130*9c46acdfSRichard Tran Mills       if (stat != SPARSE_STATUS_SUCCESS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Intel MKL error: error in mkl_sparse_destroy");
1317072be85SIrina Sokolova     }
1327072be85SIrina Sokolova #ifndef PETSC_MKL_SUPPORTS_BAIJ_ZERO_BASED
1337072be85SIrina Sokolova    ierr = PetscFree(baijmkl->ai1);CHKERRQ(ierr);
1347072be85SIrina Sokolova    ierr = PetscFree(baijmkl->aj1);CHKERRQ(ierr);
1357072be85SIrina Sokolova #endif
1367072be85SIrina Sokolova     ierr = PetscFree(A->spptr);CHKERRQ(ierr);
1377072be85SIrina Sokolova   }
1387072be85SIrina Sokolova 
1397072be85SIrina Sokolova   /* Change the type of A back to SEQBAIJ and use MatDestroy_SeqBAIJ()
1407072be85SIrina Sokolova    * to destroy everything that remains. */
1417072be85SIrina Sokolova   ierr = PetscObjectChangeTypeName((PetscObject)A, MATSEQBAIJ);CHKERRQ(ierr);
1427072be85SIrina Sokolova   ierr = MatDestroy_SeqBAIJ(A);CHKERRQ(ierr);
1437072be85SIrina Sokolova   PetscFunctionReturn(0);
1447072be85SIrina Sokolova }
1457072be85SIrina Sokolova 
1467072be85SIrina Sokolova PETSC_INTERN PetscErrorCode MatSeqBAIJMKL_create_mkl_handle(Mat A)
1477072be85SIrina Sokolova {
1487072be85SIrina Sokolova   PetscErrorCode ierr;
1497072be85SIrina Sokolova   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ*)A->data;
1507072be85SIrina Sokolova   Mat_SeqBAIJMKL  *baijmkl = (Mat_SeqBAIJMKL*)A->spptr;
1517072be85SIrina Sokolova   PetscInt        mbs, nbs, nz, bs, i;
1527072be85SIrina Sokolova   MatScalar       *aa;
1537072be85SIrina Sokolova   PetscInt        *aj,*ai;
1547072be85SIrina Sokolova   sparse_status_t stat;
1557072be85SIrina Sokolova 
1567072be85SIrina Sokolova   PetscFunctionBegin;
1577072be85SIrina Sokolova   if (baijmkl->sparse_optimized) {
1587072be85SIrina Sokolova     /* Matrix has been previously assembled and optimized. Must destroy old
1597072be85SIrina Sokolova      * matrix handle before running the optimization step again. */
1604d6dccb5SIrina Sokolova #ifndef PETSC_MKL_SUPPORTS_BAIJ_ZERO_BASED
1614d6dccb5SIrina Sokolova     ierr = PetscFree(baijmkl->ai1);CHKERRQ(ierr);
1624d6dccb5SIrina Sokolova     ierr = PetscFree(baijmkl->aj1);CHKERRQ(ierr);
1634d6dccb5SIrina Sokolova #endif
164017c2882SIrina Sokolova     stat = mkl_sparse_destroy(baijmkl->bsrA);CHKERRMKL(stat);
1657072be85SIrina Sokolova   }
1667072be85SIrina Sokolova   baijmkl->sparse_optimized = PETSC_FALSE;
1677072be85SIrina Sokolova 
1687072be85SIrina Sokolova   /* Now perform the SpMV2 setup and matrix optimization. */
1697072be85SIrina Sokolova   baijmkl->descr.type        = SPARSE_MATRIX_TYPE_GENERAL;
1707072be85SIrina Sokolova   baijmkl->descr.mode        = SPARSE_FILL_MODE_LOWER;
1717072be85SIrina Sokolova   baijmkl->descr.diag        = SPARSE_DIAG_NON_UNIT;
1727072be85SIrina Sokolova   mbs = a->mbs;
1737072be85SIrina Sokolova   nbs = a->nbs;
1747072be85SIrina Sokolova   nz  = a->nz;
1757072be85SIrina Sokolova   bs  = A->rmap->bs;
1767072be85SIrina Sokolova   aa  = a->a;
1777072be85SIrina Sokolova 
17880095d54SIrina Sokolova   if ((nz!=0) & !(A->structure_only)) {
1797072be85SIrina Sokolova     /* Create a new, optimized sparse matrix handle only if the matrix has nonzero entries.
1807072be85SIrina Sokolova      * The MKL sparse-inspector executor routines don't like being passed an empty matrix. */
1817072be85SIrina Sokolova #ifdef PETSC_MKL_SUPPORTS_BAIJ_ZERO_BASED
1827072be85SIrina Sokolova     aj   = a->j;
1837072be85SIrina Sokolova     ai   = a->i;
184017c2882SIrina Sokolova     stat = mkl_sparse_x_create_bsr(&(baijmkl->bsrA),SPARSE_INDEX_BASE_ZERO,SPARSE_LAYOUT_COLUMN_MAJOR,mbs,nbs,bs,ai,ai+1,aj,aa);CHKERRMKL(stat);
1857072be85SIrina Sokolova #else
1867072be85SIrina Sokolova     ierr = PetscMalloc1(mbs+1,&ai);CHKERRQ(ierr);
1877072be85SIrina Sokolova     ierr = PetscMalloc1(nz,&aj);CHKERRQ(ierr);
1887072be85SIrina Sokolova     for (i=0;i<mbs+1;i++)
1897072be85SIrina Sokolova       ai[i] = a->i[i]+1;
1907072be85SIrina Sokolova     for (i=0;i<nz;i++)
1917072be85SIrina Sokolova       aj[i] = a->j[i]+1;
1927072be85SIrina Sokolova     aa   = a->a;
193017c2882SIrina Sokolova     stat = mkl_sparse_x_create_bsr(&baijmkl->bsrA,SPARSE_INDEX_BASE_ONE,SPARSE_LAYOUT_COLUMN_MAJOR,mbs,nbs,bs,ai,ai+1,aj,aa);CHKERRMKL(stat);
1947072be85SIrina Sokolova     baijmkl->ai1 = ai;
1957072be85SIrina Sokolova     baijmkl->aj1 = aj;
1967072be85SIrina Sokolova #endif
197017c2882SIrina Sokolova     stat = mkl_sparse_set_mv_hint(baijmkl->bsrA,SPARSE_OPERATION_NON_TRANSPOSE,baijmkl->descr,1000);CHKERRMKL(stat);
198017c2882SIrina Sokolova     stat = mkl_sparse_set_memory_hint(baijmkl->bsrA,SPARSE_MEMORY_AGGRESSIVE);CHKERRMKL(stat);
199017c2882SIrina Sokolova     stat = mkl_sparse_optimize(baijmkl->bsrA);CHKERRMKL(stat);
2007072be85SIrina Sokolova     baijmkl->sparse_optimized = PETSC_TRUE;
2017072be85SIrina Sokolova   }
2027072be85SIrina Sokolova   PetscFunctionReturn(0);
2037072be85SIrina Sokolova }
2047072be85SIrina Sokolova 
2057072be85SIrina Sokolova PetscErrorCode MatDuplicate_SeqBAIJMKL(Mat A, MatDuplicateOption op, Mat *M)
2067072be85SIrina Sokolova {
2077072be85SIrina Sokolova   PetscErrorCode ierr;
2087072be85SIrina Sokolova   Mat_SeqBAIJMKL *baijmkl;
2097072be85SIrina Sokolova   Mat_SeqBAIJMKL *baijmkl_dest;
2107072be85SIrina Sokolova 
2117072be85SIrina Sokolova   PetscFunctionBegin;
2127072be85SIrina Sokolova   ierr = MatDuplicate_SeqBAIJ(A,op,M);CHKERRQ(ierr);
2137072be85SIrina Sokolova   baijmkl = (Mat_SeqBAIJMKL*) A->spptr;
21471bc03e0SIrina Sokolova   ierr = PetscNewLog((*M),&baijmkl_dest);CHKERRQ(ierr);
21571bc03e0SIrina Sokolova   (*M)->spptr = (void*)baijmkl_dest;
2167072be85SIrina Sokolova   ierr = PetscMemcpy(baijmkl_dest,baijmkl,sizeof(Mat_SeqBAIJMKL));CHKERRQ(ierr);
2177072be85SIrina Sokolova   baijmkl_dest->sparse_optimized = PETSC_FALSE;
2187072be85SIrina Sokolova   ierr = MatSeqBAIJMKL_create_mkl_handle(A);CHKERRQ(ierr);
2197072be85SIrina Sokolova   PetscFunctionReturn(0);
2207072be85SIrina Sokolova }
2217072be85SIrina Sokolova 
2227072be85SIrina Sokolova PetscErrorCode MatMult_SeqBAIJMKL_SpMV2(Mat A,Vec xx,Vec yy)
2237072be85SIrina Sokolova {
2247072be85SIrina Sokolova   Mat_SeqBAIJ        *a = (Mat_SeqBAIJ*)A->data;
2257072be85SIrina Sokolova   Mat_SeqBAIJMKL     *baijmkl=(Mat_SeqBAIJMKL*)A->spptr;
2267072be85SIrina Sokolova   const PetscScalar  *x;
2277072be85SIrina Sokolova   PetscScalar        *y;
2287072be85SIrina Sokolova   PetscErrorCode     ierr;
2297072be85SIrina Sokolova   sparse_status_t    stat = SPARSE_STATUS_SUCCESS;
2307072be85SIrina Sokolova 
2317072be85SIrina Sokolova   PetscFunctionBegin;
2327072be85SIrina Sokolova   /* If there are no nonzero entries, zero yy and return immediately. */
2337072be85SIrina Sokolova   if(!a->nz) {
2347072be85SIrina Sokolova     PetscInt i;
2357072be85SIrina Sokolova     PetscInt m=a->mbs*A->rmap->bs;
2367072be85SIrina Sokolova     ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
2377072be85SIrina Sokolova     for (i=0; i<m; i++) {
2387072be85SIrina Sokolova       y[i] = 0.0;
2397072be85SIrina Sokolova     }
2407072be85SIrina Sokolova     ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
2417072be85SIrina Sokolova     PetscFunctionReturn(0);
2427072be85SIrina Sokolova   }
2437072be85SIrina Sokolova 
2447072be85SIrina Sokolova   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
2457072be85SIrina Sokolova   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
2467072be85SIrina Sokolova 
2477072be85SIrina Sokolova   /* In some cases, we get to this point without mkl_sparse_optimize() having been called, so we check and then call
2487072be85SIrina Sokolova    * it if needed. Eventually, when everything in PETSc is properly updating the matrix state, we should probably
2497072be85SIrina Sokolova    * take a "lazy" approach to creation/updating of the MKL matrix handle and plan to always do it here (when needed). */
2507072be85SIrina Sokolova   if (!baijmkl->sparse_optimized) {
251017c2882SIrina Sokolova     ierr = MatSeqBAIJMKL_create_mkl_handle(A);CHKERRQ(ierr);
2527072be85SIrina Sokolova   }
2537072be85SIrina Sokolova 
2547072be85SIrina Sokolova   /* Call MKL SpMV2 executor routine to do the MatMult. */
255017c2882SIrina Sokolova   stat = mkl_sparse_x_mv(SPARSE_OPERATION_NON_TRANSPOSE,1.0,baijmkl->bsrA,baijmkl->descr,x,0.0,y);CHKERRMKL(stat);
2567072be85SIrina Sokolova 
2577072be85SIrina Sokolova   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
2587072be85SIrina Sokolova   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
2597072be85SIrina Sokolova   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
2607072be85SIrina Sokolova   PetscFunctionReturn(0);
2617072be85SIrina Sokolova }
2627072be85SIrina Sokolova 
2637072be85SIrina Sokolova PetscErrorCode MatMultTranspose_SeqBAIJMKL_SpMV2(Mat A,Vec xx,Vec yy)
2647072be85SIrina Sokolova {
2657072be85SIrina Sokolova   Mat_SeqBAIJ       *a       = (Mat_SeqBAIJ*)A->data;
2667072be85SIrina Sokolova   Mat_SeqBAIJMKL    *baijmkl = (Mat_SeqBAIJMKL*)A->spptr;
2677072be85SIrina Sokolova   const PetscScalar *x;
2687072be85SIrina Sokolova   PetscScalar       *y;
2697072be85SIrina Sokolova   PetscErrorCode    ierr;
2707072be85SIrina Sokolova   sparse_status_t   stat;
2717072be85SIrina Sokolova 
2727072be85SIrina Sokolova   PetscFunctionBegin;
2737072be85SIrina Sokolova   /* If there are no nonzero entries, zero yy and return immediately. */
2747072be85SIrina Sokolova   if(!a->nz) {
2757072be85SIrina Sokolova     PetscInt i;
2767072be85SIrina Sokolova     PetscInt n=a->nbs;
2777072be85SIrina Sokolova     ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
2787072be85SIrina Sokolova     for (i=0; i<n; i++) {
2797072be85SIrina Sokolova       y[i] = 0.0;
2807072be85SIrina Sokolova     }
2817072be85SIrina Sokolova     ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
2827072be85SIrina Sokolova     PetscFunctionReturn(0);
2837072be85SIrina Sokolova   }
2847072be85SIrina Sokolova 
2857072be85SIrina Sokolova   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
2867072be85SIrina Sokolova   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
2877072be85SIrina Sokolova 
2887072be85SIrina Sokolova   /* In some cases, we get to this point without mkl_sparse_optimize() having been called, so we check and then call
2897072be85SIrina Sokolova    * it if needed. Eventually, when everything in PETSc is properly updating the matrix state, we should probably
2907072be85SIrina Sokolova    * take a "lazy" approach to creation/updating of the MKL matrix handle and plan to always do it here (when needed). */
2917072be85SIrina Sokolova   if (!baijmkl->sparse_optimized) {
292017c2882SIrina Sokolova     ierr = MatSeqBAIJMKL_create_mkl_handle(A);CHKERRQ(ierr);
2937072be85SIrina Sokolova   }
2947072be85SIrina Sokolova 
2957072be85SIrina Sokolova   /* Call MKL SpMV2 executor routine to do the MatMultTranspose. */
296017c2882SIrina Sokolova   stat = mkl_sparse_x_mv(SPARSE_OPERATION_TRANSPOSE,1.0,baijmkl->bsrA,baijmkl->descr,x,0.0,y);CHKERRMKL(stat);
2977072be85SIrina Sokolova 
2987072be85SIrina Sokolova   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
2997072be85SIrina Sokolova   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
3007072be85SIrina Sokolova   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
3017072be85SIrina Sokolova   PetscFunctionReturn(0);
3027072be85SIrina Sokolova }
3037072be85SIrina Sokolova 
3047072be85SIrina Sokolova PetscErrorCode MatMultAdd_SeqBAIJMKL_SpMV2(Mat A,Vec xx,Vec yy,Vec zz)
3057072be85SIrina Sokolova {
3067072be85SIrina Sokolova   Mat_SeqBAIJ        *a       = (Mat_SeqBAIJ*)A->data;
3077072be85SIrina Sokolova   Mat_SeqBAIJMKL     *baijmkl = (Mat_SeqBAIJMKL*)A->spptr;
3087072be85SIrina Sokolova   const PetscScalar  *x;
3097072be85SIrina Sokolova   PetscScalar        *y,*z;
3107072be85SIrina Sokolova   PetscErrorCode     ierr;
3117072be85SIrina Sokolova   PetscInt           m=a->mbs*A->rmap->bs;
3127072be85SIrina Sokolova   PetscInt           i;
3137072be85SIrina Sokolova 
3147072be85SIrina Sokolova   sparse_status_t stat = SPARSE_STATUS_SUCCESS;
3157072be85SIrina Sokolova 
3167072be85SIrina Sokolova   PetscFunctionBegin;
3177072be85SIrina Sokolova   /* If there are no nonzero entries, set zz = yy and return immediately. */
3187072be85SIrina Sokolova   if(!a->nz) {
3197072be85SIrina Sokolova     PetscInt i;
3207072be85SIrina Sokolova     ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
3217072be85SIrina Sokolova     for (i=0; i<m; i++) {
3227072be85SIrina Sokolova       z[i] = y[i];
3237072be85SIrina Sokolova     }
3247072be85SIrina Sokolova     ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
3257072be85SIrina Sokolova     PetscFunctionReturn(0);
3267072be85SIrina Sokolova   }
3277072be85SIrina Sokolova 
3287072be85SIrina Sokolova   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
3297072be85SIrina Sokolova   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
3307072be85SIrina Sokolova 
3317072be85SIrina Sokolova   /* In some cases, we get to this point without mkl_sparse_optimize() having been called, so we check and then call
3327072be85SIrina Sokolova    * it if needed. Eventually, when everything in PETSc is properly updating the matrix state, we should probably
3337072be85SIrina Sokolova    * take a "lazy" approach to creation/updating of the MKL matrix handle and plan to always do it here (when needed). */
3347072be85SIrina Sokolova   if (!baijmkl->sparse_optimized) {
335017c2882SIrina Sokolova     ierr = MatSeqBAIJMKL_create_mkl_handle(A);CHKERRQ(ierr);
3367072be85SIrina Sokolova   }
3377072be85SIrina Sokolova 
3387072be85SIrina Sokolova   /* Call MKL sparse BLAS routine to do the MatMult. */
3397072be85SIrina Sokolova   if (zz == yy) {
3407072be85SIrina Sokolova     /* If zz and yy are the same vector, we can use mkl_sparse_x_mv, which calculates y = alpha*A*x + beta*y,
3417072be85SIrina Sokolova      * with alpha and beta both set to 1.0. */
342017c2882SIrina Sokolova     stat = mkl_sparse_x_mv(SPARSE_OPERATION_NON_TRANSPOSE,1.0,baijmkl->bsrA,baijmkl->descr,x,1.0,z);CHKERRMKL(stat);
3437072be85SIrina Sokolova   } else {
3447072be85SIrina Sokolova     /* zz and yy are different vectors, so we call mkl_sparse_x_mv with alpha=1.0 and beta=0.0, and then
3457072be85SIrina Sokolova      * we add the contents of vector yy to the result; MKL sparse BLAS does not have a MatMultAdd equivalent. */
346017c2882SIrina Sokolova     stat = mkl_sparse_x_mv(SPARSE_OPERATION_NON_TRANSPOSE,1.0,baijmkl->bsrA,baijmkl->descr,x,0.0,z);CHKERRMKL(stat);
3477072be85SIrina Sokolova     for (i=0; i<m; i++) {
3487072be85SIrina Sokolova       z[i] += y[i];
3497072be85SIrina Sokolova     }
3507072be85SIrina Sokolova   }
3517072be85SIrina Sokolova 
3527072be85SIrina Sokolova   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
3537072be85SIrina Sokolova   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
3547072be85SIrina Sokolova   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
3557072be85SIrina Sokolova   PetscFunctionReturn(0);
3567072be85SIrina Sokolova }
3577072be85SIrina Sokolova 
3587072be85SIrina Sokolova PetscErrorCode MatMultTransposeAdd_SeqBAIJMKL_SpMV2(Mat A,Vec xx,Vec yy,Vec zz)
3597072be85SIrina Sokolova {
3607072be85SIrina Sokolova   Mat_SeqBAIJ       *a       = (Mat_SeqBAIJ*)A->data;
3617072be85SIrina Sokolova   Mat_SeqBAIJMKL    *baijmkl = (Mat_SeqBAIJMKL*)A->spptr;
3627072be85SIrina Sokolova   const PetscScalar *x;
3637072be85SIrina Sokolova   PetscScalar       *y,*z;
3647072be85SIrina Sokolova   PetscErrorCode    ierr;
3657072be85SIrina Sokolova   PetscInt          n=a->nbs*A->rmap->bs;
3667072be85SIrina Sokolova   PetscInt          i;
3677072be85SIrina Sokolova   /* Variables not in MatMultTransposeAdd_SeqBAIJ. */
3687072be85SIrina Sokolova   sparse_status_t   stat = SPARSE_STATUS_SUCCESS;
3697072be85SIrina Sokolova 
3707072be85SIrina Sokolova   PetscFunctionBegin;
3717072be85SIrina Sokolova   /* If there are no nonzero entries, set zz = yy and return immediately. */
3727072be85SIrina Sokolova   if(!a->nz) {
3737072be85SIrina Sokolova     PetscInt i;
3747072be85SIrina Sokolova     ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
3757072be85SIrina Sokolova     for (i=0; i<n; i++) {
3767072be85SIrina Sokolova       z[i] = y[i];
3777072be85SIrina Sokolova     }
3787072be85SIrina Sokolova     ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
3797072be85SIrina Sokolova     PetscFunctionReturn(0);
3807072be85SIrina Sokolova   }
3817072be85SIrina Sokolova 
3827072be85SIrina Sokolova   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
3837072be85SIrina Sokolova   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
3847072be85SIrina Sokolova 
3857072be85SIrina Sokolova   /* In some cases, we get to this point without mkl_sparse_optimize() having been called, so we check and then call
3867072be85SIrina Sokolova    * it if needed. Eventually, when everything in PETSc is properly updating the matrix state, we should probably
3877072be85SIrina Sokolova    * take a "lazy" approach to creation/updating of the MKL matrix handle and plan to always do it here (when needed). */
3887072be85SIrina Sokolova   if (!baijmkl->sparse_optimized) {
389017c2882SIrina Sokolova     ierr = MatSeqBAIJMKL_create_mkl_handle(A);CHKERRQ(ierr);
3907072be85SIrina Sokolova   }
3917072be85SIrina Sokolova 
3927072be85SIrina Sokolova   /* Call MKL sparse BLAS routine to do the MatMult. */
3937072be85SIrina Sokolova   if (zz == yy) {
3947072be85SIrina Sokolova     /* If zz and yy are the same vector, we can use mkl_sparse_x_mv, which calculates y = alpha*A*x + beta*y,
3957072be85SIrina Sokolova      * with alpha and beta both set to 1.0. */
396017c2882SIrina Sokolova     stat = mkl_sparse_x_mv(SPARSE_OPERATION_TRANSPOSE,1.0,baijmkl->bsrA,baijmkl->descr,x,1.0,z);CHKERRMKL(stat);
3977072be85SIrina Sokolova   } else {
3987072be85SIrina Sokolova     /* zz and yy are different vectors, so we call mkl_sparse_x_mv with alpha=1.0 and beta=0.0, and then
3997072be85SIrina Sokolova      * we add the contents of vector yy to the result; MKL sparse BLAS does not have a MatMultAdd equivalent. */
400017c2882SIrina Sokolova     stat = mkl_sparse_x_mv(SPARSE_OPERATION_TRANSPOSE,1.0,baijmkl->bsrA,baijmkl->descr,x,0.0,z);CHKERRMKL(stat);
4017072be85SIrina Sokolova     for (i=0; i<n; i++) {
4027072be85SIrina Sokolova       z[i] += y[i];
4037072be85SIrina Sokolova     }
4047072be85SIrina Sokolova   }
4057072be85SIrina Sokolova 
4067072be85SIrina Sokolova   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
4077072be85SIrina Sokolova   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
4087072be85SIrina Sokolova   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
4097072be85SIrina Sokolova   PetscFunctionReturn(0);
4107072be85SIrina Sokolova }
4117072be85SIrina Sokolova 
4127072be85SIrina Sokolova PetscErrorCode MatScale_SeqBAIJMKL(Mat inA,PetscScalar alpha)
4137072be85SIrina Sokolova {
4147072be85SIrina Sokolova   PetscErrorCode ierr;
4157072be85SIrina Sokolova 
4167072be85SIrina Sokolova   PetscFunctionBegin;
4177072be85SIrina Sokolova   ierr = MatScale_SeqBAIJ(inA,alpha);CHKERRQ(ierr);
4187072be85SIrina Sokolova   ierr = MatSeqBAIJMKL_create_mkl_handle(inA);CHKERRQ(ierr);
4197072be85SIrina Sokolova   PetscFunctionReturn(0);
4207072be85SIrina Sokolova }
4217072be85SIrina Sokolova 
4227072be85SIrina Sokolova PetscErrorCode MatDiagonalScale_SeqBAIJMKL(Mat A,Vec ll,Vec rr)
4237072be85SIrina Sokolova {
4247072be85SIrina Sokolova   PetscErrorCode ierr;
4257072be85SIrina Sokolova 
4267072be85SIrina Sokolova   PetscFunctionBegin;
4277072be85SIrina Sokolova   ierr = MatDiagonalScale_SeqBAIJ(A,ll,rr);CHKERRQ(ierr);
4287072be85SIrina Sokolova   ierr = MatSeqBAIJMKL_create_mkl_handle(A);CHKERRQ(ierr);
4297072be85SIrina Sokolova   PetscFunctionReturn(0);
4307072be85SIrina Sokolova }
4317072be85SIrina Sokolova 
4327072be85SIrina Sokolova PetscErrorCode MatAXPY_SeqBAIJMKL(Mat Y,PetscScalar a,Mat X,MatStructure str)
4337072be85SIrina Sokolova {
4347072be85SIrina Sokolova   PetscErrorCode ierr;
4357072be85SIrina Sokolova 
4367072be85SIrina Sokolova   PetscFunctionBegin;
4377072be85SIrina Sokolova   ierr = MatAXPY_SeqBAIJ(Y,a,X,str);CHKERRQ(ierr);
4387072be85SIrina Sokolova   if (str == SAME_NONZERO_PATTERN) {
4397072be85SIrina Sokolova     /* MatAssemblyEnd() is not called if SAME_NONZERO_PATTERN, so we need to force update of the MKL matrix handle. */
4407072be85SIrina Sokolova     ierr = MatSeqBAIJMKL_create_mkl_handle(Y);CHKERRQ(ierr);
4417072be85SIrina Sokolova   }
4427072be85SIrina Sokolova   PetscFunctionReturn(0);
4437072be85SIrina Sokolova }
4447072be85SIrina Sokolova /* MatConvert_SeqBAIJ_SeqBAIJMKL converts a SeqBAIJ matrix into a
4457072be85SIrina Sokolova  * SeqBAIJMKL matrix.  This routine is called by the MatCreate_SeqMKLBAIJ()
4467072be85SIrina Sokolova  * routine, but can also be used to convert an assembled SeqBAIJ matrix
4477072be85SIrina Sokolova  * into a SeqBAIJMKL one. */
4487072be85SIrina Sokolova PETSC_INTERN PetscErrorCode MatConvert_SeqBAIJ_SeqBAIJMKL(Mat A,MatType type,MatReuse reuse,Mat *newmat)
4497072be85SIrina Sokolova {
4507072be85SIrina Sokolova   PetscErrorCode ierr;
4517072be85SIrina Sokolova   Mat            B = *newmat;
4527072be85SIrina Sokolova   Mat_SeqBAIJMKL *baijmkl;
4537072be85SIrina Sokolova   PetscBool      sametype;
4547072be85SIrina Sokolova 
4557072be85SIrina Sokolova   PetscFunctionBegin;
4567072be85SIrina Sokolova   if (reuse == MAT_INITIAL_MATRIX) {
4577072be85SIrina Sokolova     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
4587072be85SIrina Sokolova   }
4597072be85SIrina Sokolova 
4607072be85SIrina Sokolova   ierr = PetscObjectTypeCompare((PetscObject)A,type,&sametype);CHKERRQ(ierr);
4617072be85SIrina Sokolova   if (sametype) PetscFunctionReturn(0);
4627072be85SIrina Sokolova 
4637072be85SIrina Sokolova   ierr     = PetscNewLog(B,&baijmkl);CHKERRQ(ierr);
4647072be85SIrina Sokolova   B->spptr = (void*)baijmkl;
4657072be85SIrina Sokolova 
4667072be85SIrina Sokolova   /* Set function pointers for methods that we inherit from BAIJ but override.
4677072be85SIrina Sokolova    * We also parse some command line options below, since those determine some of the methods we point to. */
4687072be85SIrina Sokolova   B->ops->assemblyend      = MatAssemblyEnd_SeqBAIJMKL;
4697072be85SIrina Sokolova 
4707072be85SIrina Sokolova   baijmkl->sparse_optimized = PETSC_FALSE;
4717072be85SIrina Sokolova 
4727072be85SIrina Sokolova   ierr = PetscObjectComposeFunction((PetscObject)B,"MatScale_SeqBAIJMKL_C",MatScale_SeqBAIJMKL);CHKERRQ(ierr);
4737072be85SIrina Sokolova   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqbaijmkl_seqbaij_C",MatConvert_SeqBAIJMKL_SeqBAIJ);CHKERRQ(ierr);
4747072be85SIrina Sokolova 
4757072be85SIrina Sokolova   ierr    = PetscObjectChangeTypeName((PetscObject)B,MATSEQBAIJMKL);CHKERRQ(ierr);
4767072be85SIrina Sokolova   *newmat = B;
4777072be85SIrina Sokolova   PetscFunctionReturn(0);
4787072be85SIrina Sokolova }
479*9c46acdfSRichard Tran Mills 
4804d6dccb5SIrina Sokolova PetscErrorCode MatAssemblyEnd_SeqBAIJMKL(Mat A, MatAssemblyType mode)
4814d6dccb5SIrina Sokolova {
4824d6dccb5SIrina Sokolova   PetscErrorCode  ierr;
483*9c46acdfSRichard Tran Mills 
4844d6dccb5SIrina Sokolova   PetscFunctionBegin;
4854d6dccb5SIrina Sokolova   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
4864d6dccb5SIrina Sokolova   ierr = MatAssemblyEnd_SeqBAIJ(A, mode);CHKERRQ(ierr);
4874d6dccb5SIrina Sokolova   ierr = MatSeqBAIJMKL_create_mkl_handle(A);CHKERRQ(ierr);
4884d6dccb5SIrina Sokolova   A->ops->destroy          = MatDestroy_SeqBAIJMKL;
4894d6dccb5SIrina Sokolova   A->ops->mult             = MatMult_SeqBAIJMKL_SpMV2;
4904d6dccb5SIrina Sokolova   A->ops->multtranspose    = MatMultTranspose_SeqBAIJMKL_SpMV2;
4914d6dccb5SIrina Sokolova   A->ops->multadd          = MatMultAdd_SeqBAIJMKL_SpMV2;
4924d6dccb5SIrina Sokolova   A->ops->multtransposeadd = MatMultTransposeAdd_SeqBAIJMKL_SpMV2;
4934d6dccb5SIrina Sokolova   A->ops->scale            = MatScale_SeqBAIJMKL;
4944d6dccb5SIrina Sokolova   A->ops->diagonalscale    = MatDiagonalScale_SeqBAIJMKL;
4954d6dccb5SIrina Sokolova   A->ops->axpy             = MatAXPY_SeqBAIJMKL;
4964d6dccb5SIrina Sokolova   A->ops->duplicate        = MatDuplicate_SeqBAIJMKL;
4974d6dccb5SIrina Sokolova   PetscFunctionReturn(0);
4984d6dccb5SIrina Sokolova }
4997072be85SIrina Sokolova #endif /* PETSC_HAVE_MKL_SPARSE_OPTIMIZE */
500*9c46acdfSRichard Tran Mills 
5017072be85SIrina Sokolova /*@C
5027072be85SIrina Sokolova    MatCreateSeqBAIJMKL - Creates a sparse matrix of type SEQBAIJMKL.
5037072be85SIrina Sokolova    This type inherits from BAIJ and is largely identical, but uses sparse BLAS
5047072be85SIrina Sokolova    routines from Intel MKL whenever possible.
5057072be85SIrina Sokolova    MatMult, MatMultAdd, MatMultTranspose, and MatMultTransposeAdd
5067072be85SIrina Sokolova    operations are currently supported.
5077072be85SIrina Sokolova    If the installed version of MKL supports the "SpMV2" sparse
5087072be85SIrina Sokolova    inspector-executor routines, then those are used by default.
5097072be85SIrina Sokolova    Default PETSc kernels are used otherwise.
5107072be85SIrina Sokolova 
5117072be85SIrina Sokolova    Input Parameters:
5127072be85SIrina Sokolova +  comm - MPI communicator, set to PETSC_COMM_SELF
5137072be85SIrina Sokolova .  bs - size of block, the blocks are ALWAYS square. One can use MatSetBlockSizes() to set a different row and column blocksize but the row
5147072be85SIrina Sokolova           blocksize always defines the size of the blocks. The column blocksize sets the blocksize of the vectors obtained with MatCreateVecs()
5157072be85SIrina Sokolova .  m - number of rows
5167072be85SIrina Sokolova .  n - number of columns
5177072be85SIrina Sokolova .  nz - number of nonzero blocks  per block row (same for all rows)
5187072be85SIrina Sokolova -  nnz - array containing the number of nonzero blocks in the various block rows
5197072be85SIrina Sokolova          (possibly different for each block row) or NULL
5207072be85SIrina Sokolova 
5217072be85SIrina Sokolova 
5227072be85SIrina Sokolova    Output Parameter:
5237072be85SIrina Sokolova .  A - the matrix
5247072be85SIrina Sokolova 
5257072be85SIrina Sokolova    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
5267072be85SIrina Sokolova    MatXXXXSetPreallocation() paradgm instead of this routine directly.
5277072be85SIrina Sokolova    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
5287072be85SIrina Sokolova 
5297072be85SIrina Sokolova    Options Database Keys:
5307072be85SIrina Sokolova .   -mat_no_unroll - uses code that does not unroll the loops in the
5317072be85SIrina Sokolova                      block calculations (much slower)
5327072be85SIrina Sokolova .    -mat_block_size - size of the blocks to use
5337072be85SIrina Sokolova 
5347072be85SIrina Sokolova    Level: intermediate
5357072be85SIrina Sokolova 
5367072be85SIrina Sokolova    Notes:
5377072be85SIrina Sokolova    The number of rows and columns must be divisible by blocksize.
5387072be85SIrina Sokolova 
5397072be85SIrina Sokolova    If the nnz parameter is given then the nz parameter is ignored
5407072be85SIrina Sokolova 
5417072be85SIrina Sokolova    A nonzero block is any block that as 1 or more nonzeros in it
5427072be85SIrina Sokolova 
5437072be85SIrina Sokolova    The block AIJ format is fully compatible with standard Fortran 77
5447072be85SIrina Sokolova    storage.  That is, the stored row and column indices can begin at
5457072be85SIrina Sokolova    either one (as in Fortran) or zero.  See the users' manual for details.
5467072be85SIrina Sokolova 
5477072be85SIrina Sokolova    Specify the preallocated storage with either nz or nnz (not both).
5487072be85SIrina Sokolova    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
5497072be85SIrina Sokolova    allocation.  See Users-Manual: ch_mat for details.
5507072be85SIrina Sokolova    matrices.
5517072be85SIrina Sokolova 
5527072be85SIrina Sokolova .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateBAIJ()
5537072be85SIrina Sokolova 
5547072be85SIrina Sokolova @*/
5557072be85SIrina Sokolova PetscErrorCode  MatCreateSeqBAIJMKL(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
5567072be85SIrina Sokolova {
5577072be85SIrina Sokolova   PetscErrorCode ierr;
5587072be85SIrina Sokolova 
5597072be85SIrina Sokolova   PetscFunctionBegin;
5607072be85SIrina Sokolova   ierr = MatCreate(comm,A);CHKERRQ(ierr);
5617072be85SIrina Sokolova   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
5627072be85SIrina Sokolova #ifdef PETSC_HAVE_MKL_SPARSE_OPTIMIZE
5637072be85SIrina Sokolova   ierr = MatSetType(*A,MATSEQBAIJMKL);CHKERRQ(ierr);
5647072be85SIrina Sokolova   ierr = MatSeqBAIJSetPreallocation_SeqBAIJ(*A,bs,nz,(PetscInt*)nnz);CHKERRQ(ierr);
5657072be85SIrina Sokolova #else
5667072be85SIrina Sokolova   ierr = PetscInfo(A,"MKL baij routines are not supported for used version of MKL. Using PETSc default routines. \n Please use version of MKL 11.3 and higher. \n");
5677072be85SIrina Sokolova   ierr = MatSetType(*A,MATSEQBAIJ);CHKERRQ(ierr);
5687072be85SIrina Sokolova   ierr = MatSeqBAIJSetPreallocation(*A,bs,nz,(PetscInt*)nnz);CHKERRQ(ierr);
5697072be85SIrina Sokolova #endif
5707072be85SIrina Sokolova   PetscFunctionReturn(0);
5717072be85SIrina Sokolova }
572*9c46acdfSRichard Tran Mills 
5737072be85SIrina Sokolova PETSC_EXTERN PetscErrorCode MatCreate_SeqBAIJMKL(Mat A)
5747072be85SIrina Sokolova {
5757072be85SIrina Sokolova   PetscErrorCode ierr;
5767072be85SIrina Sokolova 
5777072be85SIrina Sokolova   PetscFunctionBegin;
5787072be85SIrina Sokolova   ierr = MatSetType(A,MATSEQBAIJ);CHKERRQ(ierr);
5797072be85SIrina Sokolova #ifdef PETSC_HAVE_MKL_SPARSE_OPTIMIZE
5807072be85SIrina Sokolova   ierr = MatConvert_SeqBAIJ_SeqBAIJMKL(A,MATSEQBAIJMKL,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
5817072be85SIrina Sokolova #else
5827072be85SIrina Sokolova   ierr = PetscInfo(A,"MKL baij routines are not supported for used version of MKL. Using PETSc default routines. \n Please use version of MKL 11.3 and higher. \n");
5837072be85SIrina Sokolova #endif
5847072be85SIrina Sokolova   PetscFunctionReturn(0);
5857072be85SIrina Sokolova }
586