Actual source code: aijmatlab.c

  1: /*$Id: aijmatlab.c,v 1.12 2001/08/06 21:15:14 bsmith Exp $*/

  3: /* 
  4:         Provides an interface for the Matlab engine sparse solver

  6: */
 7:  #include src/mat/impls/aij/seq/aij.h

  9: #include "engine.h"   /* Matlab include file */
 10: #include "mex.h"      /* Matlab include file */

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


 21: EXTERN_C_BEGIN
 24: int MatMatlabEnginePut_Matlab(PetscObject obj,void *mengine)
 25: {
 26:   int         ierr;
 27:   Mat         B = (Mat)obj;
 28:   mxArray     *mat;
 29:   Mat_SeqAIJ  *aij = (Mat_SeqAIJ*)B->data;

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

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

 46: EXTERN_C_BEGIN
 49: int MatMatlabEngineGet_Matlab(PetscObject obj,void *mengine)
 50: {
 51:   int        ierr,ii;
 52:   Mat        mat = (Mat)obj;
 53:   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
 54:   mxArray    *mmat;

 57:   PetscFree(aij->a);

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

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

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

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

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

 80:   return(0);
 81: }
 82: EXTERN_C_END

 84: EXTERN_C_BEGIN
 87: int MatConvert_Matlab_SeqAIJ(Mat A,const MatType type,Mat *newmat) {
 88:   int        ierr;
 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:   A->ops->duplicate        = lu->MatDuplicate;
 97:   A->ops->view             = lu->MatView;
 98:   A->ops->lufactorsymbolic = lu->MatLUFactorSymbolic;
 99:   A->ops->iludtfactor      = lu->MatILUDTFactor;
100:   A->ops->destroy          = lu->MatDestroy;
101: 
102:   PetscFree(lu);
103:   PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
104:   *newmat = B;
105:   return(0);
106: }
107: EXTERN_C_END

111: int MatDestroy_Matlab(Mat A) {
112:   int         ierr;

115:   MatConvert_Matlab_SeqAIJ(A,MATSEQAIJ,&A);
116:   (*A->ops->destroy)(A);
117:   return(0);
118: }

122: int MatSolve_Matlab(Mat A,Vec b,Vec x)
123: {
124:   int             ierr;
125:   char            *_A,*_b,*_x;

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

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

145: int MatLUFactorNumeric_Matlab(Mat A,Mat *F)
146: {
147:   Mat_SeqAIJ      *f = (Mat_SeqAIJ*)(*F)->data;
148:   int             ierr,len;
149:   char            *_A,*name;

152:   PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(A->comm),(PetscObject)A);
153:   _A   = A->name;
154:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"[l_%s,u_%s,p_%s] = lu(%s',%g);",_A,_A,_A,_A,f->lu_dtcol);
155:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"%s = 0;",_A);
156:   PetscStrlen(_A,&len);
157:   PetscMalloc((len+2)*sizeof(char),&name);
158:   sprintf(name,"_%s",_A);
159:   PetscObjectSetName((PetscObject)*F,name);
160:   PetscFree(name);
161:   return(0);
162: }

166: int MatLUFactorSymbolic_Matlab(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F)
167: {
168:   int        ierr;
169:   Mat_SeqAIJ *f;

172:   if (A->N != A->M) SETERRQ(PETSC_ERR_ARG_SIZ,"matrix must be square");
173:   MatCreate(A->comm,A->m,A->n,A->m,A->n,F);
174:   MatSetType(*F,A->type_name);
175:   MatSeqAIJSetPreallocation(*F,0,PETSC_NULL);
176:   (*F)->ops->solve           = MatSolve_Matlab;
177:   (*F)->ops->lufactornumeric = MatLUFactorNumeric_Matlab;
178:   (*F)->factor               = FACTOR_LU;
179:   f                          = (Mat_SeqAIJ*)(*F)->data;
180:   f->lu_dtcol = info->dtcol;
181:   return(0);
182: }

