1 #include <petsc/private/viewerimpl.h> /* "petscsys.h" */ 2 #include <mathematica.h> 3 4 #if defined(PETSC_HAVE__SNPRINTF) && !defined(PETSC_HAVE_SNPRINTF) 5 #define snprintf _snprintf 6 #endif 7 8 PetscViewer PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE = NULL; 9 static void *mathematicaEnv = NULL; 10 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(). 15 16 Level: developer 17 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 } 27 28 /*@C 29 PetscViewerMathematicaInitializePackage - This function initializes everything in the PETSc interface to Mathematica. It is 30 called from `PetscViewerInitializePackage()`. 31 32 Level: developer 33 34 .seealso: `PetscSysInitializePackage()`, `PetscInitialize()` 35 @*/ 36 PetscErrorCode PetscViewerMathematicaInitializePackage(void) 37 { 38 PetscError ierr; 39 40 PetscFunctionBegin; 41 if (PetscViewerMathematicaPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS); 42 PetscViewerMathematicaPackageInitialized = PETSC_TRUE; 43 44 mathematicaEnv = (void *)MLInitialize(0); 45 46 PetscCall(PetscRegisterFinalize(PetscViewerMathematicaFinalizePackage)); 47 PetscFunctionReturn(PETSC_SUCCESS); 48 } 49 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 } 57 58 static PetscErrorCode PetscViewerDestroy_Mathematica(PetscViewer viewer) 59 { 60 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data; 61 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 } 69 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 } 76 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; 89 90 PetscFunctionBegin; 91 /* Link name */ 92 argv[0] = "-linkname"; 93 if (!vmath->linkname) argv[1] = "math -mathlink"; 94 else argv[1] = vmath->linkname; 95 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; 102 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 } 134 135 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Mathematica(PetscViewer v) 136 { 137 PetscViewer_Mathematica *vmath; 138 139 PetscFunctionBegin; 140 PetscCall(PetscViewerMathematicaInitializePackage()); 141 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)); 147 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; 154 155 PetscCall(PetscViewerMathematicaSetFromOptions(v)); 156 PetscCall(PetscViewerMathematicaSetupConnection_Private(v)); 157 PetscFunctionReturn(PETSC_SUCCESS); 158 } 159 160 static PetscErrorCode PetscViewerMathematicaParseLinkMode(char *modename, LinkMode *mode) 161 { 162 PetscBool isCreate, isConnect, isLaunch; 163 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 } 174 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; 189 190 PetscFunctionBegin; 191 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)v), &size)); 192 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)v), &rank)); 193 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; 225 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; 233 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; 245 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 } 257 258 PetscErrorCode PetscViewerMathematicaSetLinkName(PetscViewer v, const char *name) 259 { 260 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data; 261 262 PetscFunctionBegin; 263 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1); 264 PetscAssertPointer(name, 2); 265 PetscCall(PetscStrallocpy(name, &vmath->linkname)); 266 PetscFunctionReturn(PETSC_SUCCESS); 267 } 268 269 PetscErrorCode PetscViewerMathematicaSetLinkPort(PetscViewer v, int port) 270 { 271 char name[16]; 272 273 PetscFunctionBegin; 274 snprintf(name, 16, "%6d", port); 275 PetscCall(PetscViewerMathematicaSetLinkName(v, name)); 276 PetscFunctionReturn(PETSC_SUCCESS); 277 } 278 279 PetscErrorCode PetscViewerMathematicaSetLinkHost(PetscViewer v, const char *host) 280 { 281 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data; 282 283 PetscFunctionBegin; 284 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1); 285 PetscAssertPointer(host, 2); 286 PetscCall(PetscStrallocpy(host, &vmath->linkhost)); 287 PetscFunctionReturn(PETSC_SUCCESS); 288 } 289 290 PetscErrorCode PetscViewerMathematicaSetLinkMode(PetscViewer v, LinkMode mode) 291 { 292 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data; 293 294 PetscFunctionBegin; 295 vmath->linkmode = mode; 296 PetscFunctionReturn(PETSC_SUCCESS); 297 } 298 299 /*@ 300 PetscViewerMathematicaOpen - Communicates with Mathemtica using MathLink. 301 302 Collective 303 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 309 310 Output Parameter: 311 . v - The Mathematica viewer 312 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 320 321 Level: intermediate 322 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) 329 330 or 331 332 PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer) 333 VecView(Vec vector, PetscViewer viewer) 334 .ve 335 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 } 352 353 /* 354 PetscViewerMathematicaGetLink - Returns the link to Mathematica from a `PETSCVIEWERMATHEMATICA` 355 356 Input Parameters: 357 + viewer - The Mathematica viewer 358 - link - The link to Mathematica 359 360 Level: intermediate 361 362 .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaOpen()` 363 */ 364 static PetscErrorCode PetscViewerMathematicaGetLink(PetscViewer viewer, MLINK *link) 365 { 366 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data; 367 368 PetscFunctionBegin; 369 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 370 *link = vmath->link; 371 PetscFunctionReturn(PETSC_SUCCESS); 372 } 373 374 /*@C 375 PetscViewerMathematicaSkipPackets - Discard packets sent by Mathematica until a certain packet type is received 376 377 Input Parameters: 378 + viewer - The Mathematica viewer 379 - type - The packet type to search for, e.g RETURNPKT 380 381 Level: advanced 382 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 */ 390 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 } 399 400 /*@C 401 PetscViewerMathematicaGetName - Retrieve the default name for objects communicated to Mathematica via `PETSCVIEWERMATHEMATICA` 402 403 Input Parameter: 404 . viewer - The Mathematica viewer 405 406 Output Parameter: 407 . name - The name for new objects created in Mathematica 408 409 Level: intermediate 410 411 .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaSetName()`, `PetscViewerMathematicaClearName()` 412 @*/ 413 PetscErrorCode PetscViewerMathematicaGetName(PetscViewer viewer, const char **name) 414 { 415 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data; 416 417 PetscFunctionBegin; 418 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 419 PetscAssertPointer(name, 2); 420 *name = vmath->objName; 421 PetscFunctionReturn(PETSC_SUCCESS); 422 } 423 424 /*@C 425 PetscViewerMathematicaSetName - Override the default name for objects communicated to Mathematica via `PETSCVIEWERMATHEMATICA` 426 427 Input Parameters: 428 + viewer - The Mathematica viewer 429 - name - The name for new objects created in Mathematica 430 431 Level: intermediate 432 433 .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaClearName()` 434 @*/ 435 PetscErrorCode PetscViewerMathematicaSetName(PetscViewer viewer, const char name[]) 436 { 437 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data; 438 439 PetscFunctionBegin; 440 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 441 PetscAssertPointer(name, 2); 442 vmath->objName = name; 443 PetscFunctionReturn(PETSC_SUCCESS); 444 } 445 446 /*@ 447 PetscViewerMathematicaClearName - Use the default name for objects communicated to Mathematica 448 449 Input Parameter: 450 . viewer - The Mathematica viewer 451 452 Level: intermediate 453 454 .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaGetName()`, `PetscViewerMathematicaSetName()` 455 @*/ 456 PetscErrorCode PetscViewerMathematicaClearName(PetscViewer viewer) 457 { 458 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data; 459 460 PetscFunctionBegin; 461 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 462 vmath->objName = NULL; 463 PetscFunctionReturn(PETSC_SUCCESS); 464 } 465 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; 471 472 PetscFunctionBegin; 473 /* Determine the object name */ 474 if (!vmath->objName) name = "mat"; 475 else name = (char *)vmath->objName; 476 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 } 492 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; 500 501 PetscFunctionBegin; 502 /* Determine the object name */ 503 if (!vmath->objName) name = "mat"; 504 else name = (char *)vmath->objName; 505 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); 515 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); 535 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 } 553