Actual source code: aijmatlab.c

  1: /* 
  2:         Provides an interface for the Matlab engine sparse solver

  4: */
 5:  #include src/mat/impls/aij/seq/aij.h

  7: #include "engine.h"   /* Matlab include file */
  8: #include "mex.h"      /* Matlab include file */

 10: typedef struct {
 11:   PetscErrorCode (*MatDuplicate)(Mat,MatDuplicateOption,Mat*);
 12:   PetscErrorCode (*MatView)(Mat,PetscViewer);
 13:   PetscErrorCode (*MatLUFactorSymbolic)(Mat,IS,IS,MatFactorInfo*,Mat*);
 14:   PetscErrorCode (*MatILUDTFactor)(Mat,MatFactorInfo*,IS,IS,Mat*);
 15:   PetscErrorCode (*MatDestroy)(Mat);
 16: } Mat_Matlab;


 22: PetscErrorCode MatMatlabEnginePut_Matlab(PetscObject obj,void *mengine)
 23: {
 25:   Mat         B = (Mat)obj;
 26:   mxArray     *mat;
 27:   Mat_SeqAIJ  *aij = (Mat_SeqAIJ*)B->data;

 30:   mat  = mxCreateSparse(B->n,B->m,aij->nz,mxREAL);
 31:   PetscMemcpy(mxGetPr(mat),aij->a,aij->nz*sizeof(PetscScalar));
 32:   /* Matlab stores by column, not row so we pass in the transpose of the matrix */
 33:   PetscMemcpy(mxGetIr(mat),aij->j,aij->nz*sizeof(int));
 34:   PetscMemcpy(mxGetJc(mat),aij->i,(B->m+1)*sizeof(int));

 36:   /* Matlab indices start at 0 for sparse (what a surprise) */
 37: 
 38:   PetscObjectName(obj);
 39:   engPutVariable((Engine *)mengine,obj->name,mat);
 40:   return(0);
 41: }

 47: PetscErrorCode MatMatlabEngineGet_Matlab(PetscObject obj,void *mengine)
 48: {
 50:   int        ii;
 51:   Mat        mat = (Mat)obj;
 52:   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
 53:   mxArray    *mmat;

 56:   PetscFree(aij->a);

 58:   mmat = engGetVariable((Engine *)mengine,obj->name);

 60:   aij->nz           = (mxGetJc(mmat))[mat->m];
 61:   PetscMalloc(((size_t) aij->nz)*(sizeof(int)+sizeof(PetscScalar))+(mat->m+1)*sizeof(int),&aij->a);
 62:   aij->j            = (int*)(aij->a + aij->nz);
 63:   aij->i            = aij->j + aij->nz;
 64:   aij->singlemalloc = PETSC_TRUE;
 65:   aij->freedata     = PETSC_TRUE;

 67:   PetscMemcpy(aij->a,mxGetPr(mmat),aij->nz*sizeof(PetscScalar));
 68:   /* Matlab stores by column, not row so we pass in the transpose of the matrix */
 69:   PetscMemcpy(aij->j,mxGetIr(mmat),aij->nz*sizeof(int));
 70:   PetscMemcpy(aij->i,mxGetJc(mmat),(mat->m+1)*sizeof(int));

 72:   for (ii=0; ii<mat->m; ii++) {
 73:     aij->ilen[ii] = aij->imax[ii] = aij->i[ii+1] - aij->i[ii];
 74:   }

 76:   MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);
 77:   MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);

 79:   return(0);
 80: }

 86: PetscErrorCode MatConvert_Matlab_SeqAIJ(Mat A,const MatType type,Mat *newmat)
 87: {
 89:   Mat            B=*newmat;
 90:   Mat_Matlab    *lu=(Mat_Matlab*)A->spptr;

 93:   if (B != A) {
 94:     MatDuplicate(A,MAT_COPY_VALUES,&B);
 95:   }
 96:   B->ops->duplicate        = lu->MatDuplicate;
 97:   B->ops->view             = lu->MatView;
 98:   B->ops->lufactorsymbolic = lu->MatLUFactorSymbolic;
 99:   B->ops->iludtfactor      = lu->MatILUDTFactor;
100:   B->ops->destroy          = lu->MatDestroy;
101: 
102:   PetscFree(lu);

104:   PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_matlab_C","",PETSC_NULL);
105:   PetscObjectComposeFunction((PetscObject)B,"MatConvert_matlab_seqaij_C","",PETSC_NULL);
106:   PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C","",PETSC_NULL);
107:   PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C","",PETSC_NULL);

109:   PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
110:   *newmat = B;
111:   return(0);
112: }

