xref: /petsc/doc/manual/advanced.md (revision 226f8a8a5081bc6ad7227cd631662400f0d6e2a0)
17f296bb3SBarry Smith(ch_advanced)=
27f296bb3SBarry Smith
37f296bb3SBarry Smith# Advanced Features of Matrices and Solvers
47f296bb3SBarry Smith
57f296bb3SBarry SmithThis chapter introduces additional features of the PETSc matrices and
67f296bb3SBarry Smithsolvers.
77f296bb3SBarry Smith
87f296bb3SBarry Smith(sec_matsub)=
97f296bb3SBarry Smith
107f296bb3SBarry Smith## Extracting Submatrices
117f296bb3SBarry Smith
127f296bb3SBarry SmithOne can extract a (parallel) submatrix from a given (parallel) using
137f296bb3SBarry Smith
147f296bb3SBarry Smith```
157f296bb3SBarry SmithMatCreateSubMatrix(Mat A,IS rows,IS cols,MatReuse call,Mat *B);
167f296bb3SBarry Smith```
177f296bb3SBarry Smith
187f296bb3SBarry SmithThis extracts the `rows` and `cols` of the matrix `A` into
197f296bb3SBarry Smith`B`. If call is `MAT_INITIAL_MATRIX` it will create the matrix
207f296bb3SBarry Smith`B`. If call is `MAT_REUSE_MATRIX` it will reuse the `B` created
217f296bb3SBarry Smithwith a previous call. This function is used internally by `PCFIELDSPLIT`.
227f296bb3SBarry Smith
237f296bb3SBarry SmithOne can also extract one or more submatrices per MPI process with
247f296bb3SBarry Smith
257f296bb3SBarry Smith```
267f296bb3SBarry SmithMatCreateSubMatrices(Mat A,PetscInt n,IS rows[],IS cols[],MatReuse call,Mat *B[]);
277f296bb3SBarry Smith```
287f296bb3SBarry Smith
297f296bb3SBarry SmithThis extracts n (zero or more) matrices with the `rows[k]` and `cols[k]` of the matrix `A` into an array of
307f296bb3SBarry Smithsequential matrices `B[k]` on this process. If call is `MAT_INITIAL_MATRIX` it will create the array of matrices
317f296bb3SBarry Smith`B`. If call is `MAT_REUSE_MATRIX` it will reuse the `B` created
327f296bb3SBarry Smithwith a previous call. The `IS` arguments are sequential. The array of matrices should be destroyed with `MatDestroySubMatrices()`.
337f296bb3SBarry SmithThis function is used by `PCBJACOBI` and `PCASM`.
347f296bb3SBarry Smith
357f296bb3SBarry SmithEach submatrix may be parallel, existing on a `MPI_Comm` associated with each pair of `IS` `rows[k]` and `cols[k]`,
367f296bb3SBarry Smithusing
377f296bb3SBarry Smith
387f296bb3SBarry Smith```
397f296bb3SBarry SmithMatCreateSubMatricesMPI(Mat A,PetscInt n,IS rows[],IS cols[],MatReuse call,Mat *B[]);
407f296bb3SBarry Smith```
417f296bb3SBarry Smith
427f296bb3SBarry SmithFinally this version has a specialization
437f296bb3SBarry Smith
447f296bb3SBarry Smith```
457f296bb3SBarry SmithMatGetMultiProcBlock(Mat A, MPI_Comm subComm, MatReuse scall,Mat *subMat);
467f296bb3SBarry Smith```
477f296bb3SBarry Smith
487f296bb3SBarry Smithwhere collections of non-overlapping MPI processes share a single parallel matrix on their sub-communicator.
497f296bb3SBarry SmithThis function is used by `PCBJACOBI` and `PCASM`.
507f296bb3SBarry Smith
517f296bb3SBarry SmithThe routine
527f296bb3SBarry Smith
537f296bb3SBarry Smith```
547f296bb3SBarry SmithMatCreateRedundantMatrix(Mat A,PetscInt nsubcomm,MPI_Comm subcomm,MatReuse reuse,Mat *matredundant);
557f296bb3SBarry Smith```
567f296bb3SBarry Smith
577f296bb3SBarry Smithwhere `nsubcomm` copies of the entire matrix are stored, one on each `subcomm`. The routine `PetscSubcommCreate()` and its
587f296bb3SBarry Smith`PetscSubcomm` object may, but need not be, used to construct the `subcomm`.
597f296bb3SBarry Smith
607f296bb3SBarry SmithThe routine
617f296bb3SBarry Smith
627f296bb3SBarry Smith```
637f296bb3SBarry SmithMatMPIAdjToSeq(Mat A,Mat *B);
647f296bb3SBarry Smith```
657f296bb3SBarry Smith
667f296bb3SBarry Smithis a specialization that duplicates an entire `MATMPIADJ` matrix on each MPI process.
677f296bb3SBarry Smith
687f296bb3SBarry Smith(sec_matfactor)=
697f296bb3SBarry Smith
707f296bb3SBarry Smith## Matrix Factorization
717f296bb3SBarry Smith
727f296bb3SBarry SmithNormally, PETSc users will access the matrix solvers through the `KSP`
737f296bb3SBarry Smithinterface, as discussed in {any}`ch_ksp`, but the
747f296bb3SBarry Smithunderlying factorization and triangular solve routines are also directly
757f296bb3SBarry Smithaccessible to the user.
767f296bb3SBarry Smith
777f296bb3SBarry SmithThe ILU, LU, ICC, Cholesky, and QR matrix factorizations are split into two or three
787f296bb3SBarry Smithstages depending on the user’s needs. The first stage is to calculate an
797f296bb3SBarry Smithordering for the matrix. The ordering generally is done to reduce fill
807f296bb3SBarry Smithin a sparse factorization; it does not make much sense for a dense
817f296bb3SBarry Smithmatrix.
827f296bb3SBarry Smith
837f296bb3SBarry Smith```
847f296bb3SBarry SmithMatGetOrdering(Mat matrix,MatOrderingType type,IS* rowperm,IS* colperm);
857f296bb3SBarry Smith```
867f296bb3SBarry Smith
877f296bb3SBarry SmithThe currently available alternatives for the ordering `type` are
887f296bb3SBarry Smith
897f296bb3SBarry Smith- `MATORDERINGNATURAL` - Natural
907f296bb3SBarry Smith- `MATORDERINGND` - Nested Dissection
917f296bb3SBarry Smith- `MATORDERING1WD` - One-way Dissection
927f296bb3SBarry Smith- `MATORDERINGRCM` - Reverse Cuthill-McKee
937f296bb3SBarry Smith- `MATORDERINGQMD` - Quotient Minimum Degree
947f296bb3SBarry Smith
957f296bb3SBarry SmithThese orderings can also be set through the options database.
967f296bb3SBarry Smith
977f296bb3SBarry SmithCertain matrix formats may support only a subset of these. All of
987f296bb3SBarry Smiththese orderings are symmetric at the moment; ordering routines that are
997f296bb3SBarry Smithnot symmetric may be added. Currently we support orderings only for
1007f296bb3SBarry Smithsequential matrices.
1017f296bb3SBarry Smith
1027f296bb3SBarry SmithUsers can add their own ordering routines by providing a function with
1037f296bb3SBarry Smiththe calling sequence
1047f296bb3SBarry Smith
1057f296bb3SBarry Smith```
1067f296bb3SBarry Smithint reorder(Mat A,MatOrderingType type,IS* rowperm,IS* colperm);
1077f296bb3SBarry Smith```
1087f296bb3SBarry Smith
1097f296bb3SBarry SmithHere `A` is the matrix for which we wish to generate a new ordering,
1107f296bb3SBarry Smith`type` may be ignored and `rowperm` and `colperm` are the row and
1117f296bb3SBarry Smithcolumn permutations generated by the ordering routine. The user
1127f296bb3SBarry Smithregisters the ordering routine with the command
1137f296bb3SBarry Smith
1147f296bb3SBarry Smith```
1157f296bb3SBarry SmithMatOrderingRegister(MatOrderingType ordname,char *path,char *sname,PetscErrorCode (*reorder)(Mat,MatOrderingType,IS*,IS*)));
1167f296bb3SBarry Smith```
1177f296bb3SBarry Smith
1187f296bb3SBarry SmithThe input argument `ordname` is a string of the user’s choice,
1197f296bb3SBarry Smitheither an ordering defined in `petscmat.h` or the name
1207f296bb3SBarry Smithof a new ordering introduced by the user. See the code in
1217f296bb3SBarry Smith`src/mat/impls/order/sorder.c` and other files in that
1227f296bb3SBarry Smithdirectory for examples on how the reordering routines may be written.
1237f296bb3SBarry Smith
1247f296bb3SBarry SmithOnce the reordering routine has been registered, it can be selected for
1257f296bb3SBarry Smithuse at runtime with the command line option
1267f296bb3SBarry Smith`-pc_factor_mat_ordering_type` `ordname`. If reordering from the API, the
1277f296bb3SBarry Smithuser should provide the `ordname` as the second input argument of
1287f296bb3SBarry Smith`MatGetOrdering()`.
1297f296bb3SBarry Smith
1307f296bb3SBarry SmithPETSc matrices interface to a variety of external factorization/solver packages via the `MatSolverType` which can be
1317f296bb3SBarry Smith`MATSOLVERSUPERLU_DIST`, `MATSOLVERMUMPS`, `MATSOLVERPASTIX`, `MATSOLVERMKL_PARDISO`, `MATSOLVERMKL_CPARDISO`,
1327f296bb3SBarry Smith`MATSOLVERUMFPACK`, `MATSOLVERCHOLMOD`, `MATSOLVERKLU`,
1337f296bb3SBarry Smith`MATSOLVERCUSPARSE`, and `MATSOLVERCUDA`.
1347f296bb3SBarry SmithThe last three of which can run on GPUs, while `MATSOLVERSUPERLU_DIST` can partially run on GPUs.
1357f296bb3SBarry SmithSee {any}`doc_linsolve` for a table of the factorization based solvers in PETSc.
1367f296bb3SBarry Smith
1377f296bb3SBarry SmithMost of these packages compute their own orderings and cannot use ones provided so calls to the following routines with those
1387f296bb3SBarry Smithpackages can pass NULL as the `IS` permutations.
1397f296bb3SBarry Smith
1407f296bb3SBarry SmithThe following routines perform incomplete and complete, in-place, symbolic, and
1417f296bb3SBarry Smithnumerical factorizations for symmetric and nonsymmetric matrices:
1427f296bb3SBarry Smith
1437f296bb3SBarry Smith```
1447f296bb3SBarry SmithMatICCFactor(Mat matrix,IS permutation,const MatFactorInfo *info);
1457f296bb3SBarry SmithMatCholeskyFactor(Mat matrix,IS permutation,const MatFactorInfo *info);
1467f296bb3SBarry SmithMatILUFactor(Mat matrix,IS rowpermutation,IS columnpermutation,const MatFactorInfo *info);
1477f296bb3SBarry SmithMatLUFactor(Mat matrix,IS rowpermutation,IS columnpermutation,const MatFactorInfo *info);
1487f296bb3SBarry SmithMatQRFactor(Mat matrix, IS columnpermutation, const MatFactorInfo *info);
1497f296bb3SBarry Smith```
1507f296bb3SBarry Smith
1517f296bb3SBarry SmithThe argument `info->fill > 1` is the predicted fill expected in the
1527f296bb3SBarry Smithfactored matrix, as a ratio of the original fill. For example,
1537f296bb3SBarry Smith`info->fill = 2.0` would indicate that one expects the factored matrix
1547f296bb3SBarry Smithto have twice as many nonzeros as the original.
1557f296bb3SBarry Smith
1567f296bb3SBarry SmithFor sparse matrices it is very unlikely that the factorization is
1577f296bb3SBarry Smithactually done in-place. More likely, new space is allocated for the
1587f296bb3SBarry Smithfactored matrix and the old space deallocated, but to the user it
1597f296bb3SBarry Smithappears in-place because the factored matrix replaces the unfactored
1607f296bb3SBarry Smithmatrix.
1617f296bb3SBarry Smith
1627f296bb3SBarry SmithThe two factorization stages can also be performed separately, by using
1637f296bb3SBarry Smiththe preferred out-of-place mode, first one obtains that matrix object that will
1647f296bb3SBarry Smithhold the factor using
1657f296bb3SBarry Smith
1667f296bb3SBarry Smith```
1677f296bb3SBarry SmithMatGetFactor(Mat matrix,MatSolverType package,MatFactorType ftype,Mat *factor);
1687f296bb3SBarry Smith```
1697f296bb3SBarry Smith
1707f296bb3SBarry Smithand then performs the factorization
1717f296bb3SBarry Smith
1727f296bb3SBarry Smith```
1737f296bb3SBarry SmithMatICCFactorSymbolic(Mat factor,Mat matrix,IS perm,const MatFactorInfo *info);
1747f296bb3SBarry SmithMatCholeskyFactorSymbolic(Mat factor,Mat matrix,IS perm,const MatFactorInfo *info);
1757f296bb3SBarry SmithMatCholeskyFactorNumeric(Mat factor,Mat matrix,const MatFactorInfo);
1767f296bb3SBarry Smith
1777f296bb3SBarry SmithMatILUFactorSymbolic(Mat factor,Mat matrix,IS rowperm,IS colperm,const MatFactorInfo *info);
1787f296bb3SBarry SmithMatLUFactorSymbolic(Mat factor,Mat matrix,IS rowperm,IS colperm,const MatFactorInfo *info);
1797f296bb3SBarry SmithMatLUFactorNumeric(Mat factor,Mat matrix,const MatFactorInfo *info);
1807f296bb3SBarry Smith
1817f296bb3SBarry SmithMatQRFactorSymbolic(Mat factor,Mat matrix,IS perm,const MatFactorInfo *info);
1827f296bb3SBarry SmithMatQRFactorNumeric(Mat factor,Mat matrix,const MatFactorInfo *info);
1837f296bb3SBarry Smith```
1847f296bb3SBarry Smith
1857f296bb3SBarry SmithIn this case, the contents of the matrix `factor` is undefined between
1867f296bb3SBarry Smiththe symbolic and numeric factorization stages. It is possible to reuse
1877f296bb3SBarry Smiththe symbolic factorization. For the second and succeeding
1887f296bb3SBarry Smithfactorizations, one simply calls the numerical factorization with a new
1897f296bb3SBarry Smithinput `matrix` and the *same* factored `factor` matrix. It is
1907f296bb3SBarry Smith*essential* that the new input matrix have exactly the same nonzero
1917f296bb3SBarry Smithstructure as the original factored matrix. (The numerical factorization
1927f296bb3SBarry Smithmerely overwrites the numerical values in the factored matrix and does
1937f296bb3SBarry Smithnot disturb the symbolic portion, thus enabling reuse of the symbolic
1947f296bb3SBarry Smithphase.) In general, calling `XXXFactorSymbolic` with a dense matrix
1957f296bb3SBarry Smithwill do nothing except allocate the new matrix; the `XXXFactorNumeric`
1967f296bb3SBarry Smithroutines will do all of the work.
1977f296bb3SBarry Smith
1987f296bb3SBarry SmithWhy provide the plain `XXXFactor` routines when one could simply call
1997f296bb3SBarry Smiththe two-stage routines? The answer is that if one desires in-place
2007f296bb3SBarry Smithfactorization of a sparse matrix, the intermediate stage between the
2017f296bb3SBarry Smithsymbolic and numeric phases cannot be stored in a `factor` matrix, and
2027f296bb3SBarry Smithit does not make sense to store the intermediate values inside the
2037f296bb3SBarry Smithoriginal matrix that is being transformed. We originally made the
2047f296bb3SBarry Smithcombined factor routines do either in-place or out-of-place
2057f296bb3SBarry Smithfactorization, but then decided that this approach was not needed and
2067f296bb3SBarry Smithcould easily lead to confusion.
2077f296bb3SBarry Smith
2087f296bb3SBarry SmithWe do not provide our own sparse matrix factorization with pivoting
2097f296bb3SBarry Smithfor numerical stability. This is because trying to both reduce fill and
2107f296bb3SBarry Smithdo pivoting can become quite complicated. Instead, we provide a poor
2117f296bb3SBarry Smithstepchild substitute. After one has obtained a reordering, with
2127f296bb3SBarry Smith`MatGetOrdering(Mat A,MatOrdering type,IS *row,IS *col)` one may call
2137f296bb3SBarry Smith
2147f296bb3SBarry Smith```
2157f296bb3SBarry SmithMatReorderForNonzeroDiagonal(Mat A,PetscReal tol,IS row, IS col);
2167f296bb3SBarry Smith```
2177f296bb3SBarry Smith
2187f296bb3SBarry Smithwhich will try to reorder the columns to ensure that no values along the
2197f296bb3SBarry Smithdiagonal are smaller than `tol` in a absolute value. If small values
2207f296bb3SBarry Smithare detected and corrected for, a nonsymmetric permutation of the rows
2217f296bb3SBarry Smithand columns will result. This is not guaranteed to work, but may help if
2227f296bb3SBarry Smithone was simply unlucky in the original ordering. When using the `KSP`
2237f296bb3SBarry Smithsolver interface the option `-pc_factor_nonzeros_along_diagonal <tol>`
2247f296bb3SBarry Smithmay be used. Here, `tol` is an optional tolerance to decide if a value
2257f296bb3SBarry Smithis nonzero; by default it is `1.e-10`.
2267f296bb3SBarry Smith
2277f296bb3SBarry SmithThe external `MatSolverType`'s `MATSOLVERSUPERLU_DIST` and `MATSOLVERMUMPS`
2287f296bb3SBarry Smithdo manage numerical pivoting internal to their API.
2297f296bb3SBarry Smith
2307f296bb3SBarry SmithThe external factorization packages each provide a wide number of options to chose from,
2317f296bb3SBarry Smithdetails on these may be found by consulting the manual page for the solver package, such as,
2327f296bb3SBarry Smith`MATSOLVERSUPERLU_DIST`. Most of the options can be easily set via the options database
2337f296bb3SBarry Smitheven when the factorization solvers are accessed via `KSP`.
2347f296bb3SBarry Smith
2357f296bb3SBarry SmithOnce a matrix has been factored, it is natural to solve linear systems.
2367f296bb3SBarry SmithThe following four routines enable this process:
2377f296bb3SBarry Smith
2387f296bb3SBarry Smith```
2397f296bb3SBarry SmithMatSolve(Mat A,Vec x, Vec y);
2407f296bb3SBarry SmithMatSolveTranspose(Mat A, Vec x, Vec y);
2417f296bb3SBarry SmithMatSolveAdd(Mat A,Vec x, Vec y, Vec w);
2427f296bb3SBarry SmithMatSolveTransposeAdd(Mat A, Vec x, Vec y, Vec w);
2437f296bb3SBarry Smith```
2447f296bb3SBarry Smith
2457f296bb3SBarry Smithmatrix `A` of these routines must have been obtained from a
2467f296bb3SBarry Smithfactorization routine; otherwise, an error will be generated. In
2477f296bb3SBarry Smithgeneral, the user should use the `KSP` solvers introduced in the next
2487f296bb3SBarry Smithchapter rather than using these factorization and solve routines
2497f296bb3SBarry Smithdirectly.
2507f296bb3SBarry Smith
2517f296bb3SBarry SmithSome of the factorizations also support solves with multiple right-hand sides stored in a `Mat` using
2527f296bb3SBarry Smith
2537f296bb3SBarry Smith```
2547f296bb3SBarry SmithMatMatSolve(Mat A,Mat B,Mat X);
2557f296bb3SBarry Smith```
2567f296bb3SBarry Smith
2577f296bb3SBarry Smithand
2587f296bb3SBarry Smith
2597f296bb3SBarry Smith```
2607f296bb3SBarry SmithMatMatSolveTranspose(Mat A,Mat B,Mat X);
2617f296bb3SBarry Smith```
2627f296bb3SBarry Smith
2637f296bb3SBarry SmithFinally, `MATSOLVERMUMPS`, provides access to Schur complements obtained after partial factorizations as well
2647f296bb3SBarry Smithas the inertia of a matrix via `MatGetInertia()`.
2657f296bb3SBarry Smith
2667f296bb3SBarry Smith(sec_matmatproduct)=
2677f296bb3SBarry Smith
2687f296bb3SBarry Smith## Matrix-Matrix Products
2697f296bb3SBarry Smith
2707f296bb3SBarry SmithPETSc matrices provide code for computing various matrix-matrix products. This section will introduce the two sets of routines
2717f296bb3SBarry Smithavailable. For now consult `MatCreateProduct()` and `MatMatMult()`.
2727f296bb3SBarry Smith
2737f296bb3SBarry Smith## Creating PC's Directly
2747f296bb3SBarry Smith
2757f296bb3SBarry SmithUsers obtain their preconditioner contexts from the `KSP`
2767f296bb3SBarry Smithcontext with the command `KSPGetPC()`. It is possible to create,
2777f296bb3SBarry Smithmanipulate, and destroy `PC` contexts directly, although this
2787f296bb3SBarry Smithcapability should rarely be needed. To create a `PC` context, one uses
2797f296bb3SBarry Smiththe command
2807f296bb3SBarry Smith
2817f296bb3SBarry Smith```
2827f296bb3SBarry SmithPCCreate(MPI_Comm comm,PC *pc);
2837f296bb3SBarry Smith```
2847f296bb3SBarry Smith
2857f296bb3SBarry SmithThe routine
2867f296bb3SBarry Smith
2877f296bb3SBarry Smith```
2887f296bb3SBarry SmithPCSetType(PC pc,PCType method);
2897f296bb3SBarry Smith```
2907f296bb3SBarry Smith
2917f296bb3SBarry Smithsets the preconditioner method to be used. The routine
2927f296bb3SBarry Smith
2937f296bb3SBarry Smith```
2947f296bb3SBarry SmithPCSetOperators(PC pc,Mat Amat,Mat Pmat);
2957f296bb3SBarry Smith```
2967f296bb3SBarry Smith
2977f296bb3SBarry Smithset the matrices that are to be used with the preconditioner. The
2987f296bb3SBarry Smithroutine
2997f296bb3SBarry Smith
3007f296bb3SBarry Smith```
3017f296bb3SBarry SmithPCGetOperators(PC pc,Mat *Amat,Mat *Pmat);
3027f296bb3SBarry Smith```
3037f296bb3SBarry Smith
3047f296bb3SBarry Smithreturns the values set with `PCSetOperators()`.
3057f296bb3SBarry Smith
3067f296bb3SBarry SmithThe preconditioners in PETSc can be used in several ways. The two most
3077f296bb3SBarry Smithbasic routines simply apply the preconditioner or its transpose and are
3087f296bb3SBarry Smithgiven, respectively, by
3097f296bb3SBarry Smith
3107f296bb3SBarry Smith```
3117f296bb3SBarry SmithPCApply(PC pc,Vec x,Vec y);
3127f296bb3SBarry SmithPCApplyTranspose(PC pc,Vec x,Vec y);
3137f296bb3SBarry Smith```
3147f296bb3SBarry Smith
315*7addb90fSBarry SmithIn particular, for a matrix, `B`, that has been set via
3167f296bb3SBarry Smith`PCSetOperators(pc,Amat,Pmat)`, the routine PCApply(pc,x,y) computes
3177f296bb3SBarry Smith$y = B^{-1} x$ by solving the linear system $By = x$ with
3187f296bb3SBarry Smiththe specified preconditioner method.
3197f296bb3SBarry Smith
3207f296bb3SBarry SmithAdditional preconditioner routines are
3217f296bb3SBarry Smith
3227f296bb3SBarry Smith```
3237f296bb3SBarry SmithPCApplyBAorAB(PC pc,PCSide right,Vec x,Vec y,Vec work);
3247f296bb3SBarry SmithPCApplyBAorABTranspose(PC pc,PCSide right,Vec x,Vec y,Vec work);
3257f296bb3SBarry SmithPCApplyRichardson(PC pc,Vec x,Vec y,Vec work,PetscReal rtol,PetscReal atol, PetscReal dtol,PetscInt maxits,PetscBool zeroguess,PetscInt *outits,PCRichardsonConvergedReason*);
3267f296bb3SBarry Smith```
3277f296bb3SBarry Smith
3287f296bb3SBarry SmithThe first two routines apply the action of the matrix followed by the
3297f296bb3SBarry Smithpreconditioner or the preconditioner followed by the matrix depending on
3307f296bb3SBarry Smithwhether the `right` is `PC_LEFT` or `PC_RIGHT`. The final routine
3317f296bb3SBarry Smithapplies `its` iterations of Richardson’s method. The last three
3327f296bb3SBarry Smithroutines are provided to improve efficiency for certain Krylov subspace
3337f296bb3SBarry Smithmethods.
3347f296bb3SBarry Smith
3357f296bb3SBarry SmithA `PC` context that is no longer needed can be destroyed with the
3367f296bb3SBarry Smithcommand
3377f296bb3SBarry Smith
3387f296bb3SBarry Smith```
3397f296bb3SBarry SmithPCDestroy(PC *pc);
3407f296bb3SBarry Smith```
341