Actual source code: mathematica.c

  1: #include <petsc/private/viewerimpl.h>
  2: #include <mathematica.h>

  4: #if defined(PETSC_HAVE__SNPRINTF) && !defined(PETSC_HAVE_SNPRINTF)
  5:   #define snprintf _snprintf
  6: #endif

  8: PetscViewer  PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE = NULL;
  9: static void *mathematicaEnv                         = NULL;

 11: static PetscBool PetscViewerMathematicaPackageInitialized = PETSC_FALSE;
 12: /*@C
 13:   PetscViewerMathematicaFinalizePackage - This function destroys everything in the PETSc interface to Mathematica. It is
 14:   called from PetscFinalize().

 16:   Level: developer

 18: .seealso: `PetscFinalize()`
 19: @*/
 20: PetscErrorCode PetscViewerMathematicaFinalizePackage(void)
 21: {
 22:   PetscFunctionBegin;
 23:   if (mathematicaEnv) MLDeinitialize((MLEnvironment)mathematicaEnv);
 24:   PetscViewerMathematicaPackageInitialized = PETSC_TRUE;
 25:   PetscFunctionReturn(PETSC_SUCCESS);
 26: }

 28: /*@C
 29:   PetscViewerMathematicaInitializePackage - This function initializes everything in the PETSc interface to Mathematica. It is
 30:   called from `PetscViewerInitializePackage()`.

 32:   Level: developer

 34: .seealso: `PetscSysInitializePackage()`, `PetscInitialize()`
 35: @*/
 36: PetscErrorCode PetscViewerMathematicaInitializePackage(void)
 37: {
 38:   PetscError ierr;

 40:   PetscFunctionBegin;
 41:   if (PetscViewerMathematicaPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
 42:   PetscViewerMathematicaPackageInitialized = PETSC_TRUE;

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

 46:   PetscCall(PetscRegisterFinalize(PetscViewerMathematicaFinalizePackage));
 47:   PetscFunctionReturn(PETSC_SUCCESS);
 48: }

 50: static PetscErrorCode PetscViewerInitializeMathematicaWorld_Private()
 51: {
 52:   PetscFunctionBegin;
 53:   if (PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE) PetscFunctionReturn(PETSC_SUCCESS);
 54:   PetscCall(PetscViewerMathematicaOpen(PETSC_COMM_WORLD, PETSC_DECIDE, NULL, NULL, &PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE));
 55:   PetscFunctionReturn(PETSC_SUCCESS);
 56: }

 58: static PetscErrorCode PetscViewerDestroy_Mathematica(PetscViewer viewer)
 59: {
 60:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;

 62:   PetscFunctionBegin;
 63:   MLClose(vmath->link);
 64:   PetscCall(PetscFree(vmath->linkname));
 65:   PetscCall(PetscFree(vmath->linkhost));
 66:   PetscCall(PetscFree(vmath));
 67:   PetscFunctionReturn(PETSC_SUCCESS);
 68: }

 70: static PetscErrorCode PetscViewerDestroyMathematica_Private(void)
 71: {
 72:   PetscFunctionBegin;
 73:   if (PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE) PetscCall(PetscViewerDestroy(PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE));
 74:   PetscFunctionReturn(PETSC_SUCCESS);
 75: }

 77: static PetscErrorCode PetscViewerMathematicaSetupConnection_Private(PetscViewer v)
 78: {
 79:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data;
 80: #if defined(MATHEMATICA_3_0)
 81:   int   argc = 6;
 82:   char *argv[6];
 83: #else
 84:   int   argc = 5;
 85:   char *argv[5];
 86: #endif
 87:   char hostname[256];
 88:   long lerr;

 90:   PetscFunctionBegin;
 91:   /* Link name */
 92:   argv[0] = "-linkname";
 93:   if (!vmath->linkname) argv[1] = "math -mathlink";
 94:   else argv[1] = vmath->linkname;

 96:   /* Link host */
 97:   argv[2] = "-linkhost";
 98:   if (!vmath->linkhost) {
 99:     PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
100:     argv[3] = hostname;
101:   } else argv[3] = vmath->linkhost;

103:   /* Link mode */
104: #if defined(MATHEMATICA_3_0)
105:   argv[4] = "-linkmode";
106:   switch (vmath->linkmode) {
107:   case MATHEMATICA_LINK_CREATE:
108:     argv[5] = "Create";
109:     break;
110:   case MATHEMATICA_LINK_CONNECT:
111:     argv[5] = "Connect";
112:     break;
113:   case MATHEMATICA_LINK_LAUNCH:
114:     argv[5] = "Launch";
115:     break;
116:   }
117: #else
118:   switch (vmath->linkmode) {
119:   case MATHEMATICA_LINK_CREATE:
120:     argv[4] = "-linkcreate";
121:     break;
122:   case MATHEMATICA_LINK_CONNECT:
123:     argv[4] = "-linkconnect";
124:     break;
125:   case MATHEMATICA_LINK_LAUNCH:
126:     argv[4] = "-linklaunch";
127:     break;
128:   }
129: #endif
130:   vmath->link = MLOpenInEnv(mathematicaEnv, argc, argv, &lerr);
131: #endif
132:   PetscFunctionReturn(PETSC_SUCCESS);
133: }

135: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Mathematica(PetscViewer v)
136: {
137:   PetscViewer_Mathematica *vmath;

139:   PetscFunctionBegin;
140:   PetscCall(PetscViewerMathematicaInitializePackage());

142:   PetscCall(PetscNew(&vmath));
143:   v->data         = (void *)vmath;
144:   v->ops->destroy = PetscViewerDestroy_Mathematica;
145:   v->ops->flush   = 0;
146:   PetscCall(PetscStrallocpy(PETSC_VIEWER_MATHEMATICA, &((PetscObject)v)->type_name));

148:   vmath->linkname     = NULL;
149:   vmath->linkhost     = NULL;
150:   vmath->linkmode     = MATHEMATICA_LINK_CONNECT;
151:   vmath->graphicsType = GRAPHICS_MOTIF;
152:   vmath->plotType     = MATHEMATICA_TRIANGULATION_PLOT;
153:   vmath->objName      = NULL;

155:   PetscCall(PetscViewerMathematicaSetFromOptions(v));
156:   PetscCall(PetscViewerMathematicaSetupConnection_Private(v));
157:   PetscFunctionReturn(PETSC_SUCCESS);
158: }

160: static PetscErrorCode PetscViewerMathematicaParseLinkMode(char *modename, LinkMode *mode)
161: {
162:   PetscBool isCreate, isConnect, isLaunch;

164:   PetscFunctionBegin;
165:   PetscCall(PetscStrcasecmp(modename, "Create", &isCreate));
166:   PetscCall(PetscStrcasecmp(modename, "Connect", &isConnect));
167:   PetscCall(PetscStrcasecmp(modename, "Launch", &isLaunch));
168:   if (isCreate) *mode = MATHEMATICA_LINK_CREATE;
169:   else if (isConnect) *mode = MATHEMATICA_LINK_CONNECT;
170:   else if (isLaunch) *mode = MATHEMATICA_LINK_LAUNCH;
171:   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid Mathematica link mode: %s", modename);
172:   PetscFunctionReturn(PETSC_SUCCESS);
173: }

175: PetscErrorCode PetscViewerMathematicaSetFromOptions(PetscViewer v)
176: {
177:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data;
178:   char                     linkname[256];
179:   char                     modename[256];
180:   char                     hostname[256];
181:   char                     type[256];
182:   PetscInt                 numPorts;
183:   PetscInt                *ports;
184:   PetscInt                 numHosts;
185:   int                      h;
186:   char                   **hosts;
187:   PetscMPIInt              size, rank;
188:   PetscBool                opt;

190:   PetscFunctionBegin;
191:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)v), &size));
192:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)v), &rank));