117: PetscErrorCode MatDestroy_Matlab(Mat A)
118: {

122:   MatConvert_Matlab_SeqAIJ(A,MATSEQAIJ,&A);
123:   (*A->ops->destroy)(A);
124:   return(0);
125: }

129: PetscErrorCode MatSolve_Matlab(Mat A,Vec b,Vec x)
130: {
132:   char            *_A,*_b,*_x;

135:   /* make sure objects have names; use default if not */
136:   PetscObjectName((PetscObject)b);
137:   PetscObjectName((PetscObject)x);

139:   PetscObjectGetName((PetscObject)A,&_A);
140:   PetscObjectGetName((PetscObject)b,&_b);
141:   PetscObjectGetName((PetscObject)x,&_x);
142:   PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(A->comm),(PetscObject)b);
143:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"%s = u%s\\(l%s\\(p%s*%s));",_x,_A,_A,_A,_b);
144:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"%s = 0;",_b);
145:   /* PetscMatlabEnginePrintOutput(PETSC_MATLAB_ENGINE_(A->comm),stdout);  */
146:   PetscMatlabEngineGet(PETSC_MATLAB_ENGINE_(A->comm),(PetscObject)x);
147:   return(0);
148: }

152: PetscErrorCode MatLUFactorNumeric_Matlab(Mat A,Mat *F)
153: {
154:   Mat_SeqAIJ      *f = (Mat_SeqAIJ*)(*F)->data;
156:   size_t          len;
157:   char            *_A,*name;

160:   PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(A->comm),(PetscObject)A);
161:   _A   = A->name;
162:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"[l_%s,u_%s,p_%s] = lu(%s',%g);",_A,_A,_A,_A,f->lu_dtcol);
163:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"%s = 0;",_A);
164:   PetscStrlen(_A,&len);
165:   PetscMalloc((len+2)*sizeof(char),&name);
166:   sprintf(name,"_%s",_A);
167:   PetscObjectSetName((PetscObject)*F,name);
168:   PetscFree(name);
169:   return(0);
170: }

174: PetscErrorCode MatLUFactorSymbolic_Matlab(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F)
175: {
177:   Mat_SeqAIJ *f;

180:   if (A->N != A->M) SETERRQ(PETSC_ERR_ARG_SIZ,"matrix must be square");
181:   MatCreate(A->comm,A->m,A->n,A->m,A->n,F);
182:   MatSetType(*F,A->type_name);
183:   MatSeqAIJSetPreallocation(*F,0,PETSC_NULL);
184:   (*F)->ops->solve           = MatSolve_Matlab;
185:   (*F)->ops->lufactornumeric = MatLUFactorNumeric_Matlab;
186:   (*F)->factor               = FACTOR_LU;
187:   f                          = (Mat_SeqAIJ*)(*F)->data;
188:   f->lu_dtcol = info->dtcol;
189:   return(0);
190: }

192: /* ---------------------------------------------------------------------------------*/
195: PetscErrorCode MatSolve_Matlab_QR(Mat A,Vec b,Vec x)
196: {
198:   char            *_A,*_b,*_x;

201:   /* make sure objects have names; use default if not */
202:   PetscObjectName((PetscObject)b);
203:   PetscObjectName((PetscObject)x);

205:   PetscObjectGetName((PetscObject)A,&_A);
206:   PetscObjectGetName((PetscObject)b,&_b);
207:   PetscObjectGetName((PetscObject)x,&_x);
208:   PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(A->comm),(PetscObject)b);
209:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"%s = r%s\\(r%s'\\(%s*%s));",_x,_A,_A,_A+1,_b);
210:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"%s = 0;",_b);
211:   /* PetscMatlabEnginePrintOutput(PETSC_MATLAB_ENGINE_(A->comm),stdout);  */
212:   PetscMatlabEngineGet(PETSC_MATLAB_ENGINE_(A->comm),(PetscObject)x);
213:   return(0);
214: }

