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: }