194:   /* Get link name */
195:   PetscCall(PetscOptionsGetString("viewer_", "-math_linkname", linkname, sizeof(linkname), &opt));
196:   if (opt) PetscCall(PetscViewerMathematicaSetLinkName(v, linkname));
197:   /* Get link port */
198:   numPorts = size;
199:   PetscCall(PetscMalloc1(size, &ports));
200:   PetscCall(PetscOptionsGetIntArray("viewer_", "-math_linkport", ports, &numPorts, &opt));
201:   if (opt) {
202:     if (numPorts > rank) snprintf(linkname, sizeof(linkname), "%6d", ports[rank]);
203:     else snprintf(linkname, sizeof(linkname), "%6d", ports[0]);
204:     PetscCall(PetscViewerMathematicaSetLinkName(v, linkname));
205:   }
206:   PetscCall(PetscFree(ports));
207:   /* Get link host */
208:   numHosts = size;
209:   PetscCall(PetscMalloc1(size, &hosts));
210:   PetscCall(PetscOptionsGetStringArray("viewer_", "-math_linkhost", hosts, &numHosts, &opt));
211:   if (opt) {
212:     if (numHosts > rank) {
213:       PetscCall(PetscStrncpy(hostname, hosts[rank], sizeof(hostname)));
214:     } else {
215:       PetscCall(PetscStrncpy(hostname, hosts[0], sizeof(hostname)));
216:     }
217:     PetscCall(PetscViewerMathematicaSetLinkHost(v, hostname));
218:   }
219:   for (h = 0; h < numHosts; h++) PetscCall(PetscFree(hosts[h]));
220:   PetscCall(PetscFree(hosts));
221:   /* Get link mode */
222:   PetscCall(PetscOptionsGetString("viewer_", "-math_linkmode", modename, sizeof(modename), &opt));
223:   if (opt) {
224:     LinkMode mode;

226:     PetscCall(PetscViewerMathematicaParseLinkMode(modename, &mode));
227:     PetscCall(PetscViewerMathematicaSetLinkMode(v, mode));
228:   }
229:   /* Get graphics type */
230:   PetscCall(PetscOptionsGetString("viewer_", "-math_graphics", type, sizeof(type), &opt));
231:   if (opt) {
232:     PetscBool isMotif, isPS, isPSFile;

234:     PetscCall(PetscStrcasecmp(type, "Motif", &isMotif));
235:     PetscCall(PetscStrcasecmp(type, "PS", &isPS));
236:     PetscCall(PetscStrcasecmp(type, "PSFile", &isPSFile));
237:     if (isMotif) vmath->graphicsType = GRAPHICS_MOTIF;
238:     else if (isPS) vmath->graphicsType = GRAPHICS_PS_STDOUT;
239:     else if (isPSFile) vmath->graphicsType = GRAPHICS_PS_FILE;
240:   }
241:   /* Get plot type */
242:   PetscCall(PetscOptionsGetString("viewer_", "-math_type", type, sizeof(type), &opt));
243:   if (opt) {
244:     PetscBool isTri, isVecTri, isVec, isSurface;

246:     PetscCall(PetscStrcasecmp(type, "Triangulation", &isTri));
247:     PetscCall(PetscStrcasecmp(type, "VectorTriangulation", &isVecTri));
248:     PetscCall(PetscStrcasecmp(type, "Vector", &isVec));
249:     PetscCall(PetscStrcasecmp(type, "Surface", &isSurface));
250:     if (isTri) vmath->plotType = MATHEMATICA_TRIANGULATION_PLOT;
251:     else if (isVecTri) vmath->plotType = MATHEMATICA_VECTOR_TRIANGULATION_PLOT;
252:     else if (isVec) vmath->plotType = MATHEMATICA_VECTOR_PLOT;
253:     else if (isSurface) vmath->plotType = MATHEMATICA_SURFACE_PLOT;
254:   }
255:   PetscFunctionReturn(PETSC_SUCCESS);
256: }

