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