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