258: PetscErrorCode PetscViewerMathematicaSetLinkName(PetscViewer v, const char *name)
259: {
260:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data;

262:   PetscFunctionBegin;
264:   PetscAssertPointer(name, 2);
265:   PetscCall(PetscStrallocpy(name, &vmath->linkname));
266:   PetscFunctionReturn(PETSC_SUCCESS);
267: }

269: PetscErrorCode PetscViewerMathematicaSetLinkPort(PetscViewer v, int port)
270: {
271:   char name[16];

273:   PetscFunctionBegin;
274:   snprintf(name, 16, "%6d", port);
275:   PetscCall(PetscViewerMathematicaSetLinkName(v, name));
276:   PetscFunctionReturn(PETSC_SUCCESS);
277: }

279: PetscErrorCode PetscViewerMathematicaSetLinkHost(PetscViewer v, const char *host)
280: {
281:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data;

283:   PetscFunctionBegin;
285:   PetscAssertPointer(host, 2);
286:   PetscCall(PetscStrallocpy(host, &vmath->linkhost));
287:   PetscFunctionReturn(PETSC_SUCCESS);
288: }

290: PetscErrorCode PetscViewerMathematicaSetLinkMode(PetscViewer v, LinkMode mode)
291: {
292:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data;

294:   PetscFunctionBegin;
295:   vmath->linkmode = mode;
296:   PetscFunctionReturn(PETSC_SUCCESS);
297: }