184: /* ---------------------------------------------------------------------------------*/
187: int MatSolve_Matlab_QR(Mat A,Vec b,Vec x)
188: {
189:   int             ierr;
190:   char            *_A,*_b,*_x;

193:   /* make sure objects have names; use default if not */
194:   PetscObjectName((PetscObject)b);
195:   PetscObjectName((PetscObject)x);

197:   PetscObjectGetName((PetscObject)A,&_A);
198:   PetscObjectGetName((PetscObject)b,&_b);
199:   PetscObjectGetName((PetscObject)x,&_x);
200:   PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(A->comm),(PetscObject)b);
201:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"%s = r%s\\(r%s'\\(%s*%s));",_x,_A,_A,_A+1,_b);
202:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"%s = 0;",_b);
203:   /* PetscMatlabEnginePrintOutput(PETSC_MATLAB_ENGINE_(A->comm),stdout);  */
204:   PetscMatlabEngineGet(PETSC_MATLAB_ENGINE_(A->comm),(PetscObject)x);
205:   return(0);
206: }

210: int MatLUFactorNumeric_Matlab_QR(Mat A,Mat *F)
211: {
212:   int             ierr,len;
213:   char            *_A,*name;

216:   PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(A->comm),(PetscObject)A);
217:   _A   = A->name;
218:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"r_%s = qr(%s');",_A,_A);
219:   PetscStrlen(_A,&len);
220:   PetscMalloc((len+2)*sizeof(char),&name);
221:   sprintf(name,"_%s",_A);
222:   PetscObjectSetName((PetscObject)*F,name);
223:   PetscFree(name);
224:   return(0);
225: }

229: int MatLUFactorSymbolic_Matlab_QR(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F)
230: {
231:   int  ierr;

234:   if (A->N != A->M) SETERRQ(PETSC_ERR_ARG_SIZ,"matrix must be square");
235:   MatCreate(A->comm,A->m,A->n,A->m,A->n,F);
236:   MatSetType(*F,A->type_name);
237:   MatSeqAIJSetPreallocation(*F,0,PETSC_NULL);
238:   (*F)->ops->solve           = MatSolve_Matlab_QR;
239:   (*F)->ops->lufactornumeric = MatLUFactorNumeric_Matlab_QR;
240:   (*F)->factor               = FACTOR_LU;
241:   (*F)->assembled            = PETSC_TRUE;  /* required by -ksp_view */

243:   return(0);
244: }

246: /* --------------------------------------------------------------------------------*/
249: int MatILUDTFactor_Matlab(Mat A,MatFactorInfo *info,IS isrow,IS iscol,Mat *F)
250: {
251:   int        ierr,len;
252:   char       *_A,*name;

255:   if (info->dt == PETSC_DEFAULT)      info->dt      = .005;
256:   if (info->dtcol == PETSC_DEFAULT)   info->dtcol   = .01;
257:   if (A->N != A->M) SETERRQ(PETSC_ERR_ARG_SIZ,"matrix must be square");
258:   MatCreate(A->comm,A->m,A->n,A->m,A->n,F);
259:   MatSetType(*F,A->type_name);
260:   MatSeqAIJSetPreallocation(*F,0,PETSC_NULL);
261:   (*F)->ops->solve           = MatSolve_Matlab;
262:   (*F)->factor               = FACTOR_LU;
263:   PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(A->comm),(PetscObject)A);
264:   _A   = A->name;
265:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"info_%s = struct('droptol',%g,'thresh',%g);",_A,info->dt,info->dtcol);
266:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"[l_%s,u_%s,p_%s] = luinc(%s',info_%s);",_A,_A,_A,_A,_A);
267:   PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(A->comm),"%s = 0;",_A);

269:   PetscStrlen(_A,&len);
270:   PetscMalloc((len+2)*sizeof(char),&name);
271:   sprintf(name,"_%s",_A);
272:   PetscObjectSetName((PetscObject)*F,name);
273:   PetscFree(name);
274:   return(0);
275: }

279: int MatFactorInfo_Matlab(Mat A,PetscViewer viewer)
280: {
282: 
284:   PetscViewerASCIIPrintf(viewer,"Matlab run parameters:  -- not written yet!\n");
285:   return(0);
286: }

