Actual source code: vmatlab.c


  2: #include <petsc/private/viewerimpl.h>
  3: #include <mat.h>

  5: typedef struct {
  6:   MATFile      *ep;
  7:   PetscMPIInt   rank;
  8:   PetscFileMode btype;
  9: } PetscViewer_Matlab;

 11: /*@C
 12:     PetscViewerMatlabPutArray - Puts an array into the `PETSCVIEWERMATLAB` viewer.

 14:       Not collective: only processor zero saves the array

 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

 22:    Level: advanced

 24:     Note:
 25:     Only writes array values on processor 0.

 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;

 35:   ml = (PetscViewer_Matlab *)mfile->data;
 36:   if (!ml->rank) {
 37:     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:     PetscArraycpy(mxGetPr(mat), array, m * n);
 44:     matPutVariable(ml->ep, name, mat);

 46:     PetscInfo(mfile, "Put MATLAB array %s\n", name);
 47:   }
 48:   return 0;
 49: }

 51: PetscErrorCode PetscViewerMatlabPutVariable(PetscViewer viewer, const char *name, void *mat)
 52: {
 53:   PetscViewer_Matlab *ml = (PetscViewer_Matlab *)viewer->data;

 55:   matPutVariable(ml->ep, name, (mxArray *)mat);
 56:   return 0;
 57: }

 59: /*@C
 60:     PetscViewerMatlabGetArray - Gets a variable from a `PETSCVIEWERMATLAB` viewer into an array

 62:     Not Collective; only processor zero reads in the array

 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

 70:    Level: advanced

 72:     Note:
 73:     Only reads in array values on processor 0.

 75: .seealso: `PETSCVIEWERMATLAB`, `PetscViewerMatlabPutArray()`
 76: @*/
 77: PetscErrorCode PetscViewerMatlabGetArray(PetscViewer mfile, int m, int n, PetscScalar *array, const char *name)
 78: {
 79:   PetscViewer_Matlab *ml;
 80:   mxArray            *mat;

 83:   ml = (PetscViewer_Matlab *)mfile->data;
 84:   if (!ml->rank) {
 85:     PetscInfo(mfile, "Getting MATLAB array %s\n", name);
 86:     mat = matGetVariable(ml->ep, name);
 88:     PetscArraycpy(array, mxGetPr(mat), m * n);
 89:     PetscInfo(mfile, "Got MATLAB array %s\n", name);
 90:   }
 91:   return 0;
 92: }

 94: PetscErrorCode PetscViewerFileSetMode_Matlab(PetscViewer viewer, PetscFileMode type)
 95: {
 96:   PetscViewer_Matlab *vmatlab = (PetscViewer_Matlab *)viewer->data;

 98:   vmatlab->btype = type;
 99:   return 0;
100: }

102: /*
103:         Actually opens the file
104: */
105: PetscErrorCode PetscViewerFileSetName_Matlab(PetscViewer viewer, const char name[])
106: {
107:   PetscViewer_Matlab *vmatlab = (PetscViewer_Matlab *)viewer->data;
108:   PetscFileMode       type    = vmatlab->btype;

111:   if (vmatlab->ep) matClose(vmatlab->ep);

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 {
119:       SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[type]);
120:     }
121:   }
122:   return 0;
123: }

125: PetscErrorCode PetscViewerDestroy_Matlab(PetscViewer v)
126: {
127:   PetscViewer_Matlab *vf = (PetscViewer_Matlab *)v->data;

129:   if (vf->ep) matClose(vf->ep);
130:   PetscFree(vf);
131:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", NULL);
132:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", NULL);
133:   return 0;
134: }

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').

140:    Level: intermediate

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).

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,

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

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.

168:               Use `PetscViewerMatlabPutArray()` to just put an array of doubles into the .mat file

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: {
176:   PetscViewer_Matlab *e;

178:   PetscNew(&e);
179:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &e->rank);
180:   e->btype     = FILE_MODE_UNDEFINED;
181:   viewer->data = (void *)e;

183:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_Matlab);
184:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_Matlab);

186:   viewer->ops->destroy = PetscViewerDestroy_Matlab;
187:   return 0;
188: }

