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 PetscCheck(type != FILE_MODE_UNDEFINED,PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()"); 121 else SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP, "Unsupported file mode %s",PetscFileModes[type]); 122 } 123 PetscFunctionReturn(0); 124 } 125 126 PetscErrorCode PetscViewerDestroy_Matlab(PetscViewer v) 127 { 128 PetscViewer_Matlab *vf = (PetscViewer_Matlab*)v->data; 129 130 PetscFunctionBegin; 131 if (vf->ep) matClose(vf->ep); 132 PetscCall(PetscFree(vf)); 133 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",NULL)); 134 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",NULL)); 135 PetscFunctionReturn(0); 136 } 137 138 /*MC 139 PETSCVIEWERMATLAB - A viewer that saves the variables into a MATLAB .mat file that may be read into MATLAB 140 with load('filename'). 141 142 Level: intermediate 143 144 Note: Currently can only save PETSc vectors to .mat files, not matrices (use the PETSCVIEWERBINARY and 145 ${PETSC_DIR}/share/petsc/matlab/PetscBinaryRead.m to read matrices into MATLAB). 146 147 For parallel vectors obtained with DMCreateGlobalVector() or DMGetGlobalVector() the vectors are saved to 148 the .mat file in natural ordering. You can use DMView() to save the DMDA information to the .mat file 149 the fields in the MATLAB loaded da variable give the array dimensions so you can reshape the MATLAB 150 vector to the same multidimensional shape as it had in PETSc for plotting etc. For example, 151 152 $ In your PETSc C/C++ code (assuming a two dimensional DMDA with one degree of freedom per node) 153 $ PetscObjectSetName((PetscObject)x,"x"); 154 $ VecView(x,PETSC_VIEWER_MATLAB_WORLD); 155 $ PetscObjectSetName((PetscObject)da,"da"); 156 $ DMView(x,PETSC_VIEWER_MATLAB_WORLD); 157 $ Then from MATLAB 158 $ load('matlaboutput.mat') % matlaboutput.mat is the default filename 159 $ xnew = zeros(da.n,da.m); 160 $ xnew(:) = x; % reshape one dimensional vector back to two dimensions 161 162 If you wish to put the same variable into the .mat file several times you need to give it a new 163 name before each call to view. 164 165 Use PetscViewerMatlabPutArray() to just put an array of doubles into the .mat file 166 167 .seealso: `PETSC_VIEWER_MATLAB_()`, `PETSC_VIEWER_MATLAB_SELF`, `PETSC_VIEWER_MATLAB_WORLD`, `PetscViewerCreate()`, 168 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERASCII`, `PETSCVIEWERDRAW`, 169 `PETSC_VIEWER_STDOUT_()`, `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat` 170 171 M*/ 172 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Matlab(PetscViewer viewer) 173 { 174 PetscViewer_Matlab *e; 175 176 PetscFunctionBegin; 177 PetscCall(PetscNewLog(viewer,&e)); 178 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&e->rank)); 179 e->btype = FILE_MODE_UNDEFINED; 180 viewer->data = (void*) e; 181 182 PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",PetscViewerFileSetName_Matlab)); 183 PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Matlab)); 184 185 viewer->ops->destroy = PetscViewerDestroy_Matlab; 186 PetscFunctionReturn(0); 187 } 188 189 /*@C 190 PetscViewerMatlabOpen - Opens a Matlab .mat file for output 191 192 Collective 193 194 Input Parameters: 195 + comm - MPI communicator 196 . name - name of file 197 - type - type of file 198 $ FILE_MODE_WRITE - create new file for MATLAB output 199 $ FILE_MODE_READ - open existing file for MATLAB input 200 $ FILE_MODE_WRITE - open existing file for MATLAB output 201 202 Output Parameter: 203 . binv - PetscViewer for MATLAB output to use with the specified file 204 205 Level: beginner 206 207 Note: This PetscViewer should be destroyed with PetscViewerDestroy(). 208 209 For writing files it only opens the file on processor 0 in the communicator. 210 211 This only saves Vecs it cannot be used to save Mats. We recommend using the PETSCVIEWERBINARY to save objects to be loaded into MATLAB 212 instead of this routine. 213 214 .seealso: `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()` 215 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()` 216 @*/ 217 PetscErrorCode PetscViewerMatlabOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv) 218 { 219 PetscFunctionBegin; 220 PetscCall(PetscViewerCreate(comm,binv)); 221 PetscCall(PetscViewerSetType(*binv,PETSCVIEWERMATLAB)); 222 PetscCall(PetscViewerFileSetMode(*binv,type)); 223 PetscCall(PetscViewerFileSetName(*binv,name)); 224 PetscFunctionReturn(0); 225 } 226 227 static PetscMPIInt Petsc_Viewer_Matlab_keyval = MPI_KEYVAL_INVALID; 228 229 /*@C 230 PETSC_VIEWER_MATLAB_ - Creates a Matlab PetscViewer shared by all processors 231 in a communicator. 232 233 Collective 234 235 Input Parameter: 236 . comm - the MPI communicator to share the Matlab PetscViewer 237 238 Level: intermediate 239 240 Options Database Keys: 241 . -viewer_matlab_filename <name> - name of the Matlab file 242 243 Environmental variables: 244 . PETSC_VIEWER_MATLAB_FILENAME - name of the Matlab file 245 246 Notes: 247 Unlike almost all other PETSc routines, PETSC_VIEWER_MATLAB_ does not return 248 an error code. The matlab PetscViewer is usually used in the form 249 $ XXXView(XXX object,PETSC_VIEWER_MATLAB_(comm)); 250 251 Use PETSC_VIEWER_SOCKET_() or PetscViewerSocketOpen() to communicator with an interactive MATLAB session. 252 253 .seealso: `PETSC_VIEWER_MATLAB_WORLD`, `PETSC_VIEWER_MATLAB_SELF`, `PetscViewerMatlabOpen()`, `PetscViewerCreate()`, 254 `PetscViewerDestroy()` 255 @*/ 256 PetscViewer PETSC_VIEWER_MATLAB_(MPI_Comm comm) 257 { 258 PetscErrorCode ierr; 259 PetscBool flg; 260 PetscViewer viewer; 261 char fname[PETSC_MAX_PATH_LEN]; 262 MPI_Comm ncomm; 263 264 PetscFunctionBegin; 265 ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 266 if (Petsc_Viewer_Matlab_keyval == MPI_KEYVAL_INVALID) { 267 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Matlab_keyval,0); 268 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 269 } 270 ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_Matlab_keyval,(void**)&viewer,(int*)&flg); 271 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 272 if (!flg) { /* PetscViewer not yet created */ 273 ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_MATLAB_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg); 274 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 275 if (!flg) { 276 ierr = PetscStrcpy(fname,"matlaboutput.mat"); 277 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 278 } 279 ierr = PetscViewerMatlabOpen(ncomm,fname,FILE_MODE_WRITE,&viewer); 280 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 281 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 282 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 283 ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_Matlab_keyval,(void*)viewer); 284 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 285 } 286 ierr = PetscCommDestroy(&ncomm); 287 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 288 PetscFunctionReturn(viewer); 289 } 290