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 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 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(0); 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(0); 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 the array 69 . array - the array (represented in one dimension) 70 - name - the name of the 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(0); 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(0); 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(0); 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(0); 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(0); 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 $ `FILE_MODE_WRITE` - create new file for MATLAB output 207 $ `FILE_MODE_READ` - open existing file for MATLAB input 208 $ `FILE_MODE_WRITE` - open existing file for MATLAB output 209 210 Output Parameter: 211 . binv - PetscViewer for MATLAB output to use with the specified file 212 213 Level: beginner 214 215 Notes: 216 This `PetscViewer` should be destroyed with `PetscViewerDestroy()`. 217 218 For writing files it only opens the file on processor 0 in the communicator. 219 220 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 221 instead of this routine. 222 223 PETSc must be configured with the option -with-matlab for this functionality 224 225 .seealso: `PETSCVIEWERMATLAB`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()` 226 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()` 227 @*/ 228 PetscErrorCode PetscViewerMatlabOpen(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *binv) 229 { 230 PetscFunctionBegin; 231 PetscCall(PetscViewerCreate(comm, binv)); 232 PetscCall(PetscViewerSetType(*binv, PETSCVIEWERMATLAB)); 233 PetscCall(PetscViewerFileSetMode(*binv, type)); 234 PetscCall(PetscViewerFileSetName(*binv, name)); 235 PetscFunctionReturn(0); 236 } 237 238 static PetscMPIInt Petsc_Viewer_Matlab_keyval = MPI_KEYVAL_INVALID; 239 240 /*@C 241 PETSC_VIEWER_MATLAB_ - Creates a `PETSCVIEWERMATLAB` `PetscViewer` shared by all processors 242 in a communicator. 243 244 Collective 245 246 Input Parameter: 247 . comm - the MPI communicator to share the Matlab `PetscViewer` 248 249 Options Database Key: 250 . -viewer_matlab_filename <name> - name of the Matlab file 251 252 Environmental variable: 253 . `PETSC_VIEWER_MATLAB_FILENAME` - name of the Matlab file 254 255 Level: intermediate 256 257 Note: 258 Unlike almost all other PETSc routines, `PETSC_VIEWER_MATLAB_()` does not return 259 an error code. The matlab PetscViewer is usually used in the form 260 $ XXXView(XXX object,PETSC_VIEWER_MATLAB_(comm)); 261 262 Use `PETSC_VIEWER_SOCKET_()` or `PetscViewerSocketOpen()` to communicator with an interactive MATLAB session. 263 264 .seealso: `PETSC_VIEWER_MATLAB_WORLD`, `PETSC_VIEWER_MATLAB_SELF`, `PetscViewerMatlabOpen()`, `PetscViewerCreate()`, 265 `PetscViewerDestroy()` 266 @*/ 267 PetscViewer PETSC_VIEWER_MATLAB_(MPI_Comm comm) 268 { 269 PetscErrorCode ierr; 270 PetscBool flg; 271 PetscViewer viewer; 272 char fname[PETSC_MAX_PATH_LEN]; 273 MPI_Comm ncomm; 274 275 PetscFunctionBegin; 276 ierr = PetscCommDuplicate(comm, &ncomm, NULL); 277 if (ierr) { 278 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 279 PetscFunctionReturn(0); 280 } 281 if (Petsc_Viewer_Matlab_keyval == MPI_KEYVAL_INVALID) { 282 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Matlab_keyval, 0); 283 if (ierr) { 284 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 285 PetscFunctionReturn(NULL); 286 } 287 } 288 ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_Matlab_keyval, (void **)&viewer, (int *)&flg); 289 if (ierr) { 290 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 291 PetscFunctionReturn(NULL); 292 } 293 if (!flg) { /* PetscViewer not yet created */ 294 ierr = PetscOptionsGetenv(ncomm, "PETSC_VIEWER_MATLAB_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg); 295 if (ierr) { 296 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 297 PetscFunctionReturn(NULL); 298 } 299 if (!flg) { 300 ierr = PetscStrcpy(fname, "matlaboutput.mat"); 301 if (ierr) { 302 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 303 PetscFunctionReturn(NULL); 304 } 305 } 306 ierr = PetscViewerMatlabOpen(ncomm, fname, FILE_MODE_WRITE, &viewer); 307 if (ierr) { 308 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 309 PetscFunctionReturn(NULL); 310 } 311 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 312 if (ierr) { 313 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 314 PetscFunctionReturn(NULL); 315 } 316 ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_Matlab_keyval, (void *)viewer); 317 if (ierr) { 318 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 319 PetscFunctionReturn(NULL); 320 } 321 } 322 ierr = PetscCommDestroy(&ncomm); 323 if (ierr) { 324 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 325 PetscFunctionReturn(NULL); 326 } 327 PetscFunctionReturn(viewer); 328 } 329