290: int MatView_Matlab(Mat A,PetscViewer viewer) {
291:   int               ierr;
292:   PetscTruth        isascii;
293:   PetscViewerFormat format;
294:   Mat_Matlab        *lu=(Mat_Matlab*)(A->spptr);

297:   (*lu->MatView)(A,viewer);
298:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
299:   if (isascii) {
300:     PetscViewerGetFormat(viewer,&format);
301:     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
302:       MatFactorInfo_Matlab(A,viewer);
303:     }
304:   }
305:   return(0);
306: }

310: int MatDuplicate_Matlab(Mat A, MatDuplicateOption op, Mat *M) {
311:   int        ierr;
312:   Mat_Matlab *lu=(Mat_Matlab*)A->spptr;

315:   (*lu->MatDuplicate)(A,op,M);
316:   PetscMemcpy((*M)->spptr,lu,sizeof(Mat_Matlab));
317:   return(0);
318: }

320: EXTERN_C_BEGIN
323: int MatConvert_SeqAIJ_Matlab(Mat A,const MatType type,Mat *newmat) {
324:   /* This routine is only called to convert to MATMATLAB */
325:   /* from MATSEQAIJ, so we will ignore 'MatType type'. */
326:   int        ierr;
327:   Mat        B=*newmat;
328:   Mat_Matlab *lu;
329:   PetscTruth qr;

332:   if (B != A) {
333:     MatDuplicate(A,MAT_COPY_VALUES,&B);
334:   }

336:   PetscNew(Mat_Matlab,&lu);
337:   lu->MatDuplicate         = A->ops->duplicate;
338:   lu->MatView              = A->ops->view;
339:   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
340:   lu->MatILUDTFactor       = A->ops->iludtfactor;
341:   lu->MatDestroy           = A->ops->destroy;

343:   B->spptr                 = (void*)lu;
344:   B->ops->duplicate        = MatDuplicate_Matlab;
345:   B->ops->view             = MatView_Matlab;
346:   B->ops->lufactorsymbolic = MatLUFactorSymbolic_Matlab;
347:   B->ops->iludtfactor      = MatILUDTFactor_Matlab;
348:   B->ops->destroy          = MatDestroy_Matlab;

350:   PetscOptionsHasName(A->prefix,"-mat_matlab_qr",&qr);
351:   if (qr) {
352:     B->ops->lufactorsymbolic = MatLUFactorSymbolic_Matlab_QR;
353:     PetscLogInfo(0,"Using Matlab QR with iterative refinement for LU factorization and solves");
354:   } else {
355:     PetscLogInfo(0,"Using Matlab for LU factorizations and solves.");
356:   }
357:   PetscLogInfo(0,"Using Matlab for ILUDT factorizations and solves.");

359:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_matlab_C",
360:                                            "MatConvert_SeqAIJ_Matlab",MatConvert_SeqAIJ_Matlab);
361:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_matlab_seqaij_C",
362:                                            "MatConvert_Matlab_SeqAIJ",MatConvert_Matlab_SeqAIJ);
363:   PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEnginePut_C",
364:                                            "MatMatlabEnginePut_Matlab",MatMatlabEnginePut_Matlab);
365:   PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEngineGet_C",
366:                                            "MatMatlabEngineGet_Matlab",MatMatlabEngineGet_Matlab);
367:   PetscObjectChangeTypeName((PetscObject)B,MATMATLAB);
368:   *newmat = B;
369:   return(0);
370: }
371: EXTERN_C_END

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

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

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

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

391:   Level: beginner

393: .seealso: PCLU
394: M*/

396: EXTERN_C_BEGIN
399: int MatCreate_Matlab(Mat A) {

403:   PetscObjectChangeTypeName((PetscObject)A,MATMATLAB);
404:   MatSetType(A,MATSEQAIJ);
405:   MatConvert_SeqAIJ_Matlab(A,MATMATLAB,&A);
406:   return(0);
407: }
408: EXTERN_C_END