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