Date: 2013-07-02T14:41:46+00:00

Actual source code: aijmatlab.c
petsc-3.4.2 2013-07-02

      2: /*
      3:         Provides an interface for the MATLAB engine sparse solver

      5: */
      6: #include <../src/mat/impls/aij/seq/aij.h>
      7: #include <petscmatlab.h>
      8: #include <engine.h>   /* MATLAB include file */
      9: #include <mex.h>      /* MATLAB include file */

     13: PETSC_EXTERN mxArray *MatSeqAIJToMatlab(Mat B)
     14: {
     16:   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)B->data;
     17:   mwIndex        *ii,*jj;
     18:   mxArray        *mat;
     19:   PetscInt       i;

     22:   mat  = mxCreateSparse(B->cmap->n,B->rmap->n,aij->nz,mxREAL);
     23:   PetscMemcpy(mxGetPr(mat),aij->a,aij->nz*sizeof(PetscScalar));
     24:   /* MATLAB stores by column, not row so we pass in the transpose of the matrix */
     25:   jj = mxGetIr(mat);
     26:   for (i=0; i<aij->nz; i++) jj[i] = aij->j[i];
     27:   ii = mxGetJc(mat);
     28:   for (i=0; i<B->rmap->n+1; i++) ii[i] = aij->i[i];
     29:   PetscFunctionReturn(mat);
     30: }

     34: PETSC_EXTERN PetscErrorCode MatlabEnginePut_SeqAIJ(PetscObject obj,void *mengine)
     35: {
     37:   mxArray        *mat;

     40:   mat  = MatSeqAIJToMatlab((Mat)obj);if (!mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot create MATLAB matrix");
     41:   PetscObjectName(obj);
     42:   engPutVariable((Engine*)mengine,obj->name,mat);
     43:   return(0);
     44: }

     48: /*@C
     49:     MatSeqAIJFromMatlab - Given a MATLAB sparse matrix, fills a SeqAIJ matrix with its transpose.

     51:    Not Collective

     53:    Input Parameters:
     54: +     mmat - a MATLAB sparse matris
     55: -     mat - a already created MATSEQAIJ

     57:   Level: intermediate

     59: @*/
     60: PETSC_EXTERN PetscErrorCode MatSeqAIJFromMatlab(mxArray *mmat,Mat mat)
     61: {
     63:   PetscInt       nz,n,m,*i,*j,k;
     64:   mwIndex        nnz,nn,nm,*ii,*jj;
     65:   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;

     68:   nn  = mxGetN(mmat);   /* rows of transpose of matrix */
     69:   nm  = mxGetM(mmat);
     70:   nnz = (mxGetJc(mmat))[nn];
     71:   ii  = mxGetJc(mmat);
     72:   jj  = mxGetIr(mmat);
     73:   n   = (PetscInt) nn;
     74:   m   = (PetscInt) nm;
     75:   nz  = (PetscInt) nnz;

     77:   if (mat->rmap->n < 0 && mat->cmap->n < 0) {
     78:     /* matrix has not yet had its size set */
     79:     MatSetSizes(mat,n,m,PETSC_DETERMINE,PETSC_DETERMINE);
     80:     MatSetUp(mat);
     81:   } else {
     82:     if (mat->rmap->n != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot change size of PETSc matrix %D to %D",mat->rmap->n,n);
     83:     if (mat->cmap->n != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot change size of PETSc matrix %D to %D",mat->cmap->n,m);
     84:   }
     85:   if (nz != aij->nz) {
     86:     /* number of nonzeros in matrix has changed, so need new data structure */
     87:     MatSeqXAIJFreeAIJ(mat,&aij->a,&aij->j,&aij->i);
     88:     aij->nz = nz;
     89:     PetscMalloc3(aij->nz,PetscScalar,&aij->a,aij->nz,PetscInt,&aij->j,mat->rmap->n+1,PetscInt,&aij->i);

     91:     aij->singlemalloc = PETSC_TRUE;
     92:   }

     94:   PetscMemcpy(aij->a,mxGetPr(mmat),aij->nz*sizeof(PetscScalar));
     95:   /* MATLAB stores by column, not row so we pass in the transpose of the matrix */
     96:   i = aij->i;
     97:   for (k=0; k<n+1; k++) i[k] = (PetscInt) ii[k];
     98:   j = aij->j;
     99:   for (k=0; k<nz; k++) j[k] = (PetscInt) jj[k];

    101:   for (k=0; k<mat->rmap->n; k++) aij->ilen[k] = aij->imax[k] = aij->i[k+1] - aij->i[k];

    103:   MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);
    104:   MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);
    105:   return(0);
    106: }

    110: PetscErrorCode  MatlabEngineGet_SeqAIJ(PetscObject obj,void *mengine)
    111: {
    113:   Mat            mat = (Mat)obj;
    114:   mxArray        *mmat;

    117:   mmat = engGetVariable((Engine*)mengine,obj->name);
    118:   MatSeqAIJFromMatlab(mmat,mat);
    119:   return(0);
    120: }

    124: PetscErrorCode MatSolve_Matlab(Mat A,Vec b,Vec x)
    125: {
    127:   const char     *_A,*_b,*_x;

    130:   /* make sure objects have names; use default if not */
    131:   PetscObjectName((PetscObject)b);
    132:   PetscObjectName((PetscObject)x);

    134:   PetscObjectGetName((PetscObject)A,&_A);
    135:   PetscObjectGetName((PetscObject)b,&_b);
    136:   PetscObjectGetName((PetscObject)x,&_x);
    137:   PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),(PetscObject)b);
    138:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),"%s = u%s\\(l%s\\(p%s*%s));",_x,_A,_A,_A,_b);
    139:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),"%s = 0;",_b);
    140:   /* PetscMatlabEnginePrintOutput(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),stdout);  */
    141:   PetscMatlabEngineGet(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),(PetscObject)x);
    142:   return(0);
    143: }

    147: PetscErrorCode MatLUFactorNumeric_Matlab(Mat F,Mat A,const MatFactorInfo *info)
    148: {
    150:   size_t         len;
    151:   char           *_A,*name;
    152:   PetscReal      dtcol = info->dtcol;

    155:   if (F->factortype == MAT_FACTOR_ILU || info->dt > 0) {
    156:     if (info->dtcol == PETSC_DEFAULT) dtcol = .01;
    157:     F->ops->solve = MatSolve_Matlab;
    158:     F->factortype = MAT_FACTOR_LU;

    160:     PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),(PetscObject)A);
    161:     _A   = ((PetscObject)A)->name;
    162:     PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),"info_%s = struct('droptol',%g,'thresh',%g);",_A,info->dt,dtcol);
    163:     PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),"[l_%s,u_%s,p_%s] = luinc(%s',info_%s);",_A,_A,_A,_A,_A);
    164:     PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),"%s = 0;",_A);

    166:     PetscStrlen(_A,&len);
    167:     PetscMalloc((len+2)*sizeof(char),&name);
    168:     sprintf(name,"_%s",_A);
    169:     PetscObjectSetName((PetscObject)F,name);
    170:     PetscFree(name);
    171:   } else {
    172:     PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),(PetscObject)A);
    173:     _A   = ((PetscObject)A)->name;
    174:     PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),"[l_%s,u_%s,p_%s] = lu(%s',%g);",_A,_A,_A,_A,dtcol);
    175:     PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),"%s = 0;",_A);
    176:     PetscStrlen(_A,&len);
    177:     PetscMalloc((len+2)*sizeof(char),&name);
    178:     sprintf(name,"_%s",_A);
    179:     PetscObjectSetName((PetscObject)F,name);
    180:     PetscFree(name);

    182:     F->ops->solve = MatSolve_Matlab;
    183:   }
    184:   return(0);
    185: }

    189: PetscErrorCode MatLUFactorSymbolic_Matlab(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
    190: {
    192:   if (A->cmap->N != A->rmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"matrix must be square");
    193:   F->ops->lufactornumeric = MatLUFactorNumeric_Matlab;
    194:   F->assembled            = PETSC_TRUE;
    195:   return(0);
    196: }

    200: PetscErrorCode MatFactorGetSolverPackage_seqaij_matlab(Mat A,const MatSolverPackage *type)
    201: {
    203:   *type = MATSOLVERMATLAB;
    204:   return(0);
    205: }

    209: PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_matlab(Mat A,MatFactorType ftype,Mat *F)
    210: {

    214:   if (A->cmap->N != A->rmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"matrix must be square");
    215:   MatCreate(PetscObjectComm((PetscObject)A),F);
    216:   MatSetSizes(*F,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);
    217:   MatSetType(*F,((PetscObject)A)->type_name);
    218:   MatSeqAIJSetPreallocation(*F,0,NULL);
    219:   (*F)->ops->lufactorsymbolic  = MatLUFactorSymbolic_Matlab;
    220:   (*F)->ops->ilufactorsymbolic = MatLUFactorSymbolic_Matlab;

    222:   PetscObjectComposeFunction((PetscObject)(*F),"MatFactorGetSolverPackage_C",MatFactorGetSolverPackage_seqaij_matlab);

    224:   (*F)->factortype = ftype;
    225:   return(0);
    226: }

    228: /* --------------------------------------------------------------------------------*/

    232: PetscErrorCode MatFactorInfo_Matlab(Mat A,PetscViewer viewer)
    233: {

    237:   PetscViewerASCIIPrintf(viewer,"MATLAB run parameters:  -- not written yet!\n");
    238:   return(0);
    239: }

    243: PetscErrorCode MatView_Matlab(Mat A,PetscViewer viewer)
    244: {
    245:   PetscErrorCode    ierr;
    246:   PetscBool         iascii;
    247:   PetscViewerFormat format;

    250:   MatView_SeqAIJ(A,viewer);
    251:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    252:   if (iascii) {
    253:     PetscViewerGetFormat(viewer,&format);
    254:     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
    255:       MatFactorInfo_Matlab(A,viewer);
    256:     }
    257:   }
    258:   return(0);
    259: }

    262: /*MC
    263:   MATSOLVERMATLAB - "matlab" - Providing direct solvers (LU and QR) and drop tolerance
    264:   based ILU factorization (ILUDT) for sequential matrices via the external package MATLAB.

    267:   Works with MATSEQAIJ matrices.

    269:   Options Database Keys:
    270: . -pc_factor_mat_solver_type matlab - selects MATLAB to do the sparse factorization

    273:   Level: beginner

    275: .seealso: PCLU

    277: .seealso: PCFactorSetMatSolverPackage(), MatSolverPackage
    278: M*/