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 MATLAB 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:      Notes:
 25:     Only writes array values on processor 0.

 27: @*/
 28: PetscErrorCode  PetscViewerMatlabPutArray(PetscViewer mfile,int m,int n,const PetscScalar *array,const char *name)
 29: {
 30:   PetscErrorCode     ierr;
 31:   PetscViewer_Matlab *ml;
 32:   mxArray            *mat;

 35:   if (!mfile) SETERRQ(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:     PetscInfo1(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:     PetscArraycpy(mxGetPr(mat),array,m*n);
 45:     matPutVariable(ml->ep,name,mat);

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

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

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

 61: /*@C
 62:     PetscViewerMatlabGetArray - Gets a variable from a MATLAB viewer into an array

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

 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

 72:    Level: advanced

 74:      Notes:
 75:     Only reads in array values on processor 0.

 77: @*/
 78: PetscErrorCode  PetscViewerMatlabGetArray(PetscViewer mfile,int m,int n,PetscScalar *array,const char *name)
 79: {
 80:   PetscErrorCode     ierr;
 81:   PetscViewer_Matlab *ml;
 82:   mxArray            *mat;

 85:   if (!mfile) SETERRQ(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:     PetscInfo1(mfile,"Getting MATLAB array %s\n",name);
 89:     mat  = matGetVariable(ml->ep,name);
 90:     if (!mat) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to get array %s from matlab",name);
 91:     PetscArraycpy(array,mxGetPr(mat),m*n);
 92:     PetscInfo1(mfile,"Got MATLAB array %s\n",name);
 93:   }
 94:   return(0);
 95: }

 97: PetscErrorCode  PetscViewerFileSetMode_Matlab(PetscViewer viewer,PetscFileMode type)
 98: {
 99:   PetscViewer_Matlab *vmatlab = (PetscViewer_Matlab*)viewer->data;

102:   vmatlab->btype = type;
103:   return(0);
104: }

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;

115:   if (type == (PetscFileMode) -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
116:   if (vmatlab->ep) matClose(vmatlab->ep);

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 if (type == FILE_MODE_UNDEFINED) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
123:     else SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP, "Unsupported file mode %s",PetscFileModes[type]);
124:   }
125:   return(0);
126: }

128: PetscErrorCode PetscViewerDestroy_Matlab(PetscViewer v)
129: {
130:   PetscErrorCode     ierr;
131:   PetscViewer_Matlab *vf = (PetscViewer_Matlab*)v->data;

134:   if (vf->ep) matClose(vf->ep);
135:   PetscFree(vf);
136:   return(0);
137: }

139: /*MC
140:    PETSCVIEWERMATLAB - A viewer that saves the variables into a MATLAB .mat file that may be read into MATLAB
141:        with load('filename').

143:    Level: intermediate

145:        Note: Currently can only save PETSc vectors to .mat files, not matrices (use the PETSCVIEWERBINARY and
146:              ${PETSC_DIR}/share/petsc/matlab/PetscBinaryRead.m to read matrices into MATLAB).

148:              For parallel vectors obtained with DMCreateGlobalVector() or DMGetGlobalVector() the vectors are saved to
149:              the .mat file in natural ordering. You can use DMView() to save the DMDA information to the .mat file
150:              the fields in the MATLAB loaded da variable give the array dimensions so you can reshape the MATLAB
151:              vector to the same multidimensional shape as it had in PETSc for plotting etc. For example,

153: $             In your PETSc C/C++ code (assuming a two dimensional DMDA with one degree of freedom per node)
154: $                PetscObjectSetName((PetscObject)x,"x");
155: $                VecView(x,PETSC_VIEWER_MATLAB_WORLD);
156: $                PetscObjectSetName((PetscObject)da,"da");
157: $                DMView(x,PETSC_VIEWER_MATLAB_WORLD);
158: $             Then from MATLAB
159: $                load('matlaboutput.mat')   % matlaboutput.mat is the default filename
160: $                xnew = zeros(da.n,da.m);
161: $                xnew(:) = x;    % reshape one dimensional vector back to two dimensions

163:               If you wish to put the same variable into the .mat file several times you need to give it a new
164:               name before each call to view.

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

168: .seealso:  PETSC_VIEWER_MATLAB_(),PETSC_VIEWER_MATLAB_SELF, PETSC_VIEWER_MATLAB_WORLD,PetscViewerCreate(),
169:            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERBINARY, PETSCVIEWERASCII, PETSCVIEWERDRAW,
170:            PETSC_VIEWER_STDOUT_(), PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat

172: M*/
173: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Matlab(PetscViewer viewer)
174: {
175:   PetscErrorCode     ierr;
176:   PetscViewer_Matlab *e;

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

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

187:   viewer->ops->destroy = PetscViewerDestroy_Matlab;
188:   return(0);
189: }

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

194:    Collective

196:    Input Parameters:
197: +  comm - MPI communicator
198: .  name - name of file
199: -  type - type of file
200: $    FILE_MODE_WRITE - create new file for MATLAB output
201: $    FILE_MODE_READ - open existing file for MATLAB input
202: $    FILE_MODE_WRITE - open existing file for MATLAB output

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

207:    Level: beginner

209:    Note: 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 Vecs it cannot be used to save Mats. We recommend using the PETSCVIEWERBINARY to save objects to be loaded into MATLAB
214:      instead of this routine.

216: .seealso: 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: {

224:   PetscViewerCreate(comm,binv);
225:   PetscViewerSetType(*binv,PETSCVIEWERMATLAB);
226:   PetscViewerFileSetMode(*binv,type);
227:   PetscViewerFileSetName(*binv,name);
228:   return(0);
229: }

231: static PetscMPIInt Petsc_Viewer_Matlab_keyval = MPI_KEYVAL_INVALID;

233: /*@C
234:      PETSC_VIEWER_MATLAB_ - Creates a Matlab PetscViewer shared by all processors
235:                      in a communicator.

237:      Collective

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

242:      Level: intermediate

244:    Options Database Keys:
245: .    -viewer_matlab_filename <name> - name of the Matlab file

247:    Environmental variables:
248: .   PETSC_VIEWER_MATLAB_FILENAME - name of the Matlab file

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

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

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

269:   PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
270:   if (Petsc_Viewer_Matlab_keyval == MPI_KEYVAL_INVALID) {
271:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Matlab_keyval,0);
272:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
273:   }
274:   MPI_Comm_get_attr(ncomm,Petsc_Viewer_Matlab_keyval,(void**)&viewer,(int*)&flg);
275:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
276:   if (!flg) { /* PetscViewer not yet created */
277:     PetscOptionsGetenv(ncomm,"PETSC_VIEWER_MATLAB_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
278:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
279:     if (!flg) {
280:       PetscStrcpy(fname,"matlaboutput.mat");
281:       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
282:     }
283:     PetscViewerMatlabOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
284:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
285:     PetscObjectRegisterDestroy((PetscObject)viewer);
286:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
287:     MPI_Comm_set_attr(ncomm,Petsc_Viewer_Matlab_keyval,(void*)viewer);
288:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
289:   }
290:   PetscCommDestroy(&ncomm);
291:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
292:   PetscFunctionReturn(viewer);
293: }