Actual source code: mathematica.c

petsc-3.10.5 2019-03-28
Report Typos and Errors

  2:  #include <petsc/private/viewerimpl.h>
  3:  #include <petsc/private/pcimpl.h>
  4:  #include <../src/mat/impls/aij/seq/aij.h>
  5:  #include <mathematica.h>

  7: #if defined(PETSC_HAVE__SNPRINTF) && !defined(PETSC_HAVE_SNPRINTF)
  8: #define snprintf _snprintf
  9: #endif

 11: PetscViewer PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE = NULL;
 12: static void *mathematicaEnv                        = NULL;

 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().

 19:   Level: developer

 21: .keywords: Petsc, destroy, package, mathematica
 22: .seealso: PetscFinalize()
 23: @*/
 24: PetscErrorCode  PetscViewerMathematicaFinalizePackage(void)
 25: {
 27:   if (mathematicaEnv) MLDeinitialize((MLEnvironment) mathematicaEnv);
 28:   PetscViewerMathematicaPackageInitialized = PETSC_TRUE;
 29:   return(0);
 30: }

 32: /*@C
 33:   PetscViewerMathematicaInitializePackage - This function initializes everything in the Petsc interface to Mathematica. It is
 34:   called from PetscDLLibraryRegister() when using dynamic libraries, and on the call to PetscInitialize()
 35:   when using static libraries.

 37:   Level: developer

 39: .keywords: Petsc, initialize, package
 40: .seealso: PetscSysInitializePackage(), PetscInitialize()
 41: @*/
 42: PetscErrorCode  PetscViewerMathematicaInitializePackage(void)
 43: {
 44:   PetscError ierr;

 47:   if (PetscViewerMathematicaPackageInitialized) return(0);
 48:   PetscViewerMathematicaPackageInitialized = PETSC_TRUE;

 50:   mathematicaEnv = (void*) MLInitialize(0);

 52:   PetscRegisterFinalize(PetscViewerMathematicaFinalizePackage);
 53:   return(0);
 54: }


 57: PetscErrorCode PetscViewerInitializeMathematicaWorld_Private()
 58: {

 62:   if (PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE) return(0);
 63:   PetscViewerMathematicaOpen(PETSC_COMM_WORLD, PETSC_DECIDE, NULL, NULL, &PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE);
 64:   return(0);
 65: }

 67: static PetscErrorCode PetscViewerDestroy_Mathematica(PetscViewer viewer)
 68: {
 69:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
 70:   PetscErrorCode          ierr;

 73:   MLClose(vmath->link);
 74:   PetscFree(vmath->linkname);
 75:   PetscFree(vmath->linkhost);
 76:   PetscFree(vmath);
 77:   return(0);
 78: }

 80: PetscErrorCode PetscViewerDestroyMathematica_Private(void)
 81: {

 85:   if (PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE) {
 86:     PetscViewerDestroy(PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE);
 87:   }
 88:   return(0);
 89: }

 91: PetscErrorCode PetscViewerMathematicaSetupConnection_Private(PetscViewer v)
 92: {
 93:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
 94: #if defined(MATHEMATICA_3_0)
 95:   int                     argc = 6;
 96:   char                    *argv[6];
 97: #else
 98:   int                     argc = 5;
 99:   char                    *argv[5];
100: #endif
101:   char                    hostname[256];
102:   long                    lerr;
103:   PetscErrorCode          ierr;

106:   /* Link name */
107:   argv[0] = "-linkname";
108:   if (!vmath->linkname) argv[1] = "math -mathlink";
109:   else                  argv[1] = vmath->linkname;

111:   /* Link host */
112:   argv[2] = "-linkhost";
113:   if (!vmath->linkhost) {
114:     PetscGetHostName(hostname, 255);
115:     argv[3] = hostname;
116:   } else argv[3] = vmath->linkhost;

118:   /* Link mode */
119: #if defined(MATHEMATICA_3_0)
120:   argv[4] = "-linkmode";
121:   switch (vmath->linkmode) {
122:   case MATHEMATICA_LINK_CREATE:
123:     argv[5] = "Create";
124:     break;
125:   case MATHEMATICA_LINK_CONNECT:
126:     argv[5] = "Connect";
127:     break;
128:   case MATHEMATICA_LINK_LAUNCH:
129:     argv[5] = "Launch";
130:     break;
131:   }
132: #else
133:   switch (vmath->linkmode) {
134:   case MATHEMATICA_LINK_CREATE:
135:     argv[4] = "-linkcreate";
136:     break;
137:   case MATHEMATICA_LINK_CONNECT:
138:     argv[4] = "-linkconnect";
139:     break;
140:   case MATHEMATICA_LINK_LAUNCH:
141:     argv[4] = "-linklaunch";
142:     break;
143:   }
144: #endif
145:   vmath->link = MLOpenInEnv(mathematicaEnv, argc, argv, &lerr);
146: #endif
147:   return(0);
148: }

