1 2 #include <petsc/private/viewerimpl.h> 3 #include <mat.h> 4 5 typedef struct { 6 MATFile *ep; 7 PetscMPIInt rank; 8 PetscFileMode btype; 9 } PetscViewer_Matlab; 10 11 /*@C 12 PetscViewerMatlabPutArray - Puts an array into the MATLAB viewer. 13 14 Not collective: only processor zero saves the array 15 16 Input Parameters: 17 + mfile - the viewer 18 . m,n - the dimensions of the array 19 . array - the array (represented in one dimension) 20 - name - the name of the array 21 22 Level: advanced 23 24 Notes: 25 Only writes array values on processor 0. 26 27 @*/ 28 PetscErrorCode PetscViewerMatlabPutArray(PetscViewer mfile,int m,int n,const PetscScalar *array,const char *name) 29 { 30 PetscViewer_Matlab *ml; 31 mxArray *mat; 32 33 PetscFunctionBegin; 34 PetscCheck(mfile,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null argument: probably PETSC_VIEWER_MATLAB_() failed"); 35 ml = (PetscViewer_Matlab*)mfile->data; 36 if (!ml->rank) { 37 PetscCall(PetscInfo(mfile,"Putting MATLAB array %s\n",name)); 38 #if !defined(PETSC_USE_COMPLEX) 39 mat = mxCreateDoubleMatrix(m,n,mxREAL); 40 #else 41 mat = mxCreateDoubleMatrix(m,n,mxCOMPLEX); 42 #endif 43 PetscCall(PetscArraycpy(mxGetPr(mat),array,m*n)); 44 matPutVariable(ml->ep,name,mat); 45 46 PetscCall(PetscInfo(mfile,"Put MATLAB array %s\n",name)); 47 } 48 PetscFunctionReturn(0); 49 } 50 51 PetscErrorCode PetscViewerMatlabPutVariable(PetscViewer viewer,const char *name,void *mat) 52 { 53 PetscViewer_Matlab *ml = (PetscViewer_Matlab*)viewer->data; 54 55 PetscFunctionBegin; 56 matPutVariable(ml->ep,name,(mxArray*)mat); 57 PetscFunctionReturn(0); 58 } 59 60 /*@C 61 PetscViewerMatlabGetArray - Gets a variable from a MATLAB viewer into an array 62 63 Not Collective; only processor zero reads in the array 64 65 Input Parameters: 66 + mfile - the MATLAB file viewer 67 . m,n - the dimensions of the array 68 . array - the array (represented in one dimension) 69 - name - the name of the array 70 71 Level: advanced 72 73 Notes: 74 Only reads in array values on processor 0. 75 76 @*/ 77 PetscErrorCode PetscViewerMatlabGetArray(PetscViewer mfile,int m,int n,PetscScalar *array,const char *name) 78 { 79 PetscViewer_Matlab *ml; 80 mxArray *mat; 81 82 PetscFunctionBegin; 83 PetscCheck(mfile,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null argument: probably PETSC_VIEWER_MATLAB_() failed"); 84 ml = (PetscViewer_Matlab*)mfile->data; 85 if (!ml->rank) { 86 PetscCall(PetscInfo(mfile,"Getting MATLAB array %s\n",name)); 87 mat = matGetVariable(ml->ep,name); 88 PetscCheck(mat,PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to get array %s from matlab",name); 89 PetscCall(PetscArraycpy(array,mxGetPr(mat),m*n)); 90 PetscCall(PetscInfo(mfile,"Got MATLAB array %s\n",name)); 91 } 92 PetscFunctionReturn(0); 93 } 94 95 PetscErrorCode PetscViewerFileSetMode_Matlab(PetscViewer viewer,PetscFileMode type) 96 { 97 PetscViewer_Matlab *vmatlab = (PetscViewer_Matlab*)viewer->data; 98 99 PetscFunctionBegin; 100 vmatlab->btype = type; 101 PetscFunctionReturn(0); 102 } 103 104 /* 105 Actually opens the file 106 */ 107 PetscErrorCode PetscViewerFileSetName_Matlab(PetscViewer viewer,const char name[]) 108 { 109 PetscViewer_Matlab *vmatlab = (PetscViewer_Matlab*)viewer->data; 110 PetscFileMode type = vmatlab->btype; 111 112 PetscFunctionBegin; 113 PetscCheck(type != (PetscFileMode) -1,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode() before PetscViewerFileSetName()"); 114 if (vmatlab->ep) matClose(vmatlab->ep); 115 116 /* only first processor opens file */ 117 if (!vmatlab->rank) { 118 if (type == FILE_MODE_READ) vmatlab->ep = matOpen(name,"r"); 119 else if (type == FILE_MODE_WRITE) vmatlab->ep = matOpen(name,"w"); 120 else { 121 PetscCheck(type != FILE_MODE_UNDEFINED,PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()"); 122 SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP, "Unsupported file mode %s",PetscFileModes[type]); 123 } 124 } 125 PetscFunctionReturn(0); 126 } 127 128 PetscErrorCode PetscViewerDestroy_Matlab(PetscViewer v) 129 { 130 PetscViewer_Matlab *vf = (PetscViewer_Matlab*)v->data; 131 132 PetscFunctionBegin; 133 if (vf->ep) matClose(vf->ep); 134 PetscCall(PetscFree(vf)); 135 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",NULL)); 136 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",NULL)); 137 PetscFunctionReturn(0); 138 } 139 140 /*MC 141 PETSCVIEWERMATLAB - A viewer that saves the variables into a MATLAB .mat file that may be read into MATLAB 142 with load('filename'). 143 144 Level: intermediate 145 146 Note: Currently can only save PETSc vectors to .mat files, not matrices (use the PETSCVIEWERBINARY and 147 ${PETSC_DIR}/share/petsc/matlab/PetscBinaryRead.m to read matrices into MATLAB). 148 149 For parallel vectors obtained with DMCreateGlobalVector() or DMGetGlobalVector() the vectors are saved to 150 the .mat file in natural ordering. You can use DMView() to save the DMDA information to the .mat file 151 the fields in the MATLAB loaded da variable give the array dimensions so you can reshape the MATLAB 152 vector to the same multidimensional shape as it had in PETSc for plotting etc. For example, 153 154 $ In your PETSc C/C++ code (assuming a two dimensional DMDA with one degree of freedom per node) 155 $ PetscObjectSetName((PetscObject)x,"x"); 156 $ VecView(x,PETSC_VIEWER_MATLAB_WORLD); 157 $ PetscObjectSetName((PetscObject)da,"da"); 158 $ DMView(x,PETSC_VIEWER_MATLAB_WORLD); 159 $ Then from MATLAB 160 $ load('matlaboutput.mat') % matlaboutput.mat is the default filename 161 $ xnew = zeros(da.n,da.m); 162 $ xnew(:) = x; % reshape one dimensional vector back to two dimensions 163 164 If you wish to put the same variable into the .mat file several times you need to give it a new 165 name before each call to view. 166 167 Use PetscViewerMatlabPutArray() to just put an array of doubles into the .mat file 168 169 .seealso: `PETSC_VIEWER_MATLAB_()`, `PETSC_VIEWER_MATLAB_SELF`, `PETSC_VIEWER_MATLAB_WORLD`, `PetscViewerCreate()`, 170 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERASCII`, `PETSCVIEWERDRAW`, 171 `PETSC_VIEWER_STDOUT_()`, `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat` 172 173 M*/ 174 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Matlab(PetscViewer viewer) 175 { 176 PetscViewer_Matlab *e; 177 178 PetscFunctionBegin; 179 PetscCall(PetscNewLog(viewer,&e)); 180 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&e->rank)); 181 e->btype = FILE_MODE_UNDEFINED; 182 viewer->data = (void*) e; 183 184 PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",PetscViewerFileSetName_Matlab)); 185 PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Matlab)); 186 187 viewer->ops->destroy = PetscViewerDestroy_Matlab; 188 PetscFunctionReturn(0); 189 } 190 191 /*@C 192 PetscViewerMatlabOpen - Opens a Matlab .mat file for output 193 194 Collective 195 196 Input Parameters: 197 + comm - MPI communicator 198 . name - name of file 199 - type - type of file 200 $ FILE_MODE_WRITE - create new file for MATLAB output 201 $ FILE_MODE_READ - open existing file for MATLAB input 202 $ FILE_MODE_WRITE - open existing file for MATLAB output 203 204 Output Parameter: 205 . binv - PetscViewer for MATLAB output to use with the specified file 206 207 Level: beginner 208 209 Note: This PetscViewer should be destroyed with PetscViewerDestroy(). 210 211 For writing files it only opens the file on processor 0 in the communicator. 212 213 This only saves Vecs it cannot be used to save Mats. We recommend using the PETSCVIEWERBINARY to save objects to be loaded into MATLAB 214 instead of this routine. 215 216 .seealso: `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()` 217 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()` 218 @*/ 219 PetscErrorCode PetscViewerMatlabOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv) 220 { 221 PetscFunctionBegin; 222 PetscCall(PetscViewerCreate(comm,binv)); 223 PetscCall(PetscViewerSetType(*binv,PETSCVIEWERMATLAB)); 224 PetscCall(PetscViewerFileSetMode(*binv,type)); 225 PetscCall(PetscViewerFileSetName(*binv,name)); 226 PetscFunctionReturn(0); 227 } 228 229 static PetscMPIInt Petsc_Viewer_Matlab_keyval = MPI_KEYVAL_INVALID; 230 231 /*@C 232 PETSC_VIEWER_MATLAB_ - Creates a Matlab PetscViewer shared by all processors 233 in a communicator. 234 235 Collective 236 237 Input Parameter: 238 . comm - the MPI communicator to share the Matlab PetscViewer 239 240 Level: intermediate 241 242 Options Database Keys: 243 . -viewer_matlab_filename <name> - name of the Matlab file 244 245 Environmental variables: 246 . PETSC_VIEWER_MATLAB_FILENAME - name of the Matlab file 247 248 Notes: 249 Unlike almost all other PETSc routines, PETSC_VIEWER_MATLAB_ does not return 250 an error code. The matlab PetscViewer is usually used in the form 251 $ XXXView(XXX object,PETSC_VIEWER_MATLAB_(comm)); 252 253 Use PETSC_VIEWER_SOCKET_() or PetscViewerSocketOpen() to communicator with an interactive MATLAB session. 254 255 .seealso: `PETSC_VIEWER_MATLAB_WORLD`, `PETSC_VIEWER_MATLAB_SELF`, `PetscViewerMatlabOpen()`, `PetscViewerCreate()`, 256 `PetscViewerDestroy()` 257 @*/ 258 PetscViewer PETSC_VIEWER_MATLAB_(MPI_Comm comm) 259 { 260 PetscErrorCode ierr; 261 PetscBool flg; 262 PetscViewer viewer; 263 char fname[PETSC_MAX_PATH_LEN]; 264 MPI_Comm ncomm; 265 266 PetscFunctionBegin; 267 ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 268 if (Petsc_Viewer_Matlab_keyval == MPI_KEYVAL_INVALID) { 269 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Matlab_keyval,0); 270 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 271 } 272 ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_Matlab_keyval,(void**)&viewer,(int*)&flg); 273 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 274 if (!flg) { /* PetscViewer not yet created */ 275 ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_MATLAB_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg); 276 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 277 if (!flg) { 278 ierr = PetscStrcpy(fname,"matlaboutput.mat"); 279 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 280 } 281 ierr = PetscViewerMatlabOpen(ncomm,fname,FILE_MODE_WRITE,&viewer); 282 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 283 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 284 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 285 ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_Matlab_keyval,(void*)viewer); 286 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 287 } 288 ierr = PetscCommDestroy(&ncomm); 289 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 290 PetscFunctionReturn(viewer); 291 } 292