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