218: PetscErrorCode MatLUFactorNumeric_Matlab_QR(Mat A,Mat *F)
219: {
221:   size_t          len;
222:   char            *_A,*name;

225:   PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(A->comm),(PetscObject)A);
226:   _A   = A->name;
227:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"r_%s = qr(%s');",_A,_A);
228:   PetscStrlen(_A,&len);
229:   PetscMalloc((len+2)*sizeof(char),&name);
230:   sprintf(name,"_%s",_A);
231:   PetscObjectSetName((PetscObject)*F,name);
232:   PetscFree(name);
233:   return(0);
234: }

238: PetscErrorCode MatLUFactorSymbolic_Matlab_QR(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F)
239: {

243:   if (A->N != A->M) SETERRQ(PETSC_ERR_ARG_SIZ,"matrix must be square");
244:   MatCreate(A->comm,A->m,A->n,A->m,A->n,F);
245:   MatSetType(*F,A->type_name);
246:   MatSeqAIJSetPreallocation(*F,0,PETSC_NULL);
247:   (*F)->ops->solve           = MatSolve_Matlab_QR;
248:   (*F)->ops->lufactornumeric = MatLUFactorNumeric_Matlab_QR;
249:   (*F)->factor               = FACTOR_LU;
250:   (*F)->assembled            = PETSC_TRUE;  /* required by -ksp_view */

252:   return(0);
253: }

255: /* --------------------------------------------------------------------------------*/
258: PetscErrorCode MatILUDTFactor_Matlab(Mat A,MatFactorInfo *info,IS isrow,IS iscol,Mat *F)
259: {
261:   size_t     len;
262:   char       *_A,*name;

265:   if (info->dt == PETSC_DEFAULT)      info->dt      = .005;
266:   if (info->dtcol == PETSC_DEFAULT)   info->dtcol   = .01;
267:   if (A->N != A->M) SETERRQ(PETSC_ERR_ARG_SIZ,"matrix must be square");
268:   MatCreate(A->comm,A->m,A->n,A->m,A->n,F);
269:   MatSetType(*F,A->type_name);
270:   MatSeqAIJSetPreallocation(*F,0,PETSC_NULL);
271:   (*F)->ops->solve           = MatSolve_Matlab;
272:   (*F)->factor               = FACTOR_LU;
273:   PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(A->comm),(PetscObject)A);
274:   _A   = A->name;
275:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"info_%s = struct('droptol',%g,'thresh',%g);",_A,info->dt,info->dtcol);
276:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"[l_%s,u_%s,p_%s] = luinc(%s',info_%s);",_A,_A,_A,_A,_A);
277:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"%s = 0;",_A);

279:   PetscStrlen(_A,&len);
280:   PetscMalloc((len+2)*sizeof(char),&name);
281:   sprintf(name,"_%s",_A);
282:   PetscObjectSetName((PetscObject)*F,name);
283:   PetscFree(name);
284:   return(0);
285: }

289: PetscErrorCode MatFactorInfo_Matlab(Mat A,PetscViewer viewer)
290: {
292: 
294:   PetscViewerASCIIPrintf(viewer,"Matlab run parameters:  -- not written yet!\n");
295:   return(0);
296: }

300: PetscErrorCode MatView_Matlab(Mat A,PetscViewer viewer) {
301:   PetscErrorCode    ierr;
302:   PetscTruth        iascii;
303:   PetscViewerFormat format;
304:   Mat_Matlab        *lu=(Mat_Matlab*)(A->spptr);

307:   (*lu->MatView)(A,viewer);
308:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
309:   if (iascii) {
310:     PetscViewerGetFormat(viewer,&format);
311:     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
312:       MatFactorInfo_Matlab(A,viewer);
313:     }
314:   }
315:   return(0);
316: }

