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