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