299: /*@
300:   PetscViewerMathematicaOpen - Communicates with Mathemtica using MathLink.

302:   Collective

304:   Input Parameters:
305: + comm    - The MPI communicator
306: . port    - [optional] The port to connect on, or PETSC_DECIDE
307: . machine - [optional] The machine to run Mathematica on, or NULL
308: - mode    - [optional] The connection mode, or NULL

310:   Output Parameter:
311: . v - The Mathematica viewer

313:   Options Database Keys:
314: + -viewer_math_linkhost <machine> - The host machine for the kernel
315: . -viewer_math_linkname <name>    - The full link name for the connection
316: . -viewer_math_linkport <port>    - The port for the connection
317: . -viewer_math_mode <mode>        - The mode, e.g. Launch, Connect
318: . -viewer_math_type <type>        - The plot type, e.g. Triangulation, Vector
319: - -viewer_math_graphics <output>  - The output type, e.g. Motif, PS, PSFile

321:   Level: intermediate

323:   Note:
324:   Most users should employ the following commands to access the
325:   Mathematica viewers
326: .vb
327:     PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer)
328:     MatView(Mat matrix, PetscViewer viewer)

330:                 or

332:     PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer)
333:     VecView(Vec vector, PetscViewer viewer)
334: .ve

336: .seealso: `PETSCVIEWERMATHEMATICA`, `MatView()`, `VecView()`
337: @*/
338: PetscErrorCode PetscViewerMathematicaOpen(MPI_Comm comm, int port, const char machine[], const char mode[], PetscViewer *v)
339: {
340:   PetscFunctionBegin;
341:   PetscCall(PetscViewerCreate(comm, v));
342: #if 0
343:   LinkMode linkmode;
344:   PetscCall(PetscViewerMathematicaSetLinkPort(*v, port));
345:   PetscCall(PetscViewerMathematicaSetLinkHost(*v, machine));
346:   PetscCall(PetscViewerMathematicaParseLinkMode(mode, &linkmode));
347:   PetscCall(PetscViewerMathematicaSetLinkMode(*v, linkmode));
348: #endif
349:   PetscCall(PetscViewerSetType(*v, PETSC_VIEWER_MATHEMATICA));
350:   PetscFunctionReturn(PETSC_SUCCESS);
351: }

353: /*
354:   PetscViewerMathematicaGetLink - Returns the link to Mathematica from a `PETSCVIEWERMATHEMATICA`

356:   Input Parameters:
357: + viewer - The Mathematica viewer
358: - link   - The link to Mathematica

360:   Level: intermediate

362: .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaOpen()`
363: */
364: static PetscErrorCode PetscViewerMathematicaGetLink(PetscViewer viewer, MLINK *link)
365: {
366:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;

368:   PetscFunctionBegin;
370:   *link = vmath->link;
371:   PetscFunctionReturn(PETSC_SUCCESS);
372: }

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

377:   Input Parameters:
378: + viewer - The Mathematica viewer
379: - type   - The packet type to search for, e.g RETURNPKT

381:   Level: advanced

383: .seealso: `PetscViewerMathematicaSetName()`, `PetscViewerMathematicaGetVector()`
384: @*/
385: PetscErrorCode PetscViewerMathematicaSkipPackets(PetscViewer viewer, int type)
386: {
387:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
388:   MLINK                    link  = vmath->link; /* The link to Mathematica */
389:   int                      pkt;                 /* The packet type */

391:   PetscFunctionBegin;
392:   while ((pkt = MLNextPacket(link)) && (pkt != type)) MLNewPacket(link);
393:   if (!pkt) {
394:     MLClearError(link);
395:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, (char *)MLErrorMessage(link));
396:   }
397:   PetscFunctionReturn(PETSC_SUCCESS);
398: }

400: /*@C
401:   PetscViewerMathematicaGetName - Retrieve the default name for objects communicated to Mathematica via `PETSCVIEWERMATHEMATICA`

403:   Input Parameter:
404: . viewer - The Mathematica viewer

406:   Output Parameter:
407: . name - The name for new objects created in Mathematica

409:   Level: intermediate

411: .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaSetName()`, `PetscViewerMathematicaClearName()`
412: @*/
413: PetscErrorCode PetscViewerMathematicaGetName(PetscViewer viewer, const char **name)
414: {
415:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;

417:   PetscFunctionBegin;
419:   PetscAssertPointer(name, 2);
420:   *name = vmath->objName;
421:   PetscFunctionReturn(PETSC_SUCCESS);
422: }

424: /*@C
425:   PetscViewerMathematicaSetName - Override the default name for objects communicated to Mathematica via `PETSCVIEWERMATHEMATICA`

427:   Input Parameters:
428: + viewer - The Mathematica viewer
429: - name   - The name for new objects created in Mathematica

431:   Level: intermediate

433: .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaClearName()`
434: @*/
435: PetscErrorCode PetscViewerMathematicaSetName(PetscViewer viewer, const char name[])
436: {
437:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;

439:   PetscFunctionBegin;
441:   PetscAssertPointer(name, 2);
442:   vmath->objName = name;
443:   PetscFunctionReturn(PETSC_SUCCESS);
444: }

