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