150: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Mathematica(PetscViewer v)
151: {
152:   PetscViewer_Mathematica *vmath;
153:   PetscErrorCode          ierr;

156:   PetscViewerMathematicaInitializePackage();

158:   PetscNewLog(v,&vmath);
159:   v->data         = (void*) vmath;
160:   v->ops->destroy = PetscViewerDestroy_Mathematica;
161:   v->ops->flush   = 0;
162:   PetscStrallocpy(PETSC_VIEWER_MATHEMATICA, &((PetscObject)v)->type_name);

164:   vmath->linkname     = NULL;
165:   vmath->linkhost     = NULL;
166:   vmath->linkmode     = MATHEMATICA_LINK_CONNECT;
167:   vmath->graphicsType = GRAPHICS_MOTIF;
168:   vmath->plotType     = MATHEMATICA_TRIANGULATION_PLOT;
169:   vmath->objName      = NULL;

171:   PetscViewerMathematicaSetFromOptions(v);
172:   PetscViewerMathematicaSetupConnection_Private(v);
173:   return(0);
174: }

176: static PetscErrorCode PetscViewerMathematicaParseLinkMode(char *modename, LinkMode *mode)
177: {
178:   PetscBool      isCreate, isConnect, isLaunch;

182:   PetscStrcasecmp(modename, "Create",  &isCreate);
183:   PetscStrcasecmp(modename, "Connect", &isConnect);
184:   PetscStrcasecmp(modename, "Launch",  &isLaunch);
185:   if (isCreate)       *mode = MATHEMATICA_LINK_CREATE;
186:   else if (isConnect) *mode = MATHEMATICA_LINK_CONNECT;
187:   else if (isLaunch)  *mode = MATHEMATICA_LINK_LAUNCH;
188:   else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG, "Invalid Mathematica link mode: %s", modename);
189:   return(0);
190: }

