xref: /petsc/src/mat/impls/aij/seq/matlab/aijmatlab.c (revision e91c6855ec8eedcfe894fb1dc8d9ee5acd2335f4)
1 #define PETSCMAT_DLL
2 
3 /*
4         Provides an interface for the MATLAB engine sparse solver
5 
6 */
7 #include "../src/mat/impls/aij/seq/aij.h"
8 
9 #include "engine.h"   /* MATLAB include file */
10 #include "mex.h"      /* MATLAB include file */
11 
12 EXTERN_C_BEGIN
13 #undef __FUNCT__
14 #define __FUNCT__ "MatSeqAIJToMatlab"
15 mxArray *MatSeqAIJToMatlab(Mat B)
16 {
17   PetscErrorCode ierr;
18   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)B->data;
19   mwIndex        *ii,*jj;
20   mxArray        *mat;
21   PetscInt       i;
22 
23   PetscFunctionBegin;
24   mat  = mxCreateSparse(B->cmap->n,B->rmap->n,aij->nz,mxREAL);
25   ierr = PetscMemcpy(mxGetPr(mat),aij->a,aij->nz*sizeof(PetscScalar));
26   /* MATLAB stores by column, not row so we pass in the transpose of the matrix */
27   jj = mxGetIr(mat);
28   for (i=0; i<aij->nz; i++) jj[i] = aij->j[i];
29   ii = mxGetJc(mat);
30   for (i=0; i<B->rmap->n+1; i++) ii[i] = aij->i[i];
31 
32   PetscFunctionReturn(mat);
33 }
34 EXTERN_C_END
35 
36 
37 EXTERN_C_BEGIN
38 #undef __FUNCT__
39 #define __FUNCT__ "MatlabEnginePut_SeqAIJ"
40 PetscErrorCode  MatlabEnginePut_SeqAIJ(PetscObject obj,void *mengine)
41 {
42   PetscErrorCode ierr;
43   mxArray        *mat;
44 
45   PetscFunctionBegin;
46   mat = MatSeqAIJToMatlab((Mat)obj);if (!mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot create MATLAB matrix");
47   ierr = PetscObjectName(obj);CHKERRQ(ierr);
48   engPutVariable((Engine *)mengine,obj->name,mat);
49   PetscFunctionReturn(0);
50 }
51 EXTERN_C_END
52 
53 EXTERN_C_BEGIN
54 #undef __FUNCT__
55 #define __FUNCT__ "MatSeqAIJFromMatlab"
56 /*@C
57     MatSeqAIJFromMatlab - Given a MATLAB sparse matrix, fills a SeqAIJ matrix with its transpose.
58 
59    Not Collective
60 
61    Input Parameters:
62 +     mmat - a MATLAB sparse matris
63 -     mat - a already created MATSEQAIJ
64 
65 @*/
66 PetscErrorCode  MatSeqAIJFromMatlab(mxArray *mmat,Mat mat)
67 {
68   PetscErrorCode ierr;
69   PetscInt       nz,n,m,*i,*j,k;
70   mwIndex        nnz,nn,nm,*ii,*jj;
71   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
72 
73   PetscFunctionBegin;
74   nn  = mxGetN(mmat);   /* rows of transpose of matrix */
75   nm  = mxGetM(mmat);
76   nnz = (mxGetJc(mmat))[nn];
77   ii  = mxGetJc(mmat);
78   jj  = mxGetIr(mmat);
79   n   = (PetscInt) nn;
80   m   = (PetscInt) nm;
81   nz  = (PetscInt) nnz;
82 
83   if (mat->rmap->n < 0 && mat->cmap->n < 0) {
84     /* matrix has not yet had its size set */
85     ierr = MatSetSizes(mat,n,m,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
86     ierr = MatPreallocated(mat);CHKERRQ(ierr);
87   } else {
88     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);
89     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);
90   }
91   if (nz != aij->nz) {
92     /* number of nonzeros in matrix has changed, so need new data structure */
93     ierr = MatSeqXAIJFreeAIJ(mat,&aij->a,&aij->j,&aij->i);CHKERRQ(ierr);
94     aij->nz           = nz;
95     ierr  = PetscMalloc3(aij->nz,PetscScalar,&aij->a,aij->nz,PetscInt,&aij->j,mat->rmap->n+1,PetscInt,&aij->i);CHKERRQ(ierr);
96     aij->singlemalloc = PETSC_TRUE;
97   }
98 
99   ierr = PetscMemcpy(aij->a,mxGetPr(mmat),aij->nz*sizeof(PetscScalar));CHKERRQ(ierr);
100   /* MATLAB stores by column, not row so we pass in the transpose of the matrix */
101   i = aij->i;
102   for (k=0; k<n+1; k++) {
103     i[k] = (PetscInt) ii[k];
104   }
105   j = aij->j;
106   for (k=0; k<nz; k++) {
107     j[k] = (PetscInt) jj[k];
108   }
109 
110   for (k=0; k<mat->rmap->n; k++) {
111     aij->ilen[k] = aij->imax[k] = aij->i[k+1] - aij->i[k];
112   }
113 
114   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
115   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
116   PetscFunctionReturn(0);
117 }
118 EXTERN_C_END
119 
120 
121 EXTERN_C_BEGIN
122 #undef __FUNCT__
123 #define __FUNCT__ "MatlabEngineGet_SeqAIJ"
124 PetscErrorCode  MatlabEngineGet_SeqAIJ(PetscObject obj,void *mengine)
125 {
126   PetscErrorCode ierr;
127   Mat            mat = (Mat)obj;
128   mxArray        *mmat;
129 
130   PetscFunctionBegin;
131   mmat = engGetVariable((Engine *)mengine,obj->name);
132   ierr = MatSeqAIJFromMatlab(mmat,mat);CHKERRQ(ierr);
133   PetscFunctionReturn(0);
134 }
135 EXTERN_C_END
136 
137 #undef __FUNCT__
138 #define __FUNCT__ "MatSolve_Matlab"
139 PetscErrorCode MatSolve_Matlab(Mat A,Vec b,Vec x)
140 {
141   PetscErrorCode ierr;
142   const char     *_A,*_b,*_x;
143 
144   PetscFunctionBegin;
145   /* make sure objects have names; use default if not */
146   ierr = PetscObjectName((PetscObject)b);CHKERRQ(ierr);
147   ierr = PetscObjectName((PetscObject)x);CHKERRQ(ierr);
148 
149   ierr = PetscObjectGetName((PetscObject)A,&_A);CHKERRQ(ierr);
150   ierr = PetscObjectGetName((PetscObject)b,&_b);CHKERRQ(ierr);
151   ierr = PetscObjectGetName((PetscObject)x,&_x);CHKERRQ(ierr);
152   ierr = PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),(PetscObject)b);CHKERRQ(ierr);
153   ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"%s = u%s\\(l%s\\(p%s*%s));",_x,_A,_A,_A,_b);CHKERRQ(ierr);
154   ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"%s = 0;",_b);CHKERRQ(ierr);
155   /* ierr = PetscMatlabEnginePrintOutput(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),stdout);CHKERRQ(ierr);  */
156   ierr = PetscMatlabEngineGet(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),(PetscObject)x);CHKERRQ(ierr);
157   PetscFunctionReturn(0);
158 }
159 
160 #undef __FUNCT__
161 #define __FUNCT__ "MatLUFactorNumeric_Matlab"
162 PetscErrorCode MatLUFactorNumeric_Matlab(Mat F,Mat A,const MatFactorInfo *info)
163 {
164   PetscErrorCode ierr;
165   size_t         len;
166   char           *_A,*name;
167   PetscReal      dtcol = info->dtcol;
168 
169   PetscFunctionBegin;
170   if (F->factortype == MAT_FACTOR_ILU || info->dt > 0) {
171     if (info->dtcol == PETSC_DEFAULT)  dtcol = .01;
172     F->ops->solve           = MatSolve_Matlab;
173     F->factortype           = MAT_FACTOR_LU;
174     ierr = PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),(PetscObject)A);CHKERRQ(ierr);
175     _A   = ((PetscObject)A)->name;
176     ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"info_%s = struct('droptol',%g,'thresh',%g);",_A,info->dt,dtcol);CHKERRQ(ierr);
177     ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"[l_%s,u_%s,p_%s] = luinc(%s',info_%s);",_A,_A,_A,_A,_A);CHKERRQ(ierr);
178     ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"%s = 0;",_A);CHKERRQ(ierr);
179 
180     ierr = PetscStrlen(_A,&len);CHKERRQ(ierr);
181     ierr = PetscMalloc((len+2)*sizeof(char),&name);CHKERRQ(ierr);
182     sprintf(name,"_%s",_A);
183     ierr = PetscObjectSetName((PetscObject)F,name);CHKERRQ(ierr);
184     ierr = PetscFree(name);CHKERRQ(ierr);
185   } else {
186     ierr = PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),(PetscObject)A);CHKERRQ(ierr);
187     _A   = ((PetscObject)A)->name;
188     ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"[l_%s,u_%s,p_%s] = lu(%s',%g);",_A,_A,_A,_A,dtcol);CHKERRQ(ierr);
189     ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"%s = 0;",_A);CHKERRQ(ierr);
190     ierr = PetscStrlen(_A,&len);CHKERRQ(ierr);
191     ierr = PetscMalloc((len+2)*sizeof(char),&name);CHKERRQ(ierr);
192     sprintf(name,"_%s",_A);
193     ierr = PetscObjectSetName((PetscObject)F,name);CHKERRQ(ierr);
194     ierr = PetscFree(name);CHKERRQ(ierr);
195     F->ops->solve              = MatSolve_Matlab;
196   }
197   PetscFunctionReturn(0);
198 }
199 
200 #undef __FUNCT__
201 #define __FUNCT__ "MatLUFactorSymbolic_Matlab"
202 PetscErrorCode MatLUFactorSymbolic_Matlab(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
203 {
204   PetscFunctionBegin;
205   if (A->cmap->N != A->rmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"matrix must be square");
206   F->ops->lufactornumeric    = MatLUFactorNumeric_Matlab;
207   F->assembled = PETSC_TRUE;
208   PetscFunctionReturn(0);
209 }
210 
211 EXTERN_C_BEGIN
212 #undef __FUNCT__
213 #define __FUNCT__ "MatFactorGetSolverPackage_seqaij_matlab"
214 PetscErrorCode MatFactorGetSolverPackage_seqaij_matlab(Mat A,const MatSolverPackage *type)
215 {
216   PetscFunctionBegin;
217   *type = MATSOLVERMATLAB;
218   PetscFunctionReturn(0);
219 }
220 EXTERN_C_END
221 
222 #undef __FUNCT__
223 #define __FUNCT__ "MatGetFactor_seqaij_matlab"
224 PetscErrorCode MatGetFactor_seqaij_matlab(Mat A,MatFactorType ftype,Mat *F)
225 {
226   PetscErrorCode ierr;
227 
228   PetscFunctionBegin;
229   if (A->cmap->N != A->rmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"matrix must be square");
230   ierr                         = MatCreate(((PetscObject)A)->comm,F);CHKERRQ(ierr);
231   ierr                         = MatSetSizes(*F,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
232   ierr                         = MatSetType(*F,((PetscObject)A)->type_name);CHKERRQ(ierr);
233   ierr                         = MatSeqAIJSetPreallocation(*F,0,PETSC_NULL);CHKERRQ(ierr);
234   (*F)->ops->lufactorsymbolic  = MatLUFactorSymbolic_Matlab;
235   (*F)->ops->ilufactorsymbolic = MatLUFactorSymbolic_Matlab;
236   ierr = PetscObjectComposeFunctionDynamic((PetscObject)(*F),"MatFactorGetSolverPackage_C","MatFactorGetSolverPackage_seqaij_matlab",MatFactorGetSolverPackage_seqaij_matlab);CHKERRQ(ierr);
237 
238   (*F)->factortype             = ftype;
239   PetscFunctionReturn(0);
240 }
241 
242 
243 /* --------------------------------------------------------------------------------*/
244 
245 #undef __FUNCT__
246 #define __FUNCT__ "MatFactorInfo_Matlab"
247 PetscErrorCode MatFactorInfo_Matlab(Mat A,PetscViewer viewer)
248 {
249   PetscErrorCode ierr;
250 
251   PetscFunctionBegin;
252   ierr = PetscViewerASCIIPrintf(viewer,"MATLAB run parameters:  -- not written yet!\n");CHKERRQ(ierr);
253   PetscFunctionReturn(0);
254 }
255 
256 #undef __FUNCT__
257 #define __FUNCT__ "MatView_Matlab"
258 PetscErrorCode MatView_Matlab(Mat A,PetscViewer viewer)
259 {
260   PetscErrorCode    ierr;
261   PetscBool         iascii;
262   PetscViewerFormat format;
263 
264   PetscFunctionBegin;
265   ierr = MatView_SeqAIJ(A,viewer);CHKERRQ(ierr);
266   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
267   if (iascii) {
268     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
269     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
270       ierr = MatFactorInfo_Matlab(A,viewer);
271     }
272   }
273   PetscFunctionReturn(0);
274 }
275 
276 
277 /*MC
278   MATSOLVERMATLAB - "matlab" - Providing direct solvers (LU and QR) and drop tolerance
279   based ILU factorization (ILUDT) for sequential matrices via the external package MATLAB.
280 
281 
282   Works with MATSEQAIJ matrices.
283 
284   Options Database Keys:
285 . -pc_factor_mat_solver_type matlab - selects MATLAB to do the sparse factorization
286 
287 
288   Level: beginner
289 
290 .seealso: PCLU
291 
292 .seealso: PCFactorSetMatSolverPackage(), MatSolverPackage
293 M*/
294 
295