Actual source code: aijmatlab.c

petsc-3.14.6 2021-03-30
Report Typos and Errors

  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 */

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

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

 30: PETSC_EXTERN PetscErrorCode MatlabEnginePut_SeqAIJ(PetscObject obj,void *mengine)
 31: {
 33:   mxArray        *mat;

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

 42: PETSC_EXTERN PetscErrorCode MatSeqAIJFromMatlab(mxArray *mmat,Mat mat)
 43: {
 45:   PetscInt       nz,n,m,*i,*j,k;
 46:   mwIndex        nnz,nn,nm,*ii,*jj;
 47:   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;

 50:   nn  = mxGetN(mmat);   /* rows of transpose of matrix */
 51:   nm  = mxGetM(mmat);
 52:   nnz = (mxGetJc(mmat))[nn];
 53:   ii  = mxGetJc(mmat);
 54:   jj  = mxGetIr(mmat);
 55:   n   = (PetscInt) nn;
 56:   m   = (PetscInt) nm;
 57:   nz  = (PetscInt) nnz;

 59:   if (mat->rmap->n < 0 && mat->cmap->n < 0) {
 60:     /* matrix has not yet had its size set */
 61:     MatSetSizes(mat,n,m,PETSC_DETERMINE,PETSC_DETERMINE);
 62:     MatSetUp(mat);
 63:   } else {
 64:     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);
 65:     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);
 66:   }
 67:   if (nz != aij->nz) {
 68:     /* number of nonzeros in matrix has changed, so need new data structure */
 69:     MatSeqXAIJFreeAIJ(mat,&aij->a,&aij->j,&aij->i);
 70:     aij->nz = nz;
 71:     PetscMalloc3(aij->nz,&aij->a,aij->nz,&aij->j,mat->rmap->n+1,&aij->i);

 73:     aij->singlemalloc = PETSC_TRUE;
 74:   }

 76:   PetscArraycpy(aij->a,mxGetPr(mmat),aij->nz);
 77:   /* MATLAB stores by column, not row so we pass in the transpose of the matrix */
 78:   i = aij->i;
 79:   for (k=0; k<n+1; k++) i[k] = (PetscInt) ii[k];
 80:   j = aij->j;
 81:   for (k=0; k<nz; k++) j[k] = (PetscInt) jj[k];

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

 85:   mat->nonzerostate++; /* since the nonzero structure can change anytime force the Inode information to always be rebuilt */
 86:   MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);
 87:   MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);
 88:   return(0);
 89: }

 91: PETSC_EXTERN PetscErrorCode  MatlabEngineGet_SeqAIJ(PetscObject obj,void *mengine)
 92: {
 94:   Mat            mat = (Mat)obj;
 95:   mxArray        *mmat;

 98:   mmat = engGetVariable((Engine*)mengine,obj->name);
 99:   MatSeqAIJFromMatlab(mmat,mat);
100:   return(0);
101: }

103: PetscErrorCode MatSolve_Matlab(Mat A,Vec b,Vec x)
104: {
106:   const char     *_A,*_b,*_x;

109:   /* make sure objects have names; use default if not */
110:   PetscObjectName((PetscObject)b);
111:   PetscObjectName((PetscObject)x);

113:   PetscObjectGetName((PetscObject)A,&_A);
114:   PetscObjectGetName((PetscObject)b,&_b);
115:   PetscObjectGetName((PetscObject)x,&_x);
116:   PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),(PetscObject)b);
117:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),"%s = u%s\\(l%s\\(p%s*%s));",_x,_A,_A,_A,_b);
118:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),"%s = 0;",_b);
119:   /* PetscMatlabEnginePrintOutput(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),stdout);  */
120:   PetscMatlabEngineGet(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),(PetscObject)x);
121:   return(0);
122: }

124: PetscErrorCode MatLUFactorNumeric_Matlab(Mat F,Mat A,const MatFactorInfo *info)
125: {
127:   size_t         len;
128:   char           *_A,*name;
129:   PetscReal      dtcol = info->dtcol;

132:   if (F->factortype == MAT_FACTOR_ILU || info->dt > 0) {
133:     /* the ILU form is not currently registered */
134:     if (info->dtcol == PETSC_DEFAULT) dtcol = .01;
135:     F->ops->solve = MatSolve_Matlab;
136:     F->factortype = MAT_FACTOR_LU;

138:     PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),(PetscObject)A);
139:     _A   = ((PetscObject)A)->name;
140:     PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),"info_%s = struct('droptol',%g,'thresh',%g);",_A,info->dt,dtcol);
141:     PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),"[l_%s,u_%s,p_%s] = luinc(%s',info_%s);",_A,_A,_A,_A,_A);
142:     PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),"%s = 0;",_A);