446: /*@
447:   PetscViewerMathematicaClearName - Use the default name for objects communicated to Mathematica

449:   Input Parameter:
450: . viewer - The Mathematica viewer

452:   Level: intermediate

454: .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaGetName()`, `PetscViewerMathematicaSetName()`
455: @*/
456: PetscErrorCode PetscViewerMathematicaClearName(PetscViewer viewer)
457: {
458:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;

460:   PetscFunctionBegin;
462:   vmath->objName = NULL;
463:   PetscFunctionReturn(PETSC_SUCCESS);
464: }

466: PetscErrorCode PetscViewerMathematicaPutMatrix(PetscViewer viewer, int m, int n, PetscReal *a)
467: {
468:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
469:   MLINK                    link  = vmath->link; /* The link to Mathematica */
470:   char                    *name;

472:   PetscFunctionBegin;
473:   /* Determine the object name */
474:   if (!vmath->objName) name = "mat";
475:   else name = (char *)vmath->objName;

477:   /* Send the dense matrix object */
478:   MLPutFunction(link, "EvaluatePacket", 1);
479:   MLPutFunction(link, "Set", 2);
480:   MLPutSymbol(link, name);
481:   MLPutFunction(link, "Transpose", 1);
482:   MLPutFunction(link, "Partition", 2);
483:   MLPutRealList(link, a, m * n);
484:   MLPutInteger(link, m);
485:   MLEndPacket(link);
486:   /* Skip packets until ReturnPacket */
487:   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
488:   /* Skip ReturnPacket */
489:   MLNewPacket(link);
490:   PetscFunctionReturn(PETSC_SUCCESS);
491: }

493: PetscErrorCode PetscViewerMathematicaPutCSRMatrix(PetscViewer viewer, int m, int n, int *i, int *j, PetscReal *a)
494: {
495:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
496:   MLINK                    link  = vmath->link; /* The link to Mathematica */
497:   const char              *symbol;
498:   char                    *name;
499:   PetscBool                match;

501:   PetscFunctionBegin;
502:   /* Determine the object name */
503:   if (!vmath->objName) name = "mat";
504:   else name = (char *)vmath->objName;

506:   /* Make sure Mathematica recognizes sparse matrices */
507:   MLPutFunction(link, "EvaluatePacket", 1);
508:   MLPutFunction(link, "Needs", 1);
509:   MLPutString(link, "LinearAlgebra`CSRMatrix`");
510:   MLEndPacket(link);
511:   /* Skip packets until ReturnPacket */
512:   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
513:   /* Skip ReturnPacket */
514:   MLNewPacket(link);

516:   /* Send the CSRMatrix object */
517:   MLPutFunction(link, "EvaluatePacket", 1);
518:   MLPutFunction(link, "Set", 2);
519:   MLPutSymbol(link, name);
520:   MLPutFunction(link, "CSRMatrix", 5);
521:   MLPutInteger(link, m);
522:   MLPutInteger(link, n);
523:   MLPutFunction(link, "Plus", 2);
524:   MLPutIntegerList(link, i, m + 1);
525:   MLPutInteger(link, 1);
526:   MLPutFunction(link, "Plus", 2);
527:   MLPutIntegerList(link, j, i[m]);
528:   MLPutInteger(link, 1);
529:   MLPutRealList(link, a, i[m]);
530:   MLEndPacket(link);
531:   /* Skip packets until ReturnPacket */
532:   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
533:   /* Skip ReturnPacket */
534:   MLNewPacket(link);

536:   /* Check that matrix is valid */
537:   MLPutFunction(link, "EvaluatePacket", 1);
538:   MLPutFunction(link, "ValidQ", 1);
539:   MLPutSymbol(link, name);
540:   MLEndPacket(link);
541:   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
542:   MLGetSymbol(link, &symbol);
543:   PetscCall(PetscStrcmp("True", (char *)symbol, &match));
544:   if (!match) {
545:     MLDisownSymbol(link, symbol);
546:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid CSR matrix in Mathematica");
547:   }
548:   MLDisownSymbol(link, symbol);
549:   /* Skip ReturnPacket */
550:   MLNewPacket(link);
551:   PetscFunctionReturn(PETSC_SUCCESS);
552: }