xref: /petsc/src/sys/classes/viewer/impls/mathematica/mathematica.c (revision fe8e7ddd93caa3d7f6fe6c2e358c1c3f5a39763e)
1 #include <petsc/private/viewerimpl.h> /* "petscsys.h" */
2 #include <petsc/private/pcimpl.h>
3 #include <../src/mat/impls/aij/seq/aij.h>
4 #include <mathematica.h>
5 
6 #if defined(PETSC_HAVE__SNPRINTF) && !defined(PETSC_HAVE_SNPRINTF)
7   #define snprintf _snprintf
8 #endif
9 
10 PetscViewer  PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE = NULL;
11 static void *mathematicaEnv                         = NULL;
12 
13 static PetscBool PetscViewerMathematicaPackageInitialized = PETSC_FALSE;
14 /*@C
15   PetscViewerMathematicaFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
16   called from PetscFinalize().
17 
18   Level: developer
19 
20 .seealso: `PetscFinalize()`
21 @*/
22 PetscErrorCode PetscViewerMathematicaFinalizePackage(void)
23 {
24   PetscFunctionBegin;
25   if (mathematicaEnv) MLDeinitialize((MLEnvironment)mathematicaEnv);
26   PetscViewerMathematicaPackageInitialized = PETSC_TRUE;
27   PetscFunctionReturn(PETSC_SUCCESS);
28 }
29 
30 /*@C
31   PetscViewerMathematicaInitializePackage - This function initializes everything in the Petsc interface to Mathematica. It is
32   called from `PetscViewerInitializePackage()`.
33 
34   Level: developer
35 
36 .seealso: `PetscSysInitializePackage()`, `PetscInitialize()`
37 @*/
38 PetscErrorCode PetscViewerMathematicaInitializePackage(void)
39 {
40   PetscError ierr;
41 
42   PetscFunctionBegin;
43   if (PetscViewerMathematicaPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
44   PetscViewerMathematicaPackageInitialized = PETSC_TRUE;
45 
46   mathematicaEnv = (void *)MLInitialize(0);
47 
48   PetscCall(PetscRegisterFinalize(PetscViewerMathematicaFinalizePackage));
49   PetscFunctionReturn(PETSC_SUCCESS);
50 }
51 
52 static PetscErrorCode PetscViewerInitializeMathematicaWorld_Private()
53 {
54   PetscFunctionBegin;
55   if (PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE) PetscFunctionReturn(PETSC_SUCCESS);
56   PetscCall(PetscViewerMathematicaOpen(PETSC_COMM_WORLD, PETSC_DECIDE, NULL, NULL, &PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE));
57   PetscFunctionReturn(PETSC_SUCCESS);
58 }
59 
60 static PetscErrorCode PetscViewerDestroy_Mathematica(PetscViewer viewer)
61 {
62   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
63 
64   PetscFunctionBegin;
65   MLClose(vmath->link);
66   PetscCall(PetscFree(vmath->linkname));
67   PetscCall(PetscFree(vmath->linkhost));
68   PetscCall(PetscFree(vmath));
69   PetscFunctionReturn(PETSC_SUCCESS);
70 }
71 
72 static PetscErrorCode PetscViewerDestroyMathematica_Private(void)
73 {
74   PetscFunctionBegin;
75   if (PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE) PetscCall(PetscViewerDestroy(PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE));
76   PetscFunctionReturn(PETSC_SUCCESS);
77 }
78 
79 static PetscErrorCode PetscViewerMathematicaSetupConnection_Private(PetscViewer v)
80 {
81   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data;
82 #if defined(MATHEMATICA_3_0)
83   int   argc = 6;
84   char *argv[6];
85 #else
86   int   argc = 5;
87   char *argv[5];
88 #endif
89   char hostname[256];
90   long lerr;
91 
92   PetscFunctionBegin;
93   /* Link name */
94   argv[0] = "-linkname";
95   if (!vmath->linkname) argv[1] = "math -mathlink";
96   else argv[1] = vmath->linkname;
97 
98   /* Link host */
99   argv[2] = "-linkhost";
100   if (!vmath->linkhost) {
101     PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
102     argv[3] = hostname;
103   } else argv[3] = vmath->linkhost;
104 
105     /* Link mode */
106 #if defined(MATHEMATICA_3_0)
107   argv[4] = "-linkmode";
108   switch (vmath->linkmode) {
109   case MATHEMATICA_LINK_CREATE:
110     argv[5] = "Create";
111     break;
112   case MATHEMATICA_LINK_CONNECT:
113     argv[5] = "Connect";
114     break;
115   case MATHEMATICA_LINK_LAUNCH:
116     argv[5] = "Launch";
117     break;
118   }
119 #else
120   switch (vmath->linkmode) {
121   case MATHEMATICA_LINK_CREATE:
122     argv[4] = "-linkcreate";
123     break;
124   case MATHEMATICA_LINK_CONNECT:
125     argv[4] = "-linkconnect";
126     break;
127   case MATHEMATICA_LINK_LAUNCH:
128     argv[4] = "-linklaunch";
129     break;
130   }
131 #endif
132   vmath->link = MLOpenInEnv(mathematicaEnv, argc, argv, &lerr);
133 #endif
134   PetscFunctionReturn(PETSC_SUCCESS);
135 }
136 
137 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Mathematica(PetscViewer v)
138 {
139   PetscViewer_Mathematica *vmath;
140 
141   PetscFunctionBegin;
142   PetscCall(PetscViewerMathematicaInitializePackage());
143 
144   PetscCall(PetscNew(&vmath));
145   v->data         = (void *)vmath;
146   v->ops->destroy = PetscViewerDestroy_Mathematica;
147   v->ops->flush   = 0;
148   PetscCall(PetscStrallocpy(PETSC_VIEWER_MATHEMATICA, &((PetscObject)v)->type_name));
149 
150   vmath->linkname     = NULL;
151   vmath->linkhost     = NULL;
152   vmath->linkmode     = MATHEMATICA_LINK_CONNECT;
153   vmath->graphicsType = GRAPHICS_MOTIF;
154   vmath->plotType     = MATHEMATICA_TRIANGULATION_PLOT;
155   vmath->objName      = NULL;
156 
157   PetscCall(PetscViewerMathematicaSetFromOptions(v));
158   PetscCall(PetscViewerMathematicaSetupConnection_Private(v));
159   PetscFunctionReturn(PETSC_SUCCESS);
160 }
161 
162 static PetscErrorCode PetscViewerMathematicaParseLinkMode(char *modename, LinkMode *mode)
163 {
164   PetscBool isCreate, isConnect, isLaunch;
165 
166   PetscFunctionBegin;
167   PetscCall(PetscStrcasecmp(modename, "Create", &isCreate));
168   PetscCall(PetscStrcasecmp(modename, "Connect", &isConnect));
169   PetscCall(PetscStrcasecmp(modename, "Launch", &isLaunch));
170   if (isCreate) *mode = MATHEMATICA_LINK_CREATE;
171   else if (isConnect) *mode = MATHEMATICA_LINK_CONNECT;
172   else if (isLaunch) *mode = MATHEMATICA_LINK_LAUNCH;
173   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid Mathematica link mode: %s", modename);
174   PetscFunctionReturn(PETSC_SUCCESS);
175 }
176 
177 PetscErrorCode PetscViewerMathematicaSetFromOptions(PetscViewer v)
178 {
179   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data;
180   char                     linkname[256];
181   char                     modename[256];
182   char                     hostname[256];
183   char                     type[256];
184   PetscInt                 numPorts;
185   PetscInt                *ports;
186   PetscInt                 numHosts;
187   int                      h;
188   char                   **hosts;
189   PetscMPIInt              size, rank;
190   PetscBool                opt;
191 
192   PetscFunctionBegin;
193   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)v), &size));
194   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)v), &rank));
195 
196   /* Get link name */
197   PetscCall(PetscOptionsGetString("viewer_", "-math_linkname", linkname, sizeof(linkname), &opt));
198   if (opt) PetscCall(PetscViewerMathematicaSetLinkName(v, linkname));
199   /* Get link port */
200   numPorts = size;
201   PetscCall(PetscMalloc1(size, &ports));
202   PetscCall(PetscOptionsGetIntArray("viewer_", "-math_linkport", ports, &numPorts, &opt));
203   if (opt) {
204     if (numPorts > rank) snprintf(linkname, sizeof(linkname), "%6d", ports[rank]);
205     else snprintf(linkname, sizeof(linkname), "%6d", ports[0]);
206     PetscCall(PetscViewerMathematicaSetLinkName(v, linkname));
207   }
208   PetscCall(PetscFree(ports));
209   /* Get link host */
210   numHosts = size;
211   PetscCall(PetscMalloc1(size, &hosts));
212   PetscCall(PetscOptionsGetStringArray("viewer_", "-math_linkhost", hosts, &numHosts, &opt));
213   if (opt) {
214     if (numHosts > rank) {
215       PetscCall(PetscStrncpy(hostname, hosts[rank], sizeof(hostname)));
216     } else {
217       PetscCall(PetscStrncpy(hostname, hosts[0], sizeof(hostname)));
218     }
219     PetscCall(PetscViewerMathematicaSetLinkHost(v, hostname));
220   }
221   for (h = 0; h < numHosts; h++) PetscCall(PetscFree(hosts[h]));
222   PetscCall(PetscFree(hosts));
223   /* Get link mode */
224   PetscCall(PetscOptionsGetString("viewer_", "-math_linkmode", modename, sizeof(modename), &opt));
225   if (opt) {
226     LinkMode mode;
227 
228     PetscCall(PetscViewerMathematicaParseLinkMode(modename, &mode));
229     PetscCall(PetscViewerMathematicaSetLinkMode(v, mode));
230   }
231   /* Get graphics type */
232   PetscCall(PetscOptionsGetString("viewer_", "-math_graphics", type, sizeof(type), &opt));
233   if (opt) {
234     PetscBool isMotif, isPS, isPSFile;
235 
236     PetscCall(PetscStrcasecmp(type, "Motif", &isMotif));
237     PetscCall(PetscStrcasecmp(type, "PS", &isPS));
238     PetscCall(PetscStrcasecmp(type, "PSFile", &isPSFile));
239     if (isMotif) vmath->graphicsType = GRAPHICS_MOTIF;
240     else if (isPS) vmath->graphicsType = GRAPHICS_PS_STDOUT;
241     else if (isPSFile) vmath->graphicsType = GRAPHICS_PS_FILE;
242   }
243   /* Get plot type */
244   PetscCall(PetscOptionsGetString("viewer_", "-math_type", type, sizeof(type), &opt));
245   if (opt) {
246     PetscBool isTri, isVecTri, isVec, isSurface;
247 
248     PetscCall(PetscStrcasecmp(type, "Triangulation", &isTri));
249     PetscCall(PetscStrcasecmp(type, "VectorTriangulation", &isVecTri));
250     PetscCall(PetscStrcasecmp(type, "Vector", &isVec));
251     PetscCall(PetscStrcasecmp(type, "Surface", &isSurface));
252     if (isTri) vmath->plotType = MATHEMATICA_TRIANGULATION_PLOT;
253     else if (isVecTri) vmath->plotType = MATHEMATICA_VECTOR_TRIANGULATION_PLOT;
254     else if (isVec) vmath->plotType = MATHEMATICA_VECTOR_PLOT;
255     else if (isSurface) vmath->plotType = MATHEMATICA_SURFACE_PLOT;
256   }
257   PetscFunctionReturn(PETSC_SUCCESS);
258 }
259 
260 PetscErrorCode PetscViewerMathematicaSetLinkName(PetscViewer v, const char *name)
261 {
262   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data;
263 
264   PetscFunctionBegin;
265   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1);
266   PetscAssertPointer(name, 2);
267   PetscCall(PetscStrallocpy(name, &vmath->linkname));
268   PetscFunctionReturn(PETSC_SUCCESS);
269 }
270 
271 PetscErrorCode PetscViewerMathematicaSetLinkPort(PetscViewer v, int port)
272 {
273   char name[16];
274 
275   PetscFunctionBegin;
276   snprintf(name, 16, "%6d", port);
277   PetscCall(PetscViewerMathematicaSetLinkName(v, name));
278   PetscFunctionReturn(PETSC_SUCCESS);
279 }
280 
281 PetscErrorCode PetscViewerMathematicaSetLinkHost(PetscViewer v, const char *host)
282 {
283   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data;
284 
285   PetscFunctionBegin;
286   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1);
287   PetscAssertPointer(host, 2);
288   PetscCall(PetscStrallocpy(host, &vmath->linkhost));
289   PetscFunctionReturn(PETSC_SUCCESS);
290 }
291 
292 PetscErrorCode PetscViewerMathematicaSetLinkMode(PetscViewer v, LinkMode mode)
293 {
294   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data;
295 
296   PetscFunctionBegin;
297   vmath->linkmode = mode;
298   PetscFunctionReturn(PETSC_SUCCESS);
299 }
300 
301 /*----------------------------------------- Public Functions --------------------------------------------------------*/
302 /*@C
303   PetscViewerMathematicaOpen - Communicates with Mathemtica using MathLink.
304 
305   Collective
306 
307   Input Parameters:
308 + comm    - The MPI communicator
309 . port    - [optional] The port to connect on, or PETSC_DECIDE
310 . machine - [optional] The machine to run Mathematica on, or NULL
311 - mode    - [optional] The connection mode, or NULL
312 
313   Output Parameter:
314 . v - The Mathematica viewer
315 
316   Options Database Keys:
317 + -viewer_math_linkhost <machine> - The host machine for the kernel
318 . -viewer_math_linkname <name>    - The full link name for the connection
319 . -viewer_math_linkport <port>    - The port for the connection
320 . -viewer_math_mode <mode>        - The mode, e.g. Launch, Connect
321 . -viewer_math_type <type>        - The plot type, e.g. Triangulation, Vector
322 - -viewer_math_graphics <output>  - The output type, e.g. Motif, PS, PSFile
323 
324   Level: intermediate
325 
326   Note:
327   Most users should employ the following commands to access the
328   Mathematica viewers
329 .vb
330     PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer)
331     MatView(Mat matrix, PetscViewer viewer)
332 
333                 or
334 
335     PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer)
336     VecView(Vec vector, PetscViewer viewer)
337 .ve
338 
339 .seealso: `PETSCVIEWERMATHEMATICA`, `MatView()`, `VecView()`
340 @*/
341 PetscErrorCode PetscViewerMathematicaOpen(MPI_Comm comm, int port, const char machine[], const char mode[], PetscViewer *v)
342 {
343   PetscFunctionBegin;
344   PetscCall(PetscViewerCreate(comm, v));
345 #if 0
346   LinkMode linkmode;
347   PetscCall(PetscViewerMathematicaSetLinkPort(*v, port));
348   PetscCall(PetscViewerMathematicaSetLinkHost(*v, machine));
349   PetscCall(PetscViewerMathematicaParseLinkMode(mode, &linkmode));
350   PetscCall(PetscViewerMathematicaSetLinkMode(*v, linkmode));
351 #endif
352   PetscCall(PetscViewerSetType(*v, PETSC_VIEWER_MATHEMATICA));
353   PetscFunctionReturn(PETSC_SUCCESS);
354 }
355 
356 /*
357   PetscViewerMathematicaGetLink - Returns the link to Mathematica from a `PETSCVIEWERMATHEMATICA`
358 
359   Input Parameters:
360 + viewer - The Mathematica viewer
361 - link   - The link to Mathematica
362 
363   Level: intermediate
364 
365 .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaOpen()`
366 */
367 static PetscErrorCode PetscViewerMathematicaGetLink(PetscViewer viewer, MLINK *link)
368 {
369   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
370 
371   PetscFunctionBegin;
372   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
373   *link = vmath->link;
374   PetscFunctionReturn(PETSC_SUCCESS);
375 }
376 
377 /*@C
378   PetscViewerMathematicaSkipPackets - Discard packets sent by Mathematica until a certain packet type is received
379 
380   Input Parameters:
381 + viewer - The Mathematica viewer
382 - type   - The packet type to search for, e.g RETURNPKT
383 
384   Level: advanced
385 
386 .seealso: `PetscViewerMathematicaSetName()`, `PetscViewerMathematicaGetVector()`
387 @*/
388 PetscErrorCode PetscViewerMathematicaSkipPackets(PetscViewer viewer, int type)
389 {
390   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
391   MLINK                    link  = vmath->link; /* The link to Mathematica */
392   int                      pkt;                 /* The packet type */
393 
394   PetscFunctionBegin;
395   while ((pkt = MLNextPacket(link)) && (pkt != type)) MLNewPacket(link);
396   if (!pkt) {
397     MLClearError(link);
398     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, (char *)MLErrorMessage(link));
399   }
400   PetscFunctionReturn(PETSC_SUCCESS);
401 }
402 
403 /*@C
404   PetscViewerMathematicaGetName - Retrieve the default name for objects communicated to Mathematica via `PETSCVIEWERMATHEMATICA`
405 
406   Input Parameter:
407 . viewer - The Mathematica viewer
408 
409   Output Parameter:
410 . name - The name for new objects created in Mathematica
411 
412   Level: intermediate
413 
414 .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaSetName()`, `PetscViewerMathematicaClearName()`
415 @*/
416 PetscErrorCode PetscViewerMathematicaGetName(PetscViewer viewer, const char **name)
417 {
418   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
419 
420   PetscFunctionBegin;
421   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
422   PetscAssertPointer(name, 2);
423   *name = vmath->objName;
424   PetscFunctionReturn(PETSC_SUCCESS);
425 }
426 
427 /*@C
428   PetscViewerMathematicaSetName - Override the default name for objects communicated to Mathematica via `PETSCVIEWERMATHEMATICA`
429 
430   Input Parameters:
431 + viewer - The Mathematica viewer
432 - name   - The name for new objects created in Mathematica
433 
434   Level: intermediate
435 
436 .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaClearName()`
437 @*/
438 PetscErrorCode PetscViewerMathematicaSetName(PetscViewer viewer, const char name[])
439 {
440   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
441 
442   PetscFunctionBegin;
443   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
444   PetscAssertPointer(name, 2);
445   vmath->objName = name;
446   PetscFunctionReturn(PETSC_SUCCESS);
447 }
448 
449 /*@
450   PetscViewerMathematicaClearName - Use the default name for objects communicated to Mathematica
451 
452   Input Parameter:
453 . viewer - The Mathematica viewer
454 
455   Level: intermediate
456 
457 .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaGetName()`, `PetscViewerMathematicaSetName()`
458 @*/
459 PetscErrorCode PetscViewerMathematicaClearName(PetscViewer viewer)
460 {
461   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
462 
463   PetscFunctionBegin;
464   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
465   vmath->objName = NULL;
466   PetscFunctionReturn(PETSC_SUCCESS);
467 }
468 
469 /*@
470   PetscViewerMathematicaGetVector - Retrieve a vector from Mathematica via a `PETSCVIEWERMATHEMATICA`
471 
472   Input Parameter:
473 . viewer - The Mathematica viewer
474 
475   Output Parameter:
476 . v - The vector
477 
478   Level: intermediate
479 
480 .seealso: `PETSCVIEWERMATHEMATICA`, `VecView()`, `PetscViewerMathematicaPutVector()`
481 @*/
482 PetscErrorCode PetscViewerMathematicaGetVector(PetscViewer viewer, Vec v)
483 {
484   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
485   MLINK                    link; /* The link to Mathematica */
486   char                    *name;
487   PetscScalar             *mArray, *array;
488   long                     mSize;
489   int                      n;
490 
491   PetscFunctionBegin;
492   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
493   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
494 
495   /* Determine the object name */
496   if (!vmath->objName) name = "vec";
497   else name = (char *)vmath->objName;
498 
499   link = vmath->link;
500   PetscCall(VecGetLocalSize(v, &n));
501   PetscCall(VecGetArray(v, &array));
502   MLPutFunction(link, "EvaluatePacket", 1);
503   MLPutSymbol(link, name);
504   MLEndPacket(link);
505   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
506   MLGetRealList(link, &mArray, &mSize);
507   PetscCheck(n == mSize, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Incompatible vector sizes %d %d", n, mSize);
508   PetscCall(PetscArraycpy(array, mArray, mSize));
509   MLDisownRealList(link, mArray, mSize);
510   PetscCall(VecRestoreArray(v, &array));
511   PetscFunctionReturn(PETSC_SUCCESS);
512 }
513 
514 /*@
515   PetscViewerMathematicaPutVector - Send a vector to Mathematica via a `PETSCVIEWERMATHEMATICA` `PetscViewer`
516 
517   Input Parameters:
518 + viewer - The Mathematica viewer
519 - v      - The vector
520 
521   Level: intermediate
522 
523 .seealso: `PETSCVIEWERMATHEMATICA`, `VecView()`, `PetscViewerMathematicaGetVector()`
524 @*/
525 PetscErrorCode PetscViewerMathematicaPutVector(PetscViewer viewer, Vec v)
526 {
527   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
528   MLINK                    link  = vmath->link; /* The link to Mathematica */
529   char                    *name;
530   PetscScalar             *array;
531   int                      n;
532 
533   PetscFunctionBegin;
534   /* Determine the object name */
535   if (!vmath->objName) name = "vec";
536   else name = (char *)vmath->objName;
537 
538   PetscCall(VecGetLocalSize(v, &n));
539   PetscCall(VecGetArray(v, &array));
540 
541   /* Send the Vector object */
542   MLPutFunction(link, "EvaluatePacket", 1);
543   MLPutFunction(link, "Set", 2);
544   MLPutSymbol(link, name);
545   MLPutRealList(link, array, n);
546   MLEndPacket(link);
547   /* Skip packets until ReturnPacket */
548   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
549   /* Skip ReturnPacket */
550   MLNewPacket(link);
551 
552   PetscCall(VecRestoreArray(v, &array));
553   PetscFunctionReturn(PETSC_SUCCESS);
554 }
555 
556 PetscErrorCode PetscViewerMathematicaPutMatrix(PetscViewer viewer, int m, int n, PetscReal *a)
557 {
558   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
559   MLINK                    link  = vmath->link; /* The link to Mathematica */
560   char                    *name;
561 
562   PetscFunctionBegin;
563   /* Determine the object name */
564   if (!vmath->objName) name = "mat";
565   else name = (char *)vmath->objName;
566 
567   /* Send the dense matrix object */
568   MLPutFunction(link, "EvaluatePacket", 1);
569   MLPutFunction(link, "Set", 2);
570   MLPutSymbol(link, name);
571   MLPutFunction(link, "Transpose", 1);
572   MLPutFunction(link, "Partition", 2);
573   MLPutRealList(link, a, m * n);
574   MLPutInteger(link, m);
575   MLEndPacket(link);
576   /* Skip packets until ReturnPacket */
577   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
578   /* Skip ReturnPacket */
579   MLNewPacket(link);
580   PetscFunctionReturn(PETSC_SUCCESS);
581 }
582 
583 PetscErrorCode PetscViewerMathematicaPutCSRMatrix(PetscViewer viewer, int m, int n, int *i, int *j, PetscReal *a)
584 {
585   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
586   MLINK                    link  = vmath->link; /* The link to Mathematica */
587   const char              *symbol;
588   char                    *name;
589   PetscBool                match;
590 
591   PetscFunctionBegin;
592   /* Determine the object name */
593   if (!vmath->objName) name = "mat";
594   else name = (char *)vmath->objName;
595 
596   /* Make sure Mathematica recognizes sparse matrices */
597   MLPutFunction(link, "EvaluatePacket", 1);
598   MLPutFunction(link, "Needs", 1);
599   MLPutString(link, "LinearAlgebra`CSRMatrix`");
600   MLEndPacket(link);
601   /* Skip packets until ReturnPacket */
602   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
603   /* Skip ReturnPacket */
604   MLNewPacket(link);
605 
606   /* Send the CSRMatrix object */
607   MLPutFunction(link, "EvaluatePacket", 1);
608   MLPutFunction(link, "Set", 2);
609   MLPutSymbol(link, name);
610   MLPutFunction(link, "CSRMatrix", 5);
611   MLPutInteger(link, m);
612   MLPutInteger(link, n);
613   MLPutFunction(link, "Plus", 2);
614   MLPutIntegerList(link, i, m + 1);
615   MLPutInteger(link, 1);
616   MLPutFunction(link, "Plus", 2);
617   MLPutIntegerList(link, j, i[m]);
618   MLPutInteger(link, 1);
619   MLPutRealList(link, a, i[m]);
620   MLEndPacket(link);
621   /* Skip packets until ReturnPacket */
622   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
623   /* Skip ReturnPacket */
624   MLNewPacket(link);
625 
626   /* Check that matrix is valid */
627   MLPutFunction(link, "EvaluatePacket", 1);
628   MLPutFunction(link, "ValidQ", 1);
629   MLPutSymbol(link, name);
630   MLEndPacket(link);
631   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
632   MLGetSymbol(link, &symbol);
633   PetscCall(PetscStrcmp("True", (char *)symbol, &match));
634   if (!match) {
635     MLDisownSymbol(link, symbol);
636     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid CSR matrix in Mathematica");
637   }
638   MLDisownSymbol(link, symbol);
639   /* Skip ReturnPacket */
640   MLNewPacket(link);
641   PetscFunctionReturn(PETSC_SUCCESS);
642 }
643