144:     PetscStrlen(_A,&len);
145:     PetscMalloc1(len+2,&name);
146:     sprintf(name,"_%s",_A);
147:     PetscObjectSetName((PetscObject)F,name);
148:     PetscFree(name);
149:   } else {
150:     PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),(PetscObject)A);
151:     _A   = ((PetscObject)A)->name;
152:     PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),"[l_%s,u_%s,p_%s] = lu(%s',%g);",_A,_A,_A,_A,dtcol);
153:     PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),"%s = 0;",_A);
154:     PetscStrlen(_A,&len);
155:     PetscMalloc1(len+2,&name);
156:     sprintf(name,"_%s",_A);
157:     PetscObjectSetName((PetscObject)F,name);
158:     PetscFree(name);

160:     F->ops->solve = MatSolve_Matlab;
161:   }
162:   return(0);
163: }

165: PetscErrorCode MatLUFactorSymbolic_Matlab(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
166: {
168:   if (A->cmap->N != A->rmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"matrix must be square");
169:   F->ops->lufactornumeric = MatLUFactorNumeric_Matlab;
170:   F->assembled            = PETSC_TRUE;
171:   return(0);
172: }

174: PetscErrorCode MatFactorGetSolverType_seqaij_matlab(Mat A,MatSolverType *type)
175: {
177:   *type = MATSOLVERMATLAB;
178:   return(0);
179: }

181: PetscErrorCode MatDestroy_matlab(Mat A)
182: {
184:   const char     *_A;

187:   PetscObjectGetName((PetscObject)A,&_A);
188:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(PetscObjectComm((PetscObject)A)),"delete %s l_%s u_%s;",_A,_A,_A);
189:   return(0);
190: }

192: PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_matlab(Mat A,MatFactorType ftype,Mat *F)
193: {

197:   if (A->cmap->N != A->rmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"matrix must be square");
198:   MatCreate(PetscObjectComm((PetscObject)A),F);
199:   MatSetSizes(*F,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);
200:   PetscStrallocpy("matlab",&((PetscObject)*F)->type_name);
201:   MatSetUp(*F);

203:   (*F)->ops->destroy           = MatDestroy_matlab;
204:   (*F)->ops->getinfo           = MatGetInfo_External;
205:   (*F)->ops->lufactorsymbolic  = MatLUFactorSymbolic_Matlab;
206:   (*F)->ops->ilufactorsymbolic = MatLUFactorSymbolic_Matlab;

208:   PetscObjectComposeFunction((PetscObject)(*F),"MatFactorGetSolverType_C",MatFactorGetSolverType_seqaij_matlab);

210:   (*F)->factortype = ftype;
211:   PetscFree((*F)->solvertype);
212:   PetscStrallocpy(MATSOLVERMATLAB,&(*F)->solvertype);
213:   return(0);
214: }


217: PETSC_EXTERN PetscErrorCode MatSolverTypeRegister_Matlab(void)
218: {

222:   MatSolverTypeRegister(MATSOLVERMATLAB,MATSEQAIJ,        MAT_FACTOR_LU,MatGetFactor_seqaij_matlab);
223:   return(0);
224: }

226: /* --------------------------------------------------------------------------------*/

228: PetscErrorCode MatView_Info_Matlab(Mat A,PetscViewer viewer)
229: {

233:   PetscViewerASCIIPrintf(viewer,"MATLAB run parameters:  -- not written yet!\n");
234:   return(0);
235: }

237: PetscErrorCode MatView_Matlab(Mat A,PetscViewer viewer)
238: {
239:   PetscErrorCode    ierr;
240:   PetscBool         iascii;
241:   PetscViewerFormat format;

244:   MatView_SeqAIJ(A,viewer);
245:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
246:   if (iascii) {
247:     PetscViewerGetFormat(viewer,&format);
248:     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
249:       MatView_Info_Matlab(A,viewer);
250:     }
251:   }
252:   return(0);
253: }


256: /*MC
257:   MATSOLVERMATLAB - "matlab" - Providing direct solver LU for sequential aij matrix via the external package MATLAB.


260:   Works with MATSEQAIJ matrices.

262:   Options Database Keys:
263: . -pc_factor_mat_solver_type matlab - selects MATLAB to do the sparse factorization

265:   Notes:
266:     You must ./configure with the options --with-matlab --with-matlab-engine

268:   Level: beginner

270: .seealso: PCLU

272: .seealso: PCFactorSetMatSolverType(), MatSolverType
273: M*/