320: PetscErrorCode MatDuplicate_Matlab(Mat A, MatDuplicateOption op, Mat *M) {
322:   Mat_Matlab *lu=(Mat_Matlab*)A->spptr;

325:   (*lu->MatDuplicate)(A,op,M);
326:   PetscMemcpy((*M)->spptr,lu,sizeof(Mat_Matlab));
327:   return(0);
328: }

333: PetscErrorCode MatConvert_SeqAIJ_Matlab(Mat A,const MatType type,Mat *newmat)
334: {
335:   /* This routine is only called to convert to MATMATLAB */
336:   /* from MATSEQAIJ, so we will ignore 'MatType type'. */
338:   Mat            B=*newmat;
339:   Mat_Matlab     *lu;
340:   PetscTruth     qr;

343:   if (B != A) {
344:     MatDuplicate(A,MAT_COPY_VALUES,&B);
345:   }

347:   PetscNew(Mat_Matlab,&lu);
348:   lu->MatDuplicate         = A->ops->duplicate;
349:   lu->MatView              = A->ops->view;
350:   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
351:   lu->MatILUDTFactor       = A->ops->iludtfactor;
352:   lu->MatDestroy           = A->ops->destroy;

354:   B->spptr                 = (void*)lu;
355:   B->ops->duplicate        = MatDuplicate_Matlab;
356:   B->ops->view             = MatView_Matlab;
357:   B->ops->lufactorsymbolic = MatLUFactorSymbolic_Matlab;
358:   B->ops->iludtfactor      = MatILUDTFactor_Matlab;
359:   B->ops->destroy          = MatDestroy_Matlab;

361:   PetscOptionsHasName(A->prefix,"-mat_matlab_qr",&qr);
362:   if (qr) {
363:     B->ops->lufactorsymbolic = MatLUFactorSymbolic_Matlab_QR;
364:     PetscLogInfo(0,"Using Matlab QR with iterative refinement for LU factorization and solves");
365:   } else {
366:     PetscLogInfo(0,"Using Matlab for LU factorizations and solves.");
367:   }
368:   PetscLogInfo(0,"Using Matlab for ILUDT factorizations and solves.");

370:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_matlab_C",
371:                                            "MatConvert_SeqAIJ_Matlab",MatConvert_SeqAIJ_Matlab);
372:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_matlab_seqaij_C",
373:                                            "MatConvert_Matlab_SeqAIJ",MatConvert_Matlab_SeqAIJ);
374:   PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEnginePut_C",
375:                                            "MatMatlabEnginePut_Matlab",MatMatlabEnginePut_Matlab);
376:   PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEngineGet_C",
377:                                            "MatMatlabEngineGet_Matlab",MatMatlabEngineGet_Matlab);
378:   PetscObjectChangeTypeName((PetscObject)B,MATMATLAB);
379:   *newmat = B;
380:   return(0);
381: }

384: /*MC
385:   MATMATLAB - MATMATLAB = "matlab" - A matrix type providing direct solvers (LU and QR) and drop tolerance
386:   based ILU factorization (ILUDT) for sequential matrices via the external package Matlab.

388:   If Matlab is instaled (see the manual for
389:   instructions on how to declare the existence of external packages),
390:   a matrix type can be constructed which invokes Matlab solvers.
391:   After calling MatCreate(...,A), simply call MatSetType(A,MATMATLAB).
392:   This matrix type is only supported for double precision real.

394:   This matrix inherits from MATSEQAIJ.  As a result, MatSeqAIJSetPreallocation is 
395:   supported for this matrix type.  One can also call MatConvert for an inplace conversion to or from 
396:   the MATSEQAIJ type without data copy.

398:   Options Database Keys:
399: + -mat_type matlab - sets the matrix type to "matlab" during a call to MatSetFromOptions()
400: - -mat_matlab_qr   - sets the direct solver to be QR instead of LU

402:   Level: beginner

404: .seealso: PCLU
405: M*/

410: PetscErrorCode MatCreate_Matlab(Mat A)
411: {

415:   PetscObjectChangeTypeName((PetscObject)A,MATMATLAB);
416:   MatSetType(A,MATSEQAIJ);
417:   MatConvert_SeqAIJ_Matlab(A,MATMATLAB,&A);
418:   return(0);
419: }