190: /*@C
191:    PetscViewerMatlabOpen - Opens a Matlab .mat file for output

193:    Collective

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

203:    Output Parameter:
204: .  binv - PetscViewer for MATLAB output to use with the specified file

206:    Level: beginner

208:    Notes:
209:    This `PetscViewer` should be destroyed with `PetscViewerDestroy()`.

211:    For writing files it only opens the file on processor 0 in the communicator.

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.

216:    PETSc must be configured with the option -with-matlab for this functionality

218: .seealso: `PETSCVIEWERMATLAB`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`
219:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`
220: @*/
221: PetscErrorCode PetscViewerMatlabOpen(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *binv)
222: {
223:   PetscViewerCreate(comm, binv);
224:   PetscViewerSetType(*binv, PETSCVIEWERMATLAB);
225:   PetscViewerFileSetMode(*binv, type);
226:   PetscViewerFileSetName(*binv, name);
227:   return 0;
228: }

230: static PetscMPIInt Petsc_Viewer_Matlab_keyval = MPI_KEYVAL_INVALID;

232: /*@C
233:      PETSC_VIEWER_MATLAB_ - Creates a `PETSCVIEWERMATLAB` `PetscViewer` shared by all processors
234:                      in a communicator.

236:      Collective

238:      Input Parameter:
239: .    comm - the MPI communicator to share the Matlab `PetscViewer`

241:    Options Database Key:
242: .    -viewer_matlab_filename <name> - name of the Matlab file

244:    Environmental variable:
245: .   `PETSC_VIEWER_MATLAB_FILENAME` - name of the Matlab file

247:      Level: intermediate

249:      Note:
250:      Unlike almost all other PETSc routines, `PETSC_VIEWER_MATLAB_()` does not return
251:      an error code.  The matlab PetscViewer is usually used in the form
252: $       XXXView(XXX object,PETSC_VIEWER_MATLAB_(comm));

254:      Use `PETSC_VIEWER_SOCKET_()` or `PetscViewerSocketOpen()` to communicator with an interactive MATLAB session.

256: .seealso: `PETSC_VIEWER_MATLAB_WORLD`, `PETSC_VIEWER_MATLAB_SELF`, `PetscViewerMatlabOpen()`, `PetscViewerCreate()`,
257:           `PetscViewerDestroy()`
258: @*/
259: PetscViewer PETSC_VIEWER_MATLAB_(MPI_Comm comm)
260: {
262:   PetscBool      flg;
263:   PetscViewer    viewer;
264:   char           fname[PETSC_MAX_PATH_LEN];
265:   MPI_Comm       ncomm;

267:   PetscCommDuplicate(comm, &ncomm, NULL);
268:   if (ierr) {
269:     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
270:     return 0;
271:   }
272:   if (Petsc_Viewer_Matlab_keyval == MPI_KEYVAL_INVALID) {
273:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Matlab_keyval, 0);
274:     if (ierr) {
275:       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
276:       return NULL;
277:     }
278:   }
279:   MPI_Comm_get_attr(ncomm, Petsc_Viewer_Matlab_keyval, (void **)&viewer, (int *)&flg);
280:   if (ierr) {
281:     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
282:     return NULL;
283:   }
284:   if (!flg) { /* PetscViewer not yet created */
285:     PetscOptionsGetenv(ncomm, "PETSC_VIEWER_MATLAB_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg);
286:     if (ierr) {
287:       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
288:       return NULL;
289:     }
290:     if (!flg) {
291:       PetscStrcpy(fname, "matlaboutput.mat");
292:       if (ierr) {
293:         PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
294:         return NULL;
295:       }
296:     }
297:     PetscViewerMatlabOpen(ncomm, fname, FILE_MODE_WRITE, &viewer);
298:     if (ierr) {
299:       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
300:       return NULL;
301:     }
302:     PetscObjectRegisterDestroy((PetscObject)viewer);
303:     if (ierr) {
304:       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
305:       return NULL;
306:     }
307:     MPI_Comm_set_attr(ncomm, Petsc_Viewer_Matlab_keyval, (void *)viewer);
308:     if (ierr) {
309:       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
310:       return NULL;
311:     }
312:   }
313:   PetscCommDestroy(&ncomm);
314:   if (ierr) {
315:     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
316:     return NULL;
317:   }
318:   return viewer;
319: }