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