xref: /petsc/src/mat/impls/aij/seq/matlab/aijmatlab.c (revision b3da158bef1dae38c2355a66f754a23edcc84f23)
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   ierr = MatSeqXAIJFreeAIJ(mat,&aij->a,&aij->j,&aij->i);CHKERRQ(ierr);
91 
92   aij->nz           = nz;
93   ierr  = PetscMalloc3(aij->nz,PetscScalar,&aij->a,aij->nz,PetscInt,&aij->j,mat->rmap->n+1,PetscInt,&aij->i);CHKERRQ(ierr);
94   aij->singlemalloc = PETSC_TRUE;
95 
96   ierr = PetscMemcpy(aij->a,mxGetPr(mmat),aij->nz*sizeof(PetscScalar));CHKERRQ(ierr);
97   /* Matlab stores by column, not row so we pass in the transpose of the matrix */
98   i = aij->i;
99   for (k=0; k<n+1; k++) {
100     i[k] = (PetscInt) ii[k];
101   }
102   j = aij->j;
103   for (k=0; k<nz; k++) {
104     j[k] = (PetscInt) jj[k];
105   }
106 
107   for (k=0; k<mat->rmap->n; k++) {
108     aij->ilen[k] = aij->imax[k] = aij->i[k+1] - aij->i[k];
109   }
110 
111   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
112   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
113   PetscFunctionReturn(0);
114 }
115 EXTERN_C_END
116 
117 
118 EXTERN_C_BEGIN
119 #undef __FUNCT__
120 #define __FUNCT__ "MatlabEngineGet_SeqAIJ"
121 PetscErrorCode  MatlabEngineGet_SeqAIJ(PetscObject obj,void *mengine)
122 {
123   PetscErrorCode ierr;
124   Mat            mat = (Mat)obj;
125   mxArray        *mmat;
126 
127   PetscFunctionBegin;
128   mmat = engGetVariable((Engine *)mengine,obj->name);
129   ierr = MatSeqAIJFromMatlab(mmat,mat);CHKERRQ(ierr);
130   PetscFunctionReturn(0);
131 }
132 EXTERN_C_END
133 
134 #undef __FUNCT__
135 #define __FUNCT__ "MatSolve_Matlab"
136 PetscErrorCode MatSolve_Matlab(Mat A,Vec b,Vec x)
137 {
138   PetscErrorCode ierr;
139   const char     *_A,*_b,*_x;
140 
141   PetscFunctionBegin;
142   /* make sure objects have names; use default if not */
143   ierr = PetscObjectName((PetscObject)b);CHKERRQ(ierr);
144   ierr = PetscObjectName((PetscObject)x);CHKERRQ(ierr);
145 
146   ierr = PetscObjectGetName((PetscObject)A,&_A);CHKERRQ(ierr);
147   ierr = PetscObjectGetName((PetscObject)b,&_b);CHKERRQ(ierr);
148   ierr = PetscObjectGetName((PetscObject)x,&_x);CHKERRQ(ierr);
149   ierr = PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),(PetscObject)b);CHKERRQ(ierr);
150   ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"%s = u%s\\(l%s\\(p%s*%s));",_x,_A,_A,_A,_b);CHKERRQ(ierr);
151   ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"%s = 0;",_b);CHKERRQ(ierr);
152   /* ierr = PetscMatlabEnginePrintOutput(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),stdout);CHKERRQ(ierr);  */
153   ierr = PetscMatlabEngineGet(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),(PetscObject)x);CHKERRQ(ierr);
154   PetscFunctionReturn(0);
155 }
156 
157 #undef __FUNCT__
158 #define __FUNCT__ "MatLUFactorNumeric_Matlab"
159 PetscErrorCode MatLUFactorNumeric_Matlab(Mat F,Mat A,const MatFactorInfo *info)
160 {
161   PetscErrorCode ierr;
162   size_t         len;
163   char           *_A,*name;
164   PetscReal      dtcol = info->dtcol;
165 
166   PetscFunctionBegin;
167   if (F->factortype == MAT_FACTOR_ILU || info->dt > 0) {
168     if (info->dtcol == PETSC_DEFAULT)  dtcol = .01;
169     F->ops->solve           = MatSolve_Matlab;
170     F->factortype           = MAT_FACTOR_LU;
171     ierr = PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),(PetscObject)A);CHKERRQ(ierr);
172     _A   = ((PetscObject)A)->name;
173     ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"info_%s = struct('droptol',%g,'thresh',%g);",_A,info->dt,dtcol);CHKERRQ(ierr);
174     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);
175     ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"%s = 0;",_A);CHKERRQ(ierr);
176 
177     ierr = PetscStrlen(_A,&len);CHKERRQ(ierr);
178     ierr = PetscMalloc((len+2)*sizeof(char),&name);CHKERRQ(ierr);
179     sprintf(name,"_%s",_A);
180     ierr = PetscObjectSetName((PetscObject)F,name);CHKERRQ(ierr);
181     ierr = PetscFree(name);CHKERRQ(ierr);
182   } else {
183     ierr = PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),(PetscObject)A);CHKERRQ(ierr);
184     _A   = ((PetscObject)A)->name;
185     ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"[l_%s,u_%s,p_%s] = lu(%s',%g);",_A,_A,_A,_A,dtcol);CHKERRQ(ierr);
186     ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"%s = 0;",_A);CHKERRQ(ierr);
187     ierr = PetscStrlen(_A,&len);CHKERRQ(ierr);
188     ierr = PetscMalloc((len+2)*sizeof(char),&name);CHKERRQ(ierr);
189     sprintf(name,"_%s",_A);
190     ierr = PetscObjectSetName((PetscObject)F,name);CHKERRQ(ierr);
191     ierr = PetscFree(name);CHKERRQ(ierr);
192     F->ops->solve              = MatSolve_Matlab;
193   }
194   PetscFunctionReturn(0);
195 }
196 
197 #undef __FUNCT__
198 #define __FUNCT__ "MatLUFactorSymbolic_Matlab"
199 PetscErrorCode MatLUFactorSymbolic_Matlab(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
200 {
201   PetscFunctionBegin;
202   if (A->cmap->N != A->rmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"matrix must be square");
203   F->ops->lufactornumeric    = MatLUFactorNumeric_Matlab;
204   F->assembled = PETSC_TRUE;
205   PetscFunctionReturn(0);
206 }
207 
208 EXTERN_C_BEGIN
209 #undef __FUNCT__
210 #define __FUNCT__ "MatFactorGetSolverPackage_seqaij_matlab"
211 PetscErrorCode MatFactorGetSolverPackage_seqaij_matlab(Mat A,const MatSolverPackage *type)
212 {
213   PetscFunctionBegin;
214   *type = MATSOLVERMATLAB;
215   PetscFunctionReturn(0);
216 }
217 EXTERN_C_END
218 
219 #undef __FUNCT__
220 #define __FUNCT__ "MatGetFactor_seqaij_matlab"
221 PetscErrorCode MatGetFactor_seqaij_matlab(Mat A,MatFactorType ftype,Mat *F)
222 {
223   PetscErrorCode ierr;
224 
225   PetscFunctionBegin;
226   if (A->cmap->N != A->rmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"matrix must be square");
227   ierr                         = MatCreate(((PetscObject)A)->comm,F);CHKERRQ(ierr);
228   ierr                         = MatSetSizes(*F,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
229   ierr                         = MatSetType(*F,((PetscObject)A)->type_name);CHKERRQ(ierr);
230   ierr                         = MatSeqAIJSetPreallocation(*F,0,PETSC_NULL);CHKERRQ(ierr);
231   (*F)->ops->lufactorsymbolic  = MatLUFactorSymbolic_Matlab;
232   (*F)->ops->ilufactorsymbolic = MatLUFactorSymbolic_Matlab;
233   ierr = PetscObjectComposeFunctionDynamic((PetscObject)(*F),"MatFactorGetSolverPackage_C","MatFactorGetSolverPackage_seqaij_matlab",MatFactorGetSolverPackage_seqaij_matlab);CHKERRQ(ierr);
234 
235   (*F)->factortype             = ftype;
236   PetscFunctionReturn(0);
237 }
238 
239 
240 /* --------------------------------------------------------------------------------*/
241 
242 #undef __FUNCT__
243 #define __FUNCT__ "MatFactorInfo_Matlab"
244 PetscErrorCode MatFactorInfo_Matlab(Mat A,PetscViewer viewer)
245 {
246   PetscErrorCode ierr;
247 
248   PetscFunctionBegin;
249   ierr = PetscViewerASCIIPrintf(viewer,"Matlab run parameters:  -- not written yet!\n");CHKERRQ(ierr);
250   PetscFunctionReturn(0);
251 }
252 
253 #undef __FUNCT__
254 #define __FUNCT__ "MatView_Matlab"
255 PetscErrorCode MatView_Matlab(Mat A,PetscViewer viewer)
256 {
257   PetscErrorCode    ierr;
258   PetscBool         iascii;
259   PetscViewerFormat format;
260 
261   PetscFunctionBegin;
262   ierr = MatView_SeqAIJ(A,viewer);CHKERRQ(ierr);
263   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
264   if (iascii) {
265     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
266     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
267       ierr = MatFactorInfo_Matlab(A,viewer);
268     }
269   }
270   PetscFunctionReturn(0);
271 }
272 
273 
274 /*MC
275   MATSOLVERMATLAB - "matlab" - Providing direct solvers (LU and QR) and drop tolerance
276   based ILU factorization (ILUDT) for sequential matrices via the external package Matlab.
277 
278 
279   Works with MATSEQAIJ matrices.
280 
281   Options Database Keys:
282 . -pc_factor_mat_solver_type matlab - selects Matlab to do the sparse factorization
283 
284 
285   Level: beginner
286 
287 .seealso: PCLU
288 
289 .seealso: PCFactorSetMatSolverPackage(), MatSolverPackage
290 M*/
291 
292