192: PetscErrorCode  PetscViewerMathematicaSetFromOptions(PetscViewer v)
193: {
194:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
195:   char                    linkname[256];
196:   char                    modename[256];
197:   char                    hostname[256];
198:   char                    type[256];
199:   PetscInt                numPorts;
200:   PetscInt                *ports;
201:   PetscInt                numHosts;
202:   int                     h;
203:   char                    **hosts;
204:   PetscMPIInt             size, rank;
205:   PetscBool               opt;
206:   PetscErrorCode          ierr;

209:   MPI_Comm_size(PetscObjectComm((PetscObject)v), &size);
210:   MPI_Comm_rank(PetscObjectComm((PetscObject)v), &rank);

212:   /* Get link name */
213:   PetscOptionsGetString("viewer_", "-math_linkname", linkname, 256, &opt);
214:   if (opt) {
215:     PetscViewerMathematicaSetLinkName(v, linkname);
216:   }
217:   /* Get link port */
218:   numPorts = size;
219:   PetscMalloc1(size, &ports);
220:   PetscOptionsGetIntArray("viewer_", "-math_linkport", ports, &numPorts, &opt);
221:   if (opt) {
222:     if (numPorts > rank) snprintf(linkname, 255, "%6d", ports[rank]);
223:     else                 snprintf(linkname, 255, "%6d", ports[0]);
224:     PetscViewerMathematicaSetLinkName(v, linkname);
225:   }
226:   PetscFree(ports);
227:   /* Get link host */
228:   numHosts = size;
229:   PetscMalloc1(size, &hosts);
230:   PetscOptionsGetStringArray("viewer_", "-math_linkhost", hosts, &numHosts, &opt);
231:   if (opt) {
232:     if (numHosts > rank) {
233:       PetscStrncpy(hostname, hosts[rank], 255);
234:     } else {
235:       PetscStrncpy(hostname, hosts[0], 255);
236:     }
237:     PetscViewerMathematicaSetLinkHost(v, hostname);
238:   }
239:   for (h = 0; h < numHosts; h++) {
240:     PetscFree(hosts[h]);
241:   }
242:   PetscFree(hosts);
243:   /* Get link mode */
244:   PetscOptionsGetString("viewer_", "-math_linkmode", modename, 256, &opt);
245:   if (opt) {
246:     LinkMode mode;

248:     PetscViewerMathematicaParseLinkMode(modename, &mode);
249:     PetscViewerMathematicaSetLinkMode(v, mode);
250:   }
251:   /* Get graphics type */
252:   PetscOptionsGetString("viewer_", "-math_graphics", type, 256, &opt);
253:   if (opt) {
254:     PetscBool isMotif, isPS, isPSFile;

256:     PetscStrcasecmp(type, "Motif",  &isMotif);
257:     PetscStrcasecmp(type, "PS",     &isPS);
258:     PetscStrcasecmp(type, "PSFile", &isPSFile);
259:     if (isMotif)       vmath->graphicsType = GRAPHICS_MOTIF;
260:     else if (isPS)     vmath->graphicsType = GRAPHICS_PS_STDOUT;
261:     else if (isPSFile) vmath->graphicsType = GRAPHICS_PS_FILE;
262:   }
263:   /* Get plot type */
264:   PetscOptionsGetString("viewer_", "-math_type", type, 256, &opt);
265:   if (opt) {
266:     PetscBool isTri, isVecTri, isVec, isSurface;

268:     PetscStrcasecmp(type, "Triangulation",       &isTri);
269:     PetscStrcasecmp(type, "VectorTriangulation", &isVecTri);
270:     PetscStrcasecmp(type, "Vector",              &isVec);
271:     PetscStrcasecmp(type, "Surface",             &isSurface);
272:     if (isTri)          vmath->plotType = MATHEMATICA_TRIANGULATION_PLOT;
273:     else if (isVecTri)  vmath->plotType = MATHEMATICA_VECTOR_TRIANGULATION_PLOT;
274:     else if (isVec)     vmath->plotType = MATHEMATICA_VECTOR_PLOT;
275:     else if (isSurface) vmath->plotType = MATHEMATICA_SURFACE_PLOT;
276:   }
277:   return(0);
278: }

280: PetscErrorCode  PetscViewerMathematicaSetLinkName(PetscViewer v, const char *name)
281: {
282:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
283:   PetscErrorCode          ierr;

288:   PetscStrallocpy(name, &vmath->linkname);
289:   return(0);
290: }

292: PetscErrorCode  PetscViewerMathematicaSetLinkPort(PetscViewer v, int port)
293: {
294:   char           name[16];

298:   snprintf(name, 16, "%6d", port);
299:   PetscViewerMathematicaSetLinkName(v, name);
300:   return(0);
301: }

303: PetscErrorCode  PetscViewerMathematicaSetLinkHost(PetscViewer v, const char *host)
304: {
305:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
306:   PetscErrorCode          ierr;

311:   PetscStrallocpy(host, &vmath->linkhost);
312:   return(0);
313: }

315: PetscErrorCode  PetscViewerMathematicaSetLinkMode(PetscViewer v, LinkMode mode)
316: {
317:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;

320:   vmath->linkmode = mode;
321:   return(0);
322: }

