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