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 Note: Currently can only save PETSc vectors to .mat files, not matrices (use the `PETSCVIEWERBINARY` and 143 ${PETSC_DIR}/share/petsc/matlab/PetscBinaryRead.m to read matrices into MATLAB). 144 145 For parallel vectors obtained with `DMCreateGlobalVector()` or `DMGetGlobalVector()` the vectors are saved to 146 the .mat file in natural ordering. You can use DMView() to save the `DMDA` information to the .mat file 147 the fields in the MATLAB loaded da variable give the array dimensions so you can reshape the `MATLAB` 148 vector to the same multidimensional shape as it had in PETSc for plotting etc. For example, 149 150 $ In your PETSc C/C++ code (assuming a two dimensional DMDA with one degree of freedom per node) 151 $ PetscObjectSetName((PetscObject)x,"x"); 152 $ VecView(x,PETSC_VIEWER_MATLAB_WORLD); 153 $ PetscObjectSetName((PetscObject)da,"da"); 154 $ DMView(x,PETSC_VIEWER_MATLAB_WORLD); 155 $ Then from MATLAB 156 $ load('matlaboutput.mat') % matlaboutput.mat is the default filename 157 $ xnew = zeros(da.n,da.m); 158 $ xnew(:) = x; % reshape one dimensional vector back to two dimensions 159 160 If you wish to put the same variable into the .mat file several times you need to give it a new 161 name before each call to view. 162 163 Use `PetscViewerMatlabPutArray()` to just put an array of doubles into the .mat file 164 165 .seealso: `PETSC_VIEWER_MATLAB_()`, `PETSC_VIEWER_MATLAB_SELF`, `PETSC_VIEWER_MATLAB_WORLD`, `PetscViewerCreate()`, 166 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERASCII`, `PETSCVIEWERDRAW`, 167 `PETSC_VIEWER_STDOUT_()`, `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscMatlabEngine` 168 M*/ 169 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Matlab(PetscViewer viewer) { 170 PetscViewer_Matlab *e; 171 172 PetscFunctionBegin; 173 PetscCall(PetscNewLog(viewer, &e)); 174 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &e->rank)); 175 e->btype = FILE_MODE_UNDEFINED; 176 viewer->data = (void *)e; 177 178 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_Matlab)); 179 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_Matlab)); 180 181 viewer->ops->destroy = PetscViewerDestroy_Matlab; 182 PetscFunctionReturn(0); 183 } 184 185 /*@C 186 PetscViewerMatlabOpen - Opens a Matlab .mat file for output 187 188 Collective 189 190 Input Parameters: 191 + comm - MPI communicator 192 . name - name of file 193 - type - type of file 194 $ `FILE_MODE_WRITE` - create new file for MATLAB output 195 $ `FILE_MODE_READ` - open existing file for MATLAB input 196 $ ``FILE_MODE_WRITE - open existing file for MATLAB output 197 198 Output Parameter: 199 . binv - PetscViewer for MATLAB output to use with the specified file 200 201 Level: beginner 202 203 Notes: 204 This `PetscViewer` should be destroyed with `PetscViewerDestroy()`. 205 206 For writing files it only opens the file on processor 0 in the communicator. 207 208 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 209 instead of this routine. 210 211 .seealso: `PETSCVIEWERMATLAB`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()` 212 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()` 213 @*/ 214 PetscErrorCode PetscViewerMatlabOpen(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *binv) { 215 PetscFunctionBegin; 216 PetscCall(PetscViewerCreate(comm, binv)); 217 PetscCall(PetscViewerSetType(*binv, PETSCVIEWERMATLAB)); 218 PetscCall(PetscViewerFileSetMode(*binv, type)); 219 PetscCall(PetscViewerFileSetName(*binv, name)); 220 PetscFunctionReturn(0); 221 } 222 223 static PetscMPIInt Petsc_Viewer_Matlab_keyval = MPI_KEYVAL_INVALID; 224 225 /*@C 226 PETSC_VIEWER_MATLAB_ - Creates a `PETSCVIEWERMATLAB` `PetscViewer` shared by all processors 227 in a communicator. 228 229 Collective 230 231 Input Parameter: 232 . comm - the MPI communicator to share the Matlab `PetscViewer` 233 234 Options Database Key: 235 . -viewer_matlab_filename <name> - name of the Matlab file 236 237 Environmental variable: 238 . `PETSC_VIEWER_MATLAB_FILENAME` - name of the Matlab file 239 240 Level: intermediate 241 242 Note: 243 Unlike almost all other PETSc routines, `PETSC_VIEWER_MATLAB_()` does not return 244 an error code. The matlab PetscViewer is usually used in the form 245 $ XXXView(XXX object,PETSC_VIEWER_MATLAB_(comm)); 246 247 Use `PETSC_VIEWER_SOCKET_()` or `PetscViewerSocketOpen()` to communicator with an interactive MATLAB session. 248 249 .seealso: `PETSC_VIEWER_MATLAB_WORLD`, `PETSC_VIEWER_MATLAB_SELF`, `PetscViewerMatlabOpen()`, `PetscViewerCreate()`, 250 `PetscViewerDestroy()` 251 @*/ 252 PetscViewer PETSC_VIEWER_MATLAB_(MPI_Comm comm) { 253 PetscErrorCode ierr; 254 PetscBool flg; 255 PetscViewer viewer; 256 char fname[PETSC_MAX_PATH_LEN]; 257 MPI_Comm ncomm; 258 259 PetscFunctionBegin; 260 ierr = PetscCommDuplicate(comm, &ncomm, NULL); 261 if (ierr) { 262 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 263 PetscFunctionReturn(0); 264 } 265 if (Petsc_Viewer_Matlab_keyval == MPI_KEYVAL_INVALID) { 266 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Matlab_keyval, 0); 267 if (ierr) { 268 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 269 PetscFunctionReturn(NULL); 270 } 271 } 272 ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_Matlab_keyval, (void **)&viewer, (int *)&flg); 273 if (ierr) { 274 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 275 PetscFunctionReturn(NULL); 276 } 277 if (!flg) { /* PetscViewer not yet created */ 278 ierr = PetscOptionsGetenv(ncomm, "PETSC_VIEWER_MATLAB_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg); 279 if (ierr) { 280 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 281 PetscFunctionReturn(NULL); 282 } 283 if (!flg) { 284 ierr = PetscStrcpy(fname, "matlaboutput.mat"); 285 if (ierr) { 286 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 287 PetscFunctionReturn(NULL); 288 } 289 } 290 ierr = PetscViewerMatlabOpen(ncomm, fname, FILE_MODE_WRITE, &viewer); 291 if (ierr) { 292 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 293 PetscFunctionReturn(NULL); 294 } 295 ierr = PetscObjectRegisterDestroy((PetscObject)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 = MPI_Comm_set_attr(ncomm, Petsc_Viewer_Matlab_keyval, (void *)viewer); 301 if (ierr) { 302 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 303 PetscFunctionReturn(NULL); 304 } 305 } 306 ierr = PetscCommDestroy(&ncomm); 307 if (ierr) { 308 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 309 PetscFunctionReturn(NULL); 310 } 311 PetscFunctionReturn(viewer); 312 } 313