324: /*----------------------------------------- Public Functions --------------------------------------------------------*/
325: /*@C
326:   PetscViewerMathematicaOpen - Communicates with Mathemtica using MathLink.

328:   Collective on comm

330:   Input Parameters:
331: + comm    - The MPI communicator
332: . port    - [optional] The port to connect on, or PETSC_DECIDE
333: . machine - [optional] The machine to run Mathematica on, or NULL
334: - mode    - [optional] The connection mode, or NULL

336:   Output Parameter:
337: . viewer  - The Mathematica viewer

339:   Level: intermediate

341:   Notes:
342:   Most users should employ the following commands to access the
343:   Mathematica viewers
344: $
345: $    PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer)
346: $    MatView(Mat matrix, PetscViewer viewer)
347: $
348: $                or
349: $
350: $    PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer)
351: $    VecView(Vec vector, PetscViewer viewer)

353:    Options Database Keys:
354: +    -viewer_math_linkhost <machine> - The host machine for the kernel
355: .    -viewer_math_linkname <name>    - The full link name for the connection
356: .    -viewer_math_linkport <port>    - The port for the connection
357: .    -viewer_math_mode <mode>        - The mode, e.g. Launch, Connect
358: .    -viewer_math_type <type>        - The plot type, e.g. Triangulation, Vector
359: -    -viewer_math_graphics <output>  - The output type, e.g. Motif, PS, PSFile

361: .keywords: PetscViewer, Mathematica, open

363: .seealso: MatView(), VecView()
364: @*/
365: PetscErrorCode  PetscViewerMathematicaOpen(MPI_Comm comm, int port, const char machine[], const char mode[], PetscViewer *v)
366: {

370:   PetscViewerCreate(comm, v);
371: #if 0
372:   LinkMode linkmode;
373:   PetscViewerMathematicaSetLinkPort(*v, port);
374:   PetscViewerMathematicaSetLinkHost(*v, machine);
375:   PetscViewerMathematicaParseLinkMode(mode, &linkmode);
376:   PetscViewerMathematicaSetLinkMode(*v, linkmode);
377: #endif
378:   PetscViewerSetType(*v, PETSC_VIEWER_MATHEMATICA);
379:   return(0);
380: }

382: /*@C
383:   PetscViewerMathematicaGetLink - Returns the link to Mathematica

385:   Input Parameters:
386: . viewer - The Mathematica viewer
387: . link   - The link to Mathematica

389:   Level: intermediate

391: .keywords PetscViewer, Mathematica, link
392: .seealso PetscViewerMathematicaOpen()
393: @*/
394: PetscErrorCode  PetscViewerMathematicaGetLink(PetscViewer viewer, MLINK *link)
395: {
396:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;

400:   *link = vmath->link;
401:   return(0);
402: }

404: /*@C
405:   PetscViewerMathematicaSkipPackets - Discard packets sent by Mathematica until a certain packet type is received

407:   Input Parameters:
408: . viewer - The Mathematica viewer
409: . type   - The packet type to search for, e.g RETURNPKT

411:   Level: advanced

413: .keywords PetscViewer, Mathematica, packets
414: .seealso PetscViewerMathematicaSetName(), PetscViewerMathematicaGetVector()
415: @*/
416: PetscErrorCode  PetscViewerMathematicaSkipPackets(PetscViewer viewer, int type)
417: {
418:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
419:   MLINK                   link   = vmath->link; /* The link to Mathematica */
420:   int                     pkt;                 /* The packet type */

423:   while ((pkt = MLNextPacket(link)) && (pkt != type)) MLNewPacket(link);
424:   if (!pkt) {
425:     MLClearError(link);
426:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB, (char*) MLErrorMessage(link));
427:   }
428:   return(0);
429: }

