xref: /petsc/src/sys/classes/viewer/impls/matlab/vmatlab.c (revision f97672e55eacc8688507b9471cd7ec2664d7f203)
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 MATLAB 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      Notes:
25     Only writes array values on processor 0.
26 
27 @*/
28 PetscErrorCode  PetscViewerMatlabPutArray(PetscViewer mfile,int m,int n,const PetscScalar *array,const char *name)
29 {
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 {
53   PetscViewer_Matlab *ml = (PetscViewer_Matlab*)viewer->data;
54 
55   PetscFunctionBegin;
56   matPutVariable(ml->ep,name,(mxArray*)mat);
57   PetscFunctionReturn(0);
58 }
59 
60 /*@C
61     PetscViewerMatlabGetArray - Gets a variable from a MATLAB viewer into an array
62 
63     Not Collective; only processor zero reads in the array
64 
65     Input Parameters:
66 +    mfile - the MATLAB file viewer
67 .    m,n - the dimensions of the array
68 .    array - the array (represented in one dimension)
69 -    name - the name of the array
70 
71    Level: advanced
72 
73      Notes:
74     Only reads in array values on processor 0.
75 
76 @*/
77 PetscErrorCode  PetscViewerMatlabGetArray(PetscViewer mfile,int m,int n,PetscScalar *array,const char *name)
78 {
79   PetscViewer_Matlab *ml;
80   mxArray            *mat;
81 
82   PetscFunctionBegin;
83   PetscCheck(mfile,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null argument: probably PETSC_VIEWER_MATLAB_() failed");
84   ml = (PetscViewer_Matlab*)mfile->data;
85   if (!ml->rank) {
86     PetscCall(PetscInfo(mfile,"Getting MATLAB array %s\n",name));
87     mat  = matGetVariable(ml->ep,name);
88     PetscCheck(mat,PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to get array %s from matlab",name);
89     PetscCall(PetscArraycpy(array,mxGetPr(mat),m*n));
90     PetscCall(PetscInfo(mfile,"Got MATLAB array %s\n",name));
91   }
92   PetscFunctionReturn(0);
93 }
94 
95 PetscErrorCode  PetscViewerFileSetMode_Matlab(PetscViewer viewer,PetscFileMode type)
96 {
97   PetscViewer_Matlab *vmatlab = (PetscViewer_Matlab*)viewer->data;
98 
99   PetscFunctionBegin;
100   vmatlab->btype = type;
101   PetscFunctionReturn(0);
102 }
103 
104 /*
105         Actually opens the file
106 */
107 PetscErrorCode  PetscViewerFileSetName_Matlab(PetscViewer viewer,const char name[])
108 {
109   PetscViewer_Matlab *vmatlab = (PetscViewer_Matlab*)viewer->data;
110   PetscFileMode      type     = vmatlab->btype;
111 
112   PetscFunctionBegin;
113   PetscCheck(type != (PetscFileMode) -1,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
114   if (vmatlab->ep) matClose(vmatlab->ep);
115 
116   /* only first processor opens file */
117   if (!vmatlab->rank) {
118     if (type == FILE_MODE_READ) vmatlab->ep = matOpen(name,"r");
119     else if (type == FILE_MODE_WRITE) vmatlab->ep = matOpen(name,"w");
120     else PetscCheck(type != FILE_MODE_UNDEFINED,PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
121     else SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP, "Unsupported file mode %s",PetscFileModes[type]);
122   }
123   PetscFunctionReturn(0);
124 }
125 
126 PetscErrorCode PetscViewerDestroy_Matlab(PetscViewer v)
127 {
128   PetscViewer_Matlab *vf = (PetscViewer_Matlab*)v->data;
129 
130   PetscFunctionBegin;
131   if (vf->ep) matClose(vf->ep);
132   PetscCall(PetscFree(vf));
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`
168 
169 M*/
170 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Matlab(PetscViewer viewer)
171 {
172   PetscViewer_Matlab *e;
173 
174   PetscFunctionBegin;
175   PetscCall(PetscNewLog(viewer,&e));
176   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&e->rank));
177   e->btype     = FILE_MODE_UNDEFINED;
178   viewer->data = (void*) e;
179 
180   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",PetscViewerFileSetName_Matlab));
181   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Matlab));
182 
183   viewer->ops->destroy = PetscViewerDestroy_Matlab;
184   PetscFunctionReturn(0);
185 }
186 
187 /*@C
188    PetscViewerMatlabOpen - Opens a Matlab .mat file for output
189 
190    Collective
191 
192    Input Parameters:
193 +  comm - MPI communicator
194 .  name - name of file
195 -  type - type of file
196 $    FILE_MODE_WRITE - create new file for MATLAB output
197 $    FILE_MODE_READ - open existing file for MATLAB input
198 $    FILE_MODE_WRITE - open existing file for MATLAB output
199 
200    Output Parameter:
201 .  binv - PetscViewer for MATLAB output to use with the specified file
202 
203    Level: beginner
204 
205    Note: This PetscViewer should be destroyed with PetscViewerDestroy().
206 
207     For writing files it only opens the file on processor 0 in the communicator.
208 
209      This only saves Vecs it cannot be used to save Mats. We recommend using the PETSCVIEWERBINARY to save objects to be loaded into MATLAB
210      instead of this routine.
211 
212 .seealso: `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`
213           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`
214 @*/
215 PetscErrorCode  PetscViewerMatlabOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv)
216 {
217   PetscFunctionBegin;
218   PetscCall(PetscViewerCreate(comm,binv));
219   PetscCall(PetscViewerSetType(*binv,PETSCVIEWERMATLAB));
220   PetscCall(PetscViewerFileSetMode(*binv,type));
221   PetscCall(PetscViewerFileSetName(*binv,name));
222   PetscFunctionReturn(0);
223 }
224 
225 static PetscMPIInt Petsc_Viewer_Matlab_keyval = MPI_KEYVAL_INVALID;
226 
227 /*@C
228      PETSC_VIEWER_MATLAB_ - Creates a Matlab PetscViewer shared by all processors
229                      in a communicator.
230 
231      Collective
232 
233      Input Parameter:
234 .    comm - the MPI communicator to share the Matlab PetscViewer
235 
236      Level: intermediate
237 
238    Options Database Keys:
239 .    -viewer_matlab_filename <name> - name of the Matlab file
240 
241    Environmental variables:
242 .   PETSC_VIEWER_MATLAB_FILENAME - name of the Matlab file
243 
244      Notes:
245      Unlike almost all other PETSc routines, PETSC_VIEWER_MATLAB_ does not return
246      an error code.  The matlab PetscViewer is usually used in the form
247 $       XXXView(XXX object,PETSC_VIEWER_MATLAB_(comm));
248 
249      Use PETSC_VIEWER_SOCKET_() or PetscViewerSocketOpen() to communicator with an interactive MATLAB session.
250 
251 .seealso: `PETSC_VIEWER_MATLAB_WORLD`, `PETSC_VIEWER_MATLAB_SELF`, `PetscViewerMatlabOpen()`, `PetscViewerCreate()`,
252           `PetscViewerDestroy()`
253 @*/
254 PetscViewer  PETSC_VIEWER_MATLAB_(MPI_Comm comm)
255 {
256   PetscErrorCode ierr;
257   PetscBool      flg;
258   PetscViewer    viewer;
259   char           fname[PETSC_MAX_PATH_LEN];
260   MPI_Comm       ncomm;
261 
262   PetscFunctionBegin;
263   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
264   if (Petsc_Viewer_Matlab_keyval == MPI_KEYVAL_INVALID) {
265     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Matlab_keyval,0);
266     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
267   }
268   ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_Matlab_keyval,(void**)&viewer,(int*)&flg);
269   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
270   if (!flg) { /* PetscViewer not yet created */
271     ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_MATLAB_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
272     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
273     if (!flg) {
274       ierr = PetscStrcpy(fname,"matlaboutput.mat");
275       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
276     }
277     ierr = PetscViewerMatlabOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
278     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
279     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
280     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
281     ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_Matlab_keyval,(void*)viewer);
282     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
283   }
284   ierr = PetscCommDestroy(&ncomm);
285   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
286   PetscFunctionReturn(viewer);
287 }
288