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