431: /*@C
432:   PetscViewerMathematicaGetName - Retrieve the default name for objects communicated to Mathematica

434:   Input Parameter:
435: . viewer - The Mathematica viewer

437:   Output Parameter:
438: . name   - The name for new objects created in Mathematica

440:   Level: intermediate

442: .keywords PetscViewer, Mathematica, name
443: .seealso PetscViewerMathematicaSetName(), PetscViewerMathematicaClearName()
444: @*/
445: PetscErrorCode  PetscViewerMathematicaGetName(PetscViewer viewer, const char **name)
446: {
447:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;

452:   *name = vmath->objName;
453:   return(0);
454: }

456: /*@C
457:   PetscViewerMathematicaSetName - Override the default name for objects communicated to Mathematica

459:   Input Parameters:
460: . viewer - The Mathematica viewer
461: . name   - The name for new objects created in Mathematica

463:   Level: intermediate

465: .keywords PetscViewer, Mathematica, name
466: .seealso PetscViewerMathematicaSetName(), PetscViewerMathematicaClearName()
467: @*/
468: PetscErrorCode  PetscViewerMathematicaSetName(PetscViewer viewer, const char name[])
469: {
470:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;

475:   vmath->objName = name;
476:   return(0);
477: }

479: /*@C
480:   PetscViewerMathematicaClearName - Use the default name for objects communicated to Mathematica

482:   Input Parameter:
483: . viewer - The Mathematica viewer

485:   Level: intermediate

487: .keywords PetscViewer, Mathematica, name
488: .seealso PetscViewerMathematicaGetName(), PetscViewerMathematicaSetName()
489: @*/
490: PetscErrorCode  PetscViewerMathematicaClearName(PetscViewer viewer)
491: {
492:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;

496:   vmath->objName = NULL;
497:   return(0);
498: }

500: /*@C
501:   PetscViewerMathematicaGetVector - Retrieve a vector from Mathematica

503:   Input Parameter:
504: . viewer - The Mathematica viewer

506:   Output Parameter:
507: . v      - The vector

509:   Level: intermediate

511: .keywords PetscViewer, Mathematica, vector
512: .seealso VecView(), PetscViewerMathematicaPutVector()
513: @*/
514: PetscErrorCode  PetscViewerMathematicaGetVector(PetscViewer viewer, Vec v)
515: {
516:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
517:   MLINK                   link;   /* The link to Mathematica */
518:   char                    *name;
519:   PetscScalar             *mArray,*array;
520:   long                    mSize;
521:   int                     n;
522:   PetscErrorCode          ierr;


528:   /* Determine the object name */
529:   if (!vmath->objName) name = "vec";
530:   else                 name = (char*) vmath->objName;

532:   link = vmath->link;
533:   VecGetLocalSize(v, &n);
534:   VecGetArray(v, &array);
535:   MLPutFunction(link, "EvaluatePacket", 1);
536:   MLPutSymbol(link, name);
537:   MLEndPacket(link);
538:   PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
539:   MLGetRealList(link, &mArray, &mSize);
540:   if (n != mSize) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG, "Incompatible vector sizes %d %d",n,mSize);
541:   PetscMemcpy(array, mArray, mSize * sizeof(double));
542:   MLDisownRealList(link, mArray, mSize);
543:   VecRestoreArray(v, &array);
544:   return(0);
545: }

547: /*@C
548:   PetscViewerMathematicaPutVector - Send a vector to Mathematica

550:   Input Parameters:
551: + viewer - The Mathematica viewer
552: - v      - The vector

554:   Level: intermediate

556: .keywords PetscViewer, Mathematica, vector
557: .seealso VecView(), PetscViewerMathematicaGetVector()
558: @*/
559: PetscErrorCode  PetscViewerMathematicaPutVector(PetscViewer viewer, Vec v)
560: {
561:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
562:   MLINK                   link   = vmath->link; /* The link to Mathematica */
563:   char                    *name;
564:   PetscScalar             *array;
565:   int                     n;
566:   PetscErrorCode          ierr;

569:   /* Determine the object name */
570:   if (!vmath->objName) name = "vec";
571:   else                 name = (char*) vmath->objName;

573:   VecGetLocalSize(v, &n);
574:   VecGetArray(v, &array);

576:   /* Send the Vector object */
577:   MLPutFunction(link, "EvaluatePacket", 1);
578:   MLPutFunction(link, "Set", 2);
579:   MLPutSymbol(link, name);
580:   MLPutRealList(link, array, n);
581:   MLEndPacket(link);
582:   /* Skip packets until ReturnPacket */
583:   PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
584:   /* Skip ReturnPacket */
585:   MLNewPacket(link);

587:   VecRestoreArray(v, &array);
588:   return(0);
589: }

