Actual source code: mathematica.c
petsc-3.4.5 2014-06-29
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>
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;
17: /*@C
18: PetscViewerMathematicaFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
19: called from PetscFinalize().
21: Level: developer
23: .keywords: Petsc, destroy, package, mathematica
24: .seealso: PetscFinalize()
25: @*/
26: PetscErrorCode PetscViewerMathematicaFinalizePackage(void)
27: {
29: if (mathematicaEnv) MLDeinitialize((MLEnvironment) mathematicaEnv);
30: PetscViewerMathematicaPackageInitialized = PETSC_TRUE;
31: return(0);
32: }
36: /*@C
37: PetscViewerMathematicaInitializePackage - This function initializes everything in the Petsc interface to Mathematica. It is
38: called from PetscDLLibraryRegister() when using dynamic libraries, and on the call to PetscInitialize()
39: when using static libraries.
41: Level: developer
43: .keywords: Petsc, initialize, package
44: .seealso: PetscSysInitializePackage(), PetscInitialize()
45: @*/
46: PetscErrorCode PetscViewerMathematicaInitializePackage(void)
47: {
48: PetscError ierr;
51: if (PetscViewerMathematicaPackageInitialized) return(0);
52: PetscViewerMathematicaPackageInitialized = PETSC_TRUE;
54: mathematicaEnv = (void*) MLInitialize(0);
56: PetscRegisterFinalize(PetscViewerMathematicaFinalizePackage);
57: return(0);
58: }
63: PetscErrorCode PetscViewerInitializeMathematicaWorld_Private()
64: {
68: if (PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE) return(0);
69: PetscViewerMathematicaOpen(PETSC_COMM_WORLD, PETSC_DECIDE, NULL, NULL, &PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE);
70: return(0);
71: }
75: static PetscErrorCode PetscViewerDestroy_Mathematica(PetscViewer viewer)
76: {
77: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
78: PetscErrorCode ierr;
81: MLClose(vmath->link);
82: PetscFree(vmath->linkname);
83: PetscFree(vmath->linkhost);
84: PetscFree(vmath);
85: return(0);
86: }
90: PetscErrorCode PetscViewerDestroyMathematica_Private(void)
91: {
95: if (PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE) {
96: PetscViewerDestroy(PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE);
97: }
98: return(0);
99: }
103: PetscErrorCode PetscViewerMathematicaSetupConnection_Private(PetscViewer v)
104: {
105: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
106: #if defined(MATHEMATICA_3_0)
107: int argc = 6;
108: char *argv[6];
109: #else
110: int argc = 5;
111: char *argv[5];
112: #endif
113: char hostname[256];
114: long lerr;
115: PetscErrorCode ierr;
118: /* Link name */
119: argv[0] = "-linkname";
120: if (!vmath->linkname) argv[1] = "math -mathlink";
121: else argv[1] = vmath->linkname;
123: /* Link host */
124: argv[2] = "-linkhost";
125: if (!vmath->linkhost) {
126: PetscGetHostName(hostname, 255);
127: argv[3] = hostname;
128: } else argv[3] = vmath->linkhost;
130: /* Link mode */
131: #if defined(MATHEMATICA_3_0)
132: argv[4] = "-linkmode";
133: switch (vmath->linkmode) {
134: case MATHEMATICA_LINK_CREATE:
135: argv[5] = "Create";
136: break;
137: case MATHEMATICA_LINK_CONNECT:
138: argv[5] = "Connect";
139: break;
140: case MATHEMATICA_LINK_LAUNCH:
141: argv[5] = "Launch";
142: break;
143: }
144: #else
145: switch (vmath->linkmode) {
146: case MATHEMATICA_LINK_CREATE:
147: argv[4] = "-linkcreate";
148: break;
149: case MATHEMATICA_LINK_CONNECT:
150: argv[4] = "-linkconnect";
151: break;
152: case MATHEMATICA_LINK_LAUNCH:
153: argv[4] = "-linklaunch";
154: break;
155: }
156: #endif
157: vmath->link = MLOpenInEnv(mathematicaEnv, argc, argv, &lerr);
158: #endif
159: return(0);
160: }
164: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Mathematica(PetscViewer v)
165: {
166: PetscViewer_Mathematica *vmath;
167: PetscErrorCode ierr;
170: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
171: PetscViewerMathematicaInitializePackage();
172: #endif
174: PetscNewLog(v,PetscViewer_Mathematica, &vmath);
175: v->data = (void*) vmath;
176: v->ops->destroy = PetscViewerDestroy_Mathematica;
177: v->ops->flush = 0;
178: PetscStrallocpy(PETSC_VIEWER_MATHEMATICA, &((PetscObject)v)->type_name);
180: vmath->linkname = NULL;
181: vmath->linkhost = NULL;
182: vmath->linkmode = MATHEMATICA_LINK_CONNECT;
183: vmath->graphicsType = GRAPHICS_MOTIF;
184: vmath->plotType = MATHEMATICA_TRIANGULATION_PLOT;
185: vmath->objName = NULL;
187: PetscViewerMathematicaSetFromOptions(v);
188: PetscViewerMathematicaSetupConnection_Private(v);
189: return(0);
190: }
194: PetscErrorCode PetscViewerMathematicaParseLinkMode_Private(char *modename, LinkMode *mode)
195: {
196: PetscBool isCreate, isConnect, isLaunch;
200: PetscStrcasecmp(modename, "Create", &isCreate);
201: PetscStrcasecmp(modename, "Connect", &isConnect);
202: PetscStrcasecmp(modename, "Launch", &isLaunch);
203: if (isCreate) *mode = MATHEMATICA_LINK_CREATE;
204: else if (isConnect) *mode = MATHEMATICA_LINK_CONNECT;
205: else if (isLaunch) *mode = MATHEMATICA_LINK_LAUNCH;
206: else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG, "Invalid Mathematica link mode: %s", modename);
207: return(0);
208: }
212: PetscErrorCode PetscViewerMathematicaSetFromOptions(PetscViewer v)
213: {
214: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
215: char linkname[256];
216: char modename[256];
217: char hostname[256];
218: char type[256];
219: PetscInt numPorts;
220: PetscInt *ports;
221: PetscInt numHosts;
222: int h;
223: char **hosts;
224: PetscMPIInt size, rank;
225: PetscBool opt;
226: PetscErrorCode ierr;
229: MPI_Comm_size(PetscObjectComm((PetscObject)v), &size);
230: MPI_Comm_rank(PetscObjectComm((PetscObject)v), &rank);
232: /* Get link name */
233: PetscOptionsGetString("viewer_", "-math_linkname", linkname, 256, &opt);
234: if (opt) {
235: PetscViewerMathematicaSetLinkName(v, linkname);
236: }
237: /* Get link port */
238: numPorts = size;
239: PetscMalloc(size*sizeof(int), &ports);
240: PetscOptionsGetIntArray("viewer_", "-math_linkport", ports, &numPorts, &opt);
241: if (opt) {
242: if (numPorts > rank) snprintf(linkname, 255, "%6d", ports[rank]);
243: else snprintf(linkname, 255, "%6d", ports[0]);
244: PetscViewerMathematicaSetLinkName(v, linkname);
245: }
246: PetscFree(ports);
247: /* Get link host */
248: numHosts = size;
249: PetscMalloc(size*sizeof(char*), &hosts);
250: PetscOptionsGetStringArray("viewer_", "-math_linkhost", hosts, &numHosts, &opt);
251: if (opt) {
252: if (numHosts > rank) {
253: PetscStrncpy(hostname, hosts[rank], 255);
254: } else {
255: PetscStrncpy(hostname, hosts[0], 255);
256: }
257: PetscViewerMathematicaSetLinkHost(v, hostname);
258: }
259: for (h = 0; h < numHosts; h++) {
260: PetscFree(hosts[h]);
261: }
262: PetscFree(hosts);
263: /* Get link mode */
264: PetscOptionsGetString("viewer_", "-math_linkmode", modename, 256, &opt);
265: if (opt) {
266: LinkMode mode;
268: PetscViewerMathematicaParseLinkMode_Private(modename, &mode);
269: PetscViewerMathematicaSetLinkMode(v, mode);
270: }
271: /* Get graphics type */
272: PetscOptionsGetString("viewer_", "-math_graphics", type, 256, &opt);
273: if (opt) {
274: PetscBool isMotif, isPS, isPSFile;
276: PetscStrcasecmp(type, "Motif", &isMotif);
277: PetscStrcasecmp(type, "PS", &isPS);
278: PetscStrcasecmp(type, "PSFile", &isPSFile);
279: if (isMotif) vmath->graphicsType = GRAPHICS_MOTIF;
280: else if (isPS) vmath->graphicsType = GRAPHICS_PS_STDOUT;
281: else if (isPSFile) vmath->graphicsType = GRAPHICS_PS_FILE;
282: }
283: /* Get plot type */
284: PetscOptionsGetString("viewer_", "-math_type", type, 256, &opt);
285: if (opt) {
286: PetscBool isTri, isVecTri, isVec, isSurface;
288: PetscStrcasecmp(type, "Triangulation", &isTri);
289: PetscStrcasecmp(type, "VectorTriangulation", &isVecTri);
290: PetscStrcasecmp(type, "Vector", &isVec);
291: PetscStrcasecmp(type, "Surface", &isSurface);
292: if (isTri) vmath->plotType = MATHEMATICA_TRIANGULATION_PLOT;
293: else if (isVecTri) vmath->plotType = MATHEMATICA_VECTOR_TRIANGULATION_PLOT;
294: else if (isVec) vmath->plotType = MATHEMATICA_VECTOR_PLOT;
295: else if (isSurface) vmath->plotType = MATHEMATICA_SURFACE_PLOT;
296: }
297: return(0);
298: }
302: PetscErrorCode PetscViewerMathematicaSetLinkName(PetscViewer v, const char *name)
303: {
304: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
305: PetscErrorCode ierr;
310: PetscStrallocpy(name, &vmath->linkname);
311: return(0);
312: }
316: PetscErrorCode PetscViewerMathematicaSetLinkPort(PetscViewer v, int port)
317: {
318: char name[16];
322: snprintf(name, 16, "%6d", port);
323: PetscViewerMathematicaSetLinkName(v, name);
324: return(0);
325: }
329: PetscErrorCode PetscViewerMathematicaSetLinkHost(PetscViewer v, const char *host)
330: {
331: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
332: PetscErrorCode ierr;
337: PetscStrallocpy(host, &vmath->linkhost);
338: return(0);
339: }
343: PetscErrorCode PetscViewerMathematicaSetLinkMode(PetscViewer v, LinkMode mode)
344: {
345: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
348: vmath->linkmode = mode;
349: return(0);
350: }
352: /*----------------------------------------- Public Functions --------------------------------------------------------*/
355: /*@C
356: PetscViewerMathematicaOpen - Communicates with Mathemtica using MathLink.
358: Collective on comm
360: Input Parameters:
361: + comm - The MPI communicator
362: . port - [optional] The port to connect on, or PETSC_DECIDE
363: . machine - [optional] The machine to run Mathematica on, or NULL
364: - mode - [optional] The connection mode, or NULL
366: Output Parameter:
367: . viewer - The Mathematica viewer
369: Level: intermediate
371: Notes:
372: Most users should employ the following commands to access the
373: Mathematica viewers
374: $
375: $ PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer)
376: $ MatView(Mat matrix, PetscViewer viewer)
377: $
378: $ or
379: $
380: $ PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer)
381: $ VecView(Vec vector, PetscViewer viewer)
383: Options Database Keys:
384: $ -viewer_math_linkhost <machine> - The host machine for the kernel
385: $ -viewer_math_linkname <name> - The full link name for the connection
386: $ -viewer_math_linkport <port> - The port for the connection
387: $ -viewer_math_mode <mode> - The mode, e.g. Launch, Connect
388: $ -viewer_math_type <type> - The plot type, e.g. Triangulation, Vector
389: $ -viewer_math_graphics <output> - The output type, e.g. Motif, PS, PSFile
391: .keywords: PetscViewer, Mathematica, open
393: .seealso: MatView(), VecView()
394: @*/
395: PetscErrorCode PetscViewerMathematicaOpen(MPI_Comm comm, int port, const char machine[], const char mode[], PetscViewer *v)
396: {
400: PetscViewerCreate(comm, v);
401: #if 0
402: LinkMode linkmode;
403: PetscViewerMathematicaSetLinkPort(*v, port);
404: PetscViewerMathematicaSetLinkHost(*v, machine);
405: PetscViewerMathematicaParseLinkMode_Private(mode, &linkmode);
406: PetscViewerMathematicaSetLinkMode(*v, linkmode);
407: #endif
408: PetscViewerSetType(*v, PETSC_VIEWER_MATHEMATICA);
409: return(0);
410: }
414: /*@C
415: PetscViewerMathematicaGetLink - Returns the link to Mathematica
417: Input Parameters:
418: . viewer - The Mathematica viewer
419: . link - The link to Mathematica
421: Level: intermediate
423: .keywords PetscViewer, Mathematica, link
424: .seealso PetscViewerMathematicaOpen()
425: @*/
426: PetscErrorCode PetscViewerMathematicaGetLink(PetscViewer viewer, MLINK *link)
427: {
428: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
432: *link = vmath->link;
433: return(0);
434: }
438: /*@C
439: PetscViewerMathematicaSkipPackets - Discard packets sent by Mathematica until a certain packet type is received
441: Input Parameters:
442: . viewer - The Mathematica viewer
443: . type - The packet type to search for, e.g RETURNPKT
445: Level: advanced
447: .keywords PetscViewer, Mathematica, packets
448: .seealso PetscViewerMathematicaSetName(), PetscViewerMathematicaGetVector()
449: @*/
450: PetscErrorCode PetscViewerMathematicaSkipPackets(PetscViewer viewer, int type)
451: {
452: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
453: MLINK link = vmath->link; /* The link to Mathematica */
454: int pkt; /* The packet type */
457: while ((pkt = MLNextPacket(link)) && (pkt != type)) MLNewPacket(link);
458: if (!pkt) {
459: MLClearError(link);
460: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB, (char*) MLErrorMessage(link));
461: }
462: return(0);
463: }
467: /*@C
468: PetscViewerMathematicaGetName - Retrieve the default name for objects communicated to Mathematica
470: Input Parameter:
471: . viewer - The Mathematica viewer
473: Output Parameter:
474: . name - The name for new objects created in Mathematica
476: Level: intermediate
478: .keywords PetscViewer, Mathematica, name
479: .seealso PetscViewerMathematicaSetName(), PetscViewerMathematicaClearName()
480: @*/
481: PetscErrorCode PetscViewerMathematicaGetName(PetscViewer viewer, const char **name)
482: {
483: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
488: *name = vmath->objName;
489: return(0);
490: }
494: /*@C
495: PetscViewerMathematicaSetName - Override the default name for objects communicated to Mathematica
497: Input Parameters:
498: . viewer - The Mathematica viewer
499: . name - The name for new objects created in Mathematica
501: Level: intermediate
503: .keywords PetscViewer, Mathematica, name
504: .seealso PetscViewerMathematicaSetName(), PetscViewerMathematicaClearName()
505: @*/
506: PetscErrorCode PetscViewerMathematicaSetName(PetscViewer viewer, const char name[])
507: {
508: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
513: vmath->objName = name;
514: return(0);
515: }
519: /*@C
520: PetscViewerMathematicaClearName - Use the default name for objects communicated to Mathematica
522: Input Parameter:
523: . viewer - The Mathematica viewer
525: Level: intermediate
527: .keywords PetscViewer, Mathematica, name
528: .seealso PetscViewerMathematicaGetName(), PetscViewerMathematicaSetName()
529: @*/
530: PetscErrorCode PetscViewerMathematicaClearName(PetscViewer viewer)
531: {
532: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
536: vmath->objName = NULL;
537: return(0);
538: }
542: /*@C
543: PetscViewerMathematicaGetVector - Retrieve a vector from Mathematica
545: Input Parameter:
546: . viewer - The Mathematica viewer
548: Output Parameter:
549: . v - The vector
551: Level: intermediate
553: .keywords PetscViewer, Mathematica, vector
554: .seealso VecView(), PetscViewerMathematicaPutVector()
555: @*/
556: PetscErrorCode PetscViewerMathematicaGetVector(PetscViewer viewer, Vec v)
557: {
558: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
559: MLINK link; /* The link to Mathematica */
560: char *name;
561: PetscScalar *mArray,*array;
562: long mSize;
563: int n;
564: PetscErrorCode ierr;
570: /* Determine the object name */
571: if (!vmath->objName) name = "vec";
572: else name = (char*) vmath->objName;
574: link = vmath->link;
575: VecGetLocalSize(v, &n);
576: VecGetArray(v, &array);
577: MLPutFunction(link, "EvaluatePacket", 1);
578: MLPutSymbol(link, name);
579: MLEndPacket(link);
580: PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
581: MLGetRealList(link, &mArray, &mSize);
582: if (n != mSize) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG, "Incompatible vector sizes %d %d",n,mSize);
583: PetscMemcpy(array, mArray, mSize * sizeof(double));
584: MLDisownRealList(link, mArray, mSize);
585: VecRestoreArray(v, &array);
586: return(0);
587: }
591: /*@C
592: PetscViewerMathematicaPutVector - Send a vector to Mathematica
594: Input Parameters:
595: + viewer - The Mathematica viewer
596: - v - The vector
598: Level: intermediate
600: .keywords PetscViewer, Mathematica, vector
601: .seealso VecView(), PetscViewerMathematicaGetVector()
602: @*/
603: PetscErrorCode PetscViewerMathematicaPutVector(PetscViewer viewer, Vec v)
604: {
605: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
606: MLINK link = vmath->link; /* The link to Mathematica */
607: char *name;
608: PetscScalar *array;
609: int n;
610: PetscErrorCode ierr;
613: /* Determine the object name */
614: if (!vmath->objName) name = "vec";
615: else name = (char*) vmath->objName;
617: VecGetLocalSize(v, &n);
618: VecGetArray(v, &array);
620: /* Send the Vector object */
621: MLPutFunction(link, "EvaluatePacket", 1);
622: MLPutFunction(link, "Set", 2);
623: MLPutSymbol(link, name);
624: MLPutRealList(link, array, n);
625: MLEndPacket(link);
626: /* Skip packets until ReturnPacket */
627: PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
628: /* Skip ReturnPacket */
629: MLNewPacket(link);
631: VecRestoreArray(v, &array);
632: return(0);
633: }
635: PetscErrorCode PetscViewerMathematicaPutMatrix(PetscViewer viewer, int m, int n, PetscReal *a)
636: {
637: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
638: MLINK link = vmath->link; /* The link to Mathematica */
639: char *name;
640: PetscErrorCode ierr;
643: /* Determine the object name */
644: if (!vmath->objName) name = "mat";
645: else name = (char*) vmath->objName;
647: /* Send the dense matrix object */
648: MLPutFunction(link, "EvaluatePacket", 1);
649: MLPutFunction(link, "Set", 2);
650: MLPutSymbol(link, name);
651: MLPutFunction(link, "Transpose", 1);
652: MLPutFunction(link, "Partition", 2);
653: MLPutRealList(link, a, m*n);
654: MLPutInteger(link, m);
655: MLEndPacket(link);
656: /* Skip packets until ReturnPacket */
657: PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
658: /* Skip ReturnPacket */
659: MLNewPacket(link);
660: return(0);
661: }
663: PetscErrorCode PetscViewerMathematicaPutCSRMatrix(PetscViewer viewer, int m, int n, int *i, int *j, PetscReal *a)
664: {
665: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
666: MLINK link = vmath->link; /* The link to Mathematica */
667: const char *symbol;
668: char *name;
669: PetscBool match;
670: PetscErrorCode ierr;
673: /* Determine the object name */
674: if (!vmath->objName) name = "mat";
675: else name = (char*) vmath->objName;
677: /* Make sure Mathematica recognizes sparse matrices */
678: MLPutFunction(link, "EvaluatePacket", 1);
679: MLPutFunction(link, "Needs", 1);
680: MLPutString(link, "LinearAlgebra`CSRMatrix`");
681: MLEndPacket(link);
682: /* Skip packets until ReturnPacket */
683: PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
684: /* Skip ReturnPacket */
685: MLNewPacket(link);
687: /* Send the CSRMatrix object */
688: MLPutFunction(link, "EvaluatePacket", 1);
689: MLPutFunction(link, "Set", 2);
690: MLPutSymbol(link, name);
691: MLPutFunction(link, "CSRMatrix", 5);
692: MLPutInteger(link, m);
693: MLPutInteger(link, n);
694: MLPutFunction(link, "Plus", 2);
695: MLPutIntegerList(link, i, m+1);
696: MLPutInteger(link, 1);
697: MLPutFunction(link, "Plus", 2);
698: MLPutIntegerList(link, j, i[m]);
699: MLPutInteger(link, 1);
700: MLPutRealList(link, a, i[m]);
701: MLEndPacket(link);
702: /* Skip packets until ReturnPacket */
703: PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
704: /* Skip ReturnPacket */
705: MLNewPacket(link);
707: /* Check that matrix is valid */
708: MLPutFunction(link, "EvaluatePacket", 1);
709: MLPutFunction(link, "ValidQ", 1);
710: MLPutSymbol(link, name);
711: MLEndPacket(link);
712: PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
713: MLGetSymbol(link, &symbol);
714: PetscStrcmp("True", (char*) symbol, &match);
715: if (!match) {
716: MLDisownSymbol(link, symbol);
717: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Invalid CSR matrix in Mathematica");
718: }
719: MLDisownSymbol(link, symbol);
720: /* Skip ReturnPacket */
721: MLNewPacket(link);
722: return(0);
723: }