Actual source code: vmatlab.c

petsc-main 2021-04-20
Report Typos and Errors

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


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

 12: /*@C
 13:     PetscViewerMatlabPutArray - Puts an array into the MATLAB viewer.

 15:       Not collective: only processor zero saves the array

 17:     Input Parameters:
 18: +    mfile - the viewer
 19: .    m,n - the dimensions of the array
 20: .    array - the array (represented in one dimension)
 21: -    name - the name of the array

 23:    Level: advanced

 25:      Notes:
 26:     Only writes array values on processor 0.

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

 36:   if (!mfile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null argument: probably PETSC_VIEWER_MATLAB_() failed");
 37:   ml = (PetscViewer_Matlab*)mfile->data;
 38:   if (!ml->rank) {
 39:     PetscInfo1(mfile,"Putting MATLAB array %s\n",name);
 40: #if !defined(PETSC_USE_COMPLEX)
 41:     mat  = mxCreateDoubleMatrix(m,n,mxREAL);
 42: #else
 43:     mat  = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
 44: #endif
 45:     PetscArraycpy(mxGetPr(mat),array,m*n);
 46:     matPutVariable(ml->ep,name,mat);

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

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

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

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

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

 67:     Input Parameters:
 68: +    mfile - the MATLAB file viewer
 69: .    m,n - the dimensions of the array
 70: .    array - the array (represented in one dimension)
 71: -    name - the name of the array

 73:    Level: advanced

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

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

 86:   if (!mfile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null argument: probably PETSC_VIEWER_MATLAB_() failed");
 87:   ml = (PetscViewer_Matlab*)mfile->data;
 88:   if (!ml->rank) {
 89:     PetscInfo1(mfile,"Getting MATLAB array %s\n",name);
 90:     mat  = matGetVariable(ml->ep,name);
 91:     if (!mat) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to get array %s from matlab",name);
 92:     PetscArraycpy(array,mxGetPr(mat),m*n);
 93:     PetscInfo1(mfile,"Got MATLAB array %s\n",name);
 94:   }
 95:   return(0);
 96: }

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

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

107: /*
108:         Actually opens the file
109: */
110: PetscErrorCode  PetscViewerFileSetName_Matlab(PetscViewer viewer,const char name[])
111: {
112:   PetscViewer_Matlab *vmatlab = (PetscViewer_Matlab*)viewer->data;
113:   PetscFileMode      type     = vmatlab->btype;

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

119:   /* only first processor opens file */
120:   if (!vmatlab->rank) {
121:     if (type == FILE_MODE_READ) vmatlab->ep = matOpen(name,"r");
122:     else if (type == FILE_MODE_WRITE) vmatlab->ep = matOpen(name,"w");
123:     else if (type == FILE_MODE_UNDEFINED) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
124:     else SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP, "Unsupported file mode %s",PetscFileModes[type]);
125:   }
126:   return(0);
127: }

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

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

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

144:    Level: intermediate

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

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

154: $             In your PETSc C/C++ code (assuming a two dimensional DMDA with one degree of freedom per node)
155: $                PetscObjectSetName((PetscObject)x,"x");
156: $                VecView(x,PETSC_VIEWER_MATLAB_WORLD);
157: $                PetscObjectSetName((PetscObject)da,"da");
158: $                DMView(x,PETSC_VIEWER_MATLAB_WORLD);
159: $             Then from MATLAB
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

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

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

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

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

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

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

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

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

195:    Collective

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

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

208:    Level: beginner

210:    Note: This PetscViewer should be destroyed with PetscViewerDestroy().

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

214:      This only saves Vecs it cannot be used to save Mats. We recommend using the PETSCVIEWERBINARY to save objects to be loaded into MATLAB
215:      instead of this routine.


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

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

233: static PetscMPIInt Petsc_Viewer_Matlab_keyval = MPI_KEYVAL_INVALID;

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

239:      Collective

241:      Input Parameter:
242: .    comm - the MPI communicator to share the Matlab PetscViewer

244:      Level: intermediate

246:    Options Database Keys:
247: .    -viewer_matlab_filename <name>

249:    Environmental variables:
250: .   PETSC_VIEWER_MATLAB_FILENAME

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

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

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

271:   PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
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) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
275:   }
276:   MPI_Comm_get_attr(ncomm,Petsc_Viewer_Matlab_keyval,(void**)&viewer,(int*)&flg);
277:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
278:   if (!flg) { /* PetscViewer not yet created */
279:     PetscOptionsGetenv(ncomm,"PETSC_VIEWER_MATLAB_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
280:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
281:     if (!flg) {
282:       PetscStrcpy(fname,"matlaboutput.mat");
283:       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
284:     }
285:     PetscViewerMatlabOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
286:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
287:     PetscObjectRegisterDestroy((PetscObject)viewer);
288:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
289:     MPI_Comm_set_attr(ncomm,Petsc_Viewer_Matlab_keyval,(void*)viewer);
290:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
291:   }
292:   PetscCommDestroy(&ncomm);
293:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
294:   PetscFunctionReturn(viewer);
295: }