591: PetscErrorCode  PetscViewerMathematicaPutMatrix(PetscViewer viewer, int m, int n, PetscReal *a)
592: {
593:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
594:   MLINK                   link   = vmath->link; /* The link to Mathematica */
595:   char                    *name;
596:   PetscErrorCode          ierr;

599:   /* Determine the object name */
600:   if (!vmath->objName) name = "mat";
601:   else                 name = (char*) vmath->objName;

603:   /* Send the dense matrix object */
604:   MLPutFunction(link, "EvaluatePacket", 1);
605:   MLPutFunction(link, "Set", 2);
606:   MLPutSymbol(link, name);
607:   MLPutFunction(link, "Transpose", 1);
608:   MLPutFunction(link, "Partition", 2);
609:   MLPutRealList(link, a, m*n);
610:   MLPutInteger(link, m);
611:   MLEndPacket(link);
612:   /* Skip packets until ReturnPacket */
613:   PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
614:   /* Skip ReturnPacket */
615:   MLNewPacket(link);
616:   return(0);
617: }

619: PetscErrorCode  PetscViewerMathematicaPutCSRMatrix(PetscViewer viewer, int m, int n, int *i, int *j, PetscReal *a)
620: {
621:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
622:   MLINK                   link   = vmath->link; /* The link to Mathematica */
623:   const char              *symbol;
624:   char                    *name;
625:   PetscBool               match;
626:   PetscErrorCode          ierr;

629:   /* Determine the object name */
630:   if (!vmath->objName) name = "mat";
631:   else                 name = (char*) vmath->objName;

633:   /* Make sure Mathematica recognizes sparse matrices */
634:   MLPutFunction(link, "EvaluatePacket", 1);
635:   MLPutFunction(link, "Needs", 1);
636:   MLPutString(link, "LinearAlgebra`CSRMatrix`");
637:   MLEndPacket(link);
638:   /* Skip packets until ReturnPacket */
639:   PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
640:   /* Skip ReturnPacket */
641:   MLNewPacket(link);

643:   /* Send the CSRMatrix object */
644:   MLPutFunction(link, "EvaluatePacket", 1);
645:   MLPutFunction(link, "Set", 2);
646:   MLPutSymbol(link, name);
647:   MLPutFunction(link, "CSRMatrix", 5);
648:   MLPutInteger(link, m);
649:   MLPutInteger(link, n);
650:   MLPutFunction(link, "Plus", 2);
651:   MLPutIntegerList(link, i, m+1);
652:   MLPutInteger(link, 1);
653:   MLPutFunction(link, "Plus", 2);
654:   MLPutIntegerList(link, j, i[m]);
655:   MLPutInteger(link, 1);
656:   MLPutRealList(link, a, i[m]);
657:   MLEndPacket(link);
658:   /* Skip packets until ReturnPacket */
659:   PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
660:   /* Skip ReturnPacket */
661:   MLNewPacket(link);

663:   /* Check that matrix is valid */
664:   MLPutFunction(link, "EvaluatePacket", 1);
665:   MLPutFunction(link, "ValidQ", 1);
666:   MLPutSymbol(link, name);
667:   MLEndPacket(link);
668:   PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
669:   MLGetSymbol(link, &symbol);
670:   PetscStrcmp("True", (char*) symbol, &match);
671:   if (!match) {
672:     MLDisownSymbol(link, symbol);
673:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Invalid CSR matrix in Mathematica");
674:   }
675:   MLDisownSymbol(link, symbol);
676:   /* Skip ReturnPacket */
677:   MLNewPacket(link);
678:   return(0);
679: }