Actual source code: matimpl.h

  1: #pragma once

  3: #include <petscmat.h>
  4: #include <petscmatcoarsen.h>
  5: #include <petsc/private/petscimpl.h>

  7: PETSC_EXTERN PetscBool      MatRegisterAllCalled;
  8: PETSC_EXTERN PetscBool      MatSeqAIJRegisterAllCalled;
  9: PETSC_EXTERN PetscBool      MatOrderingRegisterAllCalled;
 10: PETSC_EXTERN PetscBool      MatColoringRegisterAllCalled;
 11: PETSC_EXTERN PetscBool      MatPartitioningRegisterAllCalled;
 12: PETSC_EXTERN PetscBool      MatMeshToCellGraphRegisterAllCalled;
 13: PETSC_EXTERN PetscBool      MatCoarsenRegisterAllCalled;
 14: PETSC_EXTERN PetscErrorCode MatRegisterAll(void);
 15: PETSC_EXTERN PetscErrorCode MatOrderingRegisterAll(void);
 16: PETSC_EXTERN PetscErrorCode MatColoringRegisterAll(void);
 17: PETSC_EXTERN PetscErrorCode MatPartitioningRegisterAll(void);
 18: PETSC_EXTERN PetscErrorCode MatMeshToCellGraphRegisterAll(void);
 19: PETSC_EXTERN PetscErrorCode MatCoarsenRegisterAll(void);
 20: PETSC_EXTERN PetscErrorCode MatSeqAIJRegisterAll(void);

 22: /* Gets the root type of the input matrix's type (e.g., MATAIJ for MATSEQAIJ) */
 23: PETSC_EXTERN PetscErrorCode MatGetRootType_Private(Mat, MatType *);

 25: /* Gets the MPI type corresponding to the input matrix's type (e.g., MATMPIAIJ for MATSEQAIJ) */
 26: PETSC_INTERN PetscErrorCode MatGetMPIMatType_Private(Mat, MatType *);

 28: /*
 29:   This file defines the parts of the matrix data structure that are
 30:   shared by all matrix types.
 31: */

 33: /*
 34:     If you add entries here also add them to the MATOP enum
 35:     in include/petscmat.h
 36: */
 37: typedef struct _MatOps *MatOps;
 38: struct _MatOps {
 39:   /* 0*/
 40:   PetscErrorCode (*setvalues)(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], const PetscScalar[], InsertMode);
 41:   PetscErrorCode (*getrow)(Mat, PetscInt, PetscInt *, PetscInt *[], PetscScalar *[]);
 42:   PetscErrorCode (*restorerow)(Mat, PetscInt, PetscInt *, PetscInt *[], PetscScalar *[]);
 43:   PetscErrorCode (*mult)(Mat, Vec, Vec);
 44:   PetscErrorCode (*multadd)(Mat, Vec, Vec, Vec);
 45:   /* 5*/
 46:   PetscErrorCode (*multtranspose)(Mat, Vec, Vec);
 47:   PetscErrorCode (*multtransposeadd)(Mat, Vec, Vec, Vec);
 48:   PetscErrorCode (*solve)(Mat, Vec, Vec);
 49:   PetscErrorCode (*solveadd)(Mat, Vec, Vec, Vec);
 50:   PetscErrorCode (*solvetranspose)(Mat, Vec, Vec);
 51:   /*10*/
 52:   PetscErrorCode (*solvetransposeadd)(Mat, Vec, Vec, Vec);
 53:   PetscErrorCode (*lufactor)(Mat, IS, IS, const MatFactorInfo *);
 54:   PetscErrorCode (*choleskyfactor)(Mat, IS, const MatFactorInfo *);
 55:   PetscErrorCode (*sor)(Mat, Vec, PetscReal, MatSORType, PetscReal, PetscInt, PetscInt, Vec);
 56:   PetscErrorCode (*transpose)(Mat, MatReuse, Mat *);
 57:   /*15*/
 58:   PetscErrorCode (*getinfo)(Mat, MatInfoType, MatInfo *);
 59:   PetscErrorCode (*equal)(Mat, Mat, PetscBool *);
 60:   PetscErrorCode (*getdiagonal)(Mat, Vec);
 61:   PetscErrorCode (*diagonalscale)(Mat, Vec, Vec);
 62:   PetscErrorCode (*norm)(Mat, NormType, PetscReal *);
 63:   /*20*/
 64:   PetscErrorCode (*assemblybegin)(Mat, MatAssemblyType);
 65:   PetscErrorCode (*assemblyend)(Mat, MatAssemblyType);
 66:   PetscErrorCode (*setoption)(Mat, MatOption, PetscBool);
 67:   PetscErrorCode (*zeroentries)(Mat);
 68:   /*24*/
 69:   PetscErrorCode (*zerorows)(Mat, PetscInt, const PetscInt[], PetscScalar, Vec, Vec);
 70:   PetscErrorCode (*lufactorsymbolic)(Mat, Mat, IS, IS, const MatFactorInfo *);
 71:   PetscErrorCode (*lufactornumeric)(Mat, Mat, const MatFactorInfo *);
 72:   PetscErrorCode (*choleskyfactorsymbolic)(Mat, Mat, IS, const MatFactorInfo *);
 73:   PetscErrorCode (*choleskyfactornumeric)(Mat, Mat, const MatFactorInfo *);
 74:   /*29*/
 75:   PetscErrorCode (*setup)(Mat);
 76:   PetscErrorCode (*ilufactorsymbolic)(Mat, Mat, IS, IS, const MatFactorInfo *);
 77:   PetscErrorCode (*iccfactorsymbolic)(Mat, Mat, IS, const MatFactorInfo *);
 78:   PetscErrorCode (*getdiagonalblock)(Mat, Mat *);
 79:   PetscErrorCode (*setinf)(Mat);
 80:   /*34*/
 81:   PetscErrorCode (*duplicate)(Mat, MatDuplicateOption, Mat *);
 82:   PetscErrorCode (*forwardsolve)(Mat, Vec, Vec);
 83:   PetscErrorCode (*backwardsolve)(Mat, Vec, Vec);
 84:   PetscErrorCode (*ilufactor)(Mat, IS, IS, const MatFactorInfo *);
 85:   PetscErrorCode (*iccfactor)(Mat, IS, const MatFactorInfo *);
 86:   /*39*/
 87:   PetscErrorCode (*axpy)(Mat, PetscScalar, Mat, MatStructure);
 88:   PetscErrorCode (*createsubmatrices)(Mat, PetscInt, const IS[], const IS[], MatReuse, Mat *[]);
 89:   PetscErrorCode (*increaseoverlap)(Mat, PetscInt, IS[], PetscInt);
 90:   PetscErrorCode (*getvalues)(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], PetscScalar[]);
 91:   PetscErrorCode (*copy)(Mat, Mat, MatStructure);
 92:   /*44*/
 93:   PetscErrorCode (*getrowmax)(Mat, Vec, PetscInt[]);
 94:   PetscErrorCode (*scale)(Mat, PetscScalar);
 95:   PetscErrorCode (*shift)(Mat, PetscScalar);
 96:   PetscErrorCode (*diagonalset)(Mat, Vec, InsertMode);
 97:   PetscErrorCode (*zerorowscolumns)(Mat, PetscInt, const PetscInt[], PetscScalar, Vec, Vec);
 98:   /*49*/
 99:   PetscErrorCode (*setrandom)(Mat, PetscRandom);
100:   PetscErrorCode (*getrowij)(Mat, PetscInt, PetscBool, PetscBool, PetscInt *, const PetscInt *[], const PetscInt *[], PetscBool *);
101:   PetscErrorCode (*restorerowij)(Mat, PetscInt, PetscBool, PetscBool, PetscInt *, const PetscInt *[], const PetscInt *[], PetscBool *);
102:   PetscErrorCode (*getcolumnij)(Mat, PetscInt, PetscBool, PetscBool, PetscInt *, const PetscInt *[], const PetscInt *[], PetscBool *);
103:   PetscErrorCode (*restorecolumnij)(Mat, PetscInt, PetscBool, PetscBool, PetscInt *, const PetscInt *[], const PetscInt *[], PetscBool *);
104:   /*54*/
105:   PetscErrorCode (*fdcoloringcreate)(Mat, ISColoring, MatFDColoring);
106:   PetscErrorCode (*coloringpatch)(Mat, PetscInt, PetscInt, ISColoringValue[], ISColoring *);
107:   PetscErrorCode (*setunfactored)(Mat);
108:   PetscErrorCode (*permute)(Mat, IS, IS, Mat *);
109:   PetscErrorCode (*setvaluesblocked)(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], const PetscScalar[], InsertMode);
110:   /*59*/
111:   PetscErrorCode (*createsubmatrix)(Mat, IS, IS, MatReuse, Mat *);
112:   PetscErrorCode (*destroy)(Mat);
113:   PetscErrorCode (*view)(Mat, PetscViewer);
114:   PetscErrorCode (*convertfrom)(Mat, MatType, MatReuse, Mat *);
115:   PetscErrorCode (*matmatmultsymbolic)(Mat, Mat, Mat, PetscReal, Mat);
116:   /*64*/
117:   PetscErrorCode (*matmatmultnumeric)(Mat, Mat, Mat, Mat);
118:   PetscErrorCode (*setlocaltoglobalmapping)(Mat, ISLocalToGlobalMapping, ISLocalToGlobalMapping);
119:   PetscErrorCode (*setvalueslocal)(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], const PetscScalar[], InsertMode);
120:   PetscErrorCode (*zerorowslocal)(Mat, PetscInt, const PetscInt[], PetscScalar, Vec, Vec);
121:   PetscErrorCode (*getrowmaxabs)(Mat, Vec, PetscInt[]);
122:   /*69*/
123:   PetscErrorCode (*getrowminabs)(Mat, Vec, PetscInt[]);
124:   PetscErrorCode (*convert)(Mat, MatType, MatReuse, Mat *);
125:   PetscErrorCode (*hasoperation)(Mat, MatOperation, PetscBool *);
126:   PetscErrorCode (*fdcoloringapply)(Mat, MatFDColoring, Vec, void *);
127:   PetscErrorCode (*setfromoptions)(Mat, PetscOptionItems);
128:   /*74*/
129:   PetscErrorCode (*findzerodiagonals)(Mat, IS *);
130:   PetscErrorCode (*mults)(Mat, Vecs, Vecs);
131:   PetscErrorCode (*solves)(Mat, Vecs, Vecs);
132:   PetscErrorCode (*getinertia)(Mat, PetscInt *, PetscInt *, PetscInt *);
133:   PetscErrorCode (*load)(Mat, PetscViewer);
134:   /*79*/
135:   PetscErrorCode (*issymmetric)(Mat, PetscReal, PetscBool *);
136:   PetscErrorCode (*ishermitian)(Mat, PetscReal, PetscBool *);
137:   PetscErrorCode (*isstructurallysymmetric)(Mat, PetscBool *);
138:   PetscErrorCode (*setvaluesblockedlocal)(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], const PetscScalar[], InsertMode);
139:   PetscErrorCode (*getvecs)(Mat, Vec *, Vec *);
140:   /*84*/
141:   PetscErrorCode (*matmultsymbolic)(Mat, Mat, PetscReal, Mat);
142:   PetscErrorCode (*matmultnumeric)(Mat, Mat, Mat);
143:   PetscErrorCode (*ptapnumeric)(Mat, Mat, Mat); /* double dispatch wrapper routine */
144:   PetscErrorCode (*mattransposemultsymbolic)(Mat, Mat, PetscReal, Mat);
145:   PetscErrorCode (*mattransposemultnumeric)(Mat, Mat, Mat);
146:   /*89*/
147:   PetscErrorCode (*bindtocpu)(Mat, PetscBool);
148:   PetscErrorCode (*productsetfromoptions)(Mat);
149:   PetscErrorCode (*productsymbolic)(Mat);
150:   PetscErrorCode (*productnumeric)(Mat);
151:   PetscErrorCode (*conjugate)(Mat); /* complex conjugate */
152:   /*94*/
153:   PetscErrorCode (*viewnative)(Mat, PetscViewer);
154:   PetscErrorCode (*setvaluesrow)(Mat, PetscInt, const PetscScalar[]);
155:   PetscErrorCode (*realpart)(Mat);
156:   PetscErrorCode (*imaginarypart)(Mat);
157:   PetscErrorCode (*getrowuppertriangular)(Mat);
158:   /*99*/
159:   PetscErrorCode (*restorerowuppertriangular)(Mat);
160:   PetscErrorCode (*matsolve)(Mat, Mat, Mat);
161:   PetscErrorCode (*matsolvetranspose)(Mat, Mat, Mat);
162:   PetscErrorCode (*getrowmin)(Mat, Vec, PetscInt[]);
163:   PetscErrorCode (*getcolumnvector)(Mat, Vec, PetscInt);
164:   /*104*/
165:   PetscErrorCode (*getseqnonzerostructure)(Mat, Mat *);
166:   PetscErrorCode (*create)(Mat);
167:   PetscErrorCode (*getghosts)(Mat, PetscInt *, const PetscInt *[]);
168:   PetscErrorCode (*getlocalsubmatrix)(Mat, IS, IS, Mat *);
169:   PetscErrorCode (*restorelocalsubmatrix)(Mat, IS, IS, Mat *);
170:   /*109*/
171:   PetscErrorCode (*multdiagonalblock)(Mat, Vec, Vec);
172:   PetscErrorCode (*hermitiantranspose)(Mat, MatReuse, Mat *);
173:   PetscErrorCode (*multhermitiantranspose)(Mat, Vec, Vec);
174:   PetscErrorCode (*multhermitiantransposeadd)(Mat, Vec, Vec, Vec);
175:   PetscErrorCode (*getmultiprocblock)(Mat, MPI_Comm, MatReuse, Mat *);
176:   /*114*/
177:   PetscErrorCode (*findnonzerorows)(Mat, IS *);
178:   PetscErrorCode (*getcolumnreductions)(Mat, PetscInt, PetscReal *);
179:   PetscErrorCode (*invertblockdiagonal)(Mat, const PetscScalar **);
180:   PetscErrorCode (*invertvariableblockdiagonal)(Mat, PetscInt, const PetscInt *, PetscScalar *);
181:   PetscErrorCode (*createsubmatricesmpi)(Mat, PetscInt, const IS[], const IS[], MatReuse, Mat **);
182:   /*119*/
183:   PetscErrorCode (*transposematmultsymbolic)(Mat, Mat, PetscReal, Mat);
184:   PetscErrorCode (*transposematmultnumeric)(Mat, Mat, Mat);
185:   PetscErrorCode (*transposecoloringcreate)(Mat, ISColoring, MatTransposeColoring);
186:   PetscErrorCode (*transcoloringapplysptoden)(MatTransposeColoring, Mat, Mat);
187:   PetscErrorCode (*transcoloringapplydentosp)(MatTransposeColoring, Mat, Mat);
188:   /*124*/
189:   PetscErrorCode (*rartnumeric)(Mat, Mat, Mat); /* double dispatch wrapper routine */
190:   PetscErrorCode (*setblocksizes)(Mat, PetscInt, PetscInt);
191:   PetscErrorCode (*residual)(Mat, Vec, Vec, Vec);
192:   PetscErrorCode (*fdcoloringsetup)(Mat, ISColoring, MatFDColoring);
193:   PetscErrorCode (*findoffblockdiagonalentries)(Mat, IS *);
194:   /*129*/
195:   PetscErrorCode (*creatempimatconcatenateseqmat)(MPI_Comm, Mat, PetscInt, MatReuse, Mat *);
196:   PetscErrorCode (*destroysubmatrices)(PetscInt, Mat *[]);
197:   PetscErrorCode (*mattransposesolve)(Mat, Mat, Mat);
198:   PetscErrorCode (*getvalueslocal)(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], PetscScalar[]);
199:   PetscErrorCode (*creategraph)(Mat, PetscBool, PetscBool, PetscReal, PetscInt, PetscInt[], Mat *);
200:   /*134*/
201:   PetscErrorCode (*transposesymbolic)(Mat, Mat *);
202:   PetscErrorCode (*eliminatezeros)(Mat, PetscBool);
203:   PetscErrorCode (*getrowsumabs)(Mat, Vec);
204:   PetscErrorCode (*getfactor)(Mat, MatSolverType, MatFactorType, Mat *);
205:   PetscErrorCode (*getblockdiagonal)(Mat, Mat *); // NOTE: the caller of get{block, vblock}diagonal owns the returned matrix;
206:   /*139*/
207:   PetscErrorCode (*getvblockdiagonal)(Mat, Mat *); // they must destroy it after use
208:   PetscErrorCode (*copyhashtoxaij)(Mat, Mat);
209:   PetscErrorCode (*getcurrentmemtype)(Mat, PetscMemType *);
210:   PetscErrorCode (*zerorowscolumnslocal)(Mat, PetscInt, const PetscInt[], PetscScalar, Vec, Vec);
211:   PetscErrorCode (*adot)(Mat, Vec, Vec, PetscScalar *); /* induced vector inner product */
212:   /*144*/
213:   PetscErrorCode (*anorm)(Mat, Vec, PetscReal *); /* induced vector norm */
214:   PetscErrorCode (*adot_local)(Mat, Vec, Vec, PetscScalar *);
215:   PetscErrorCode (*anorm_local)(Mat, Vec, PetscReal *);
216:   PetscErrorCode (*getordering)(Mat, MatOrderingType, IS *, IS *);
217: };
218: /*
219:     If you add MatOps entries above also add them to the MATOP enum
220:     in include/petscmat.h
221: */

223: #include <petscsys.h>

225: typedef struct _n_MatRootName *MatRootName;
226: struct _n_MatRootName {
227:   char       *rname, *sname, *mname;
228:   MatRootName next;
229: };

231: PETSC_EXTERN MatRootName MatRootNameList;

233: /*
234:    Utility private matrix routines used outside Mat
235: */
236: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat, PetscBool, PetscReal, IS *);
237: PETSC_EXTERN PetscErrorCode                MatShellGetScalingShifts(Mat, PetscScalar *, PetscScalar *, Vec *, Vec *, Vec *, Mat *, IS *, IS *);

239: #define MAT_SHELL_NOT_ALLOWED (void *)-1

241: /*
242:    Utility private matrix routines
243: */
244: PETSC_INTERN PetscErrorCode MatConvert_Basic(Mat, MatType, MatReuse, Mat *);
245: PETSC_INTERN PetscErrorCode MatConvert_Shell(Mat, MatType, MatReuse, Mat *);
246: PETSC_INTERN PetscErrorCode MatConvertFrom_Shell(Mat, MatType, MatReuse, Mat *);
247: PETSC_INTERN PetscErrorCode MatShellSetContext_Immutable(Mat, void *);
248: PETSC_INTERN PetscErrorCode MatShellSetContextDestroy_Immutable(Mat, PetscCtxDestroyFn *);
249: PETSC_INTERN PetscErrorCode MatShellSetManageScalingShifts_Immutable(Mat);
250: PETSC_INTERN PetscErrorCode MatCopy_Basic(Mat, Mat, MatStructure);
251: PETSC_INTERN PetscErrorCode MatDiagonalSet_Default(Mat, Vec, InsertMode);
252: #if PetscDefined(HAVE_SCALAPACK) && (PetscDefined(USE_REAL_SINGLE) || PetscDefined(USE_REAL_DOUBLE))
253: PETSC_INTERN PetscErrorCode MatConvert_Dense_ScaLAPACK(Mat, MatType, MatReuse, Mat *);
254: #endif
255: PETSC_INTERN PetscErrorCode MatSetPreallocationCOO_Basic(Mat, PetscCount, PetscInt[], PetscInt[]);
256: PETSC_INTERN PetscErrorCode MatSetValuesCOO_Basic(Mat, const PetscScalar[], InsertMode);

258: /*
259:    Index translation for the local submatrices of MATLOCALREF and MATIS, which both forward their local
260:    insertions to another matrix. These need to be macros because they use sizeof
261: */
262: #define MatIndexSpaceGet_Private(buf, nrow, ncol, irowm, icolm) \
263:   do { \
264:     if ((nrow) + (ncol) > (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { \
265:       PetscCall(PetscMalloc2(nrow, &(irowm), ncol, &(icolm))); \
266:     } else { \
267:       irowm = &(buf)[0]; \
268:       icolm = &(buf)[nrow]; \
269:     } \
270:   } while (0)

272: #define MatIndexSpaceRestore_Private(buf, nrow, ncol, irowm, icolm) \
273:   do { \
274:     if ((nrow) + (ncol) > (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) PetscCall(PetscFree2(irowm, icolm)); \
275:   } while (0)

277: /* Turn n block indices into the n * bs scalar indices they stand for */
278: static inline void MatBlockIndicesExpand_Private(PetscInt n, const PetscInt idx[], PetscInt bs, PetscInt idxm[])
279: {
280:   for (PetscInt i = 0; i < n; i++) {
281:     for (PetscInt j = 0; j < bs; j++) idxm[i * bs + j] = idx[i] * bs + j;
282:   }
283: }

285: /* Scattering of dense matrices with strided PetscSF */
286: PETSC_EXTERN PetscErrorCode MatDenseScatter_Private(PetscSF, Mat, Mat, InsertMode, ScatterMode);

288: /* This can be moved to the public header after implementing some missing MatProducts */
289: PETSC_INTERN PetscErrorCode MatCreateFromISLocalToGlobalMapping(ISLocalToGlobalMapping, Mat, PetscBool, PetscBool, MatType, Mat *);

291: /* these callbacks rely on the old matrix function pointers for
292:    matmat operations. They are unsafe, and should be removed.
293:    However, the amount of work needed to clean up all the
294:    implementations is not negligible */
295: PETSC_INTERN PetscErrorCode MatProductSymbolic_AB(Mat);
296: PETSC_INTERN PetscErrorCode MatProductNumeric_AB(Mat);
297: PETSC_INTERN PetscErrorCode MatProductSymbolic_AtB(Mat);
298: PETSC_INTERN PetscErrorCode MatProductNumeric_AtB(Mat);
299: PETSC_INTERN PetscErrorCode MatProductSymbolic_ABt(Mat);
300: PETSC_INTERN PetscErrorCode MatProductNumeric_ABt(Mat);
301: PETSC_INTERN PetscErrorCode MatProductNumeric_PtAP(Mat);
302: PETSC_INTERN PetscErrorCode MatProductNumeric_RARt(Mat);
303: PETSC_INTERN PetscErrorCode MatProductSymbolic_ABC(Mat);
304: PETSC_INTERN PetscErrorCode MatProductNumeric_ABC(Mat);

306: PETSC_INTERN PetscErrorCode MatProductCreate_Private(Mat, Mat, Mat, Mat);
307: /* this callback handles all the different triple products and
308:    does not rely on the function pointers; used by cuSPARSE/hipSPARSE and KOKKOS-KERNELS */
309: PETSC_INTERN PetscErrorCode MatProductSymbolic_ABC_Basic(Mat);

311: /* CreateGraph is common to AIJ seq and mpi */
312: PETSC_INTERN PetscErrorCode MatCreateGraph_Simple_AIJ(Mat, PetscBool, PetscBool, PetscReal, PetscInt, PetscInt[], Mat *);

314: #if PetscDefined(CLANG_STATIC_ANALYZER)
315: template <typename Tm>
316: extern void MatCheckPreallocated(Tm, int);
317: template <typename Tm>
318: extern void MatCheckProduct(Tm, int);
319: #else /* PETSC_CLANG_STATIC_ANALYZER */
320:   #define MatCheckPreallocated(A, arg) \
321:     do { \
322:       if (!(A)->preallocated) PetscCall(MatSetUp(A)); \
323:     } while (0)

325:   #if PetscDefined(USE_DEBUG)
326:     #define MatCheckProduct(A, arg) \
327:       do { \
328:         PetscCheck((A)->product, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Argument %d \"%s\" is not a matrix obtained from MatProductCreate()", arg, #A); \
329:       } while (0)
330:   #else
331:     #define MatCheckProduct(A, arg) \
332:       do { \
333:       } while (0)
334:   #endif
335: #endif /* PETSC_CLANG_STATIC_ANALYZER */

337: /*
338:   The stash is used to temporarily store inserted matrix values that
339:   belong to another processor. During the assembly phase the stashed
340:   values are moved to the correct processor and
341: */

343: typedef struct _MatStashSpace *PetscMatStashSpace;

345: struct _MatStashSpace {
346:   PetscMatStashSpace next;
347:   PetscScalar       *space_head, *val;
348:   PetscInt          *idx, *idy;
349:   PetscInt           total_space_size;
350:   PetscInt           local_used;
351:   PetscInt           local_remaining;
352: };

354: PETSC_EXTERN PetscErrorCode PetscMatStashSpaceGet(PetscInt, PetscInt, PetscMatStashSpace *);
355: PETSC_EXTERN PetscErrorCode PetscMatStashSpaceContiguous(PetscInt, PetscMatStashSpace *, PetscScalar *, PetscInt *, PetscInt *);
356: PETSC_EXTERN PetscErrorCode PetscMatStashSpaceDestroy(PetscMatStashSpace *);

358: typedef struct {
359:   PetscInt count;
360: } MatStashHeader;

362: typedef struct {
363:   void    *buffer; /* Of type blocktype, dynamically constructed  */
364:   PetscInt count;
365:   char     pending;
366: } MatStashFrame;

368: typedef struct _MatStash MatStash;
369: struct _MatStash {
370:   PetscInt           nmax;              /* maximum stash size */
371:   PetscInt           umax;              /* user specified max-size */
372:   PetscInt           oldnmax;           /* the nmax value used previously */
373:   PetscInt           n;                 /* stash size */
374:   PetscInt           bs;                /* block size of the stash */
375:   PetscInt           reallocs;          /* preserve the no of mallocs invoked */
376:   PetscMatStashSpace space_head, space; /* linked list to hold stashed global row/column numbers and matrix values */

378:   PetscErrorCode (*ScatterBegin)(Mat, MatStash *, PetscInt *);
379:   PetscErrorCode (*ScatterGetMesg)(MatStash *, PetscMPIInt *, PetscInt **, PetscInt **, PetscScalar **, PetscInt *);
380:   PetscErrorCode (*ScatterEnd)(MatStash *);
381:   PetscErrorCode (*ScatterDestroy)(MatStash *);

383:   /* The following variables are used for communication */
384:   MPI_Comm      comm;
385:   PetscMPIInt   size, rank;
386:   PetscMPIInt   tag1, tag2;
387:   MPI_Request  *send_waits;     /* array of send requests */
388:   MPI_Request  *recv_waits;     /* array of receive requests */
389:   MPI_Status   *send_status;    /* array of send status */
390:   PetscMPIInt   nsends, nrecvs; /* numbers of sends and receives */
391:   PetscScalar  *svalues;        /* sending data */
392:   PetscInt     *sindices;
393:   PetscScalar **rvalues;    /* receiving data (values) */
394:   PetscInt    **rindices;   /* receiving data (indices) */
395:   PetscMPIInt   nprocessed; /* number of messages already processed */
396:   PetscMPIInt  *flg_v;      /* indicates what messages have arrived so far and from whom */
397:   PetscBool     reproduce;
398:   PetscMPIInt   reproduce_count;

400:   /* The following variables are used for BTS communication */
401:   PetscBool       first_assembly_done; /* Is the first time matrix assembly done? */
402:   PetscBool       use_status;          /* Use MPI_Status to determine number of items in each message */
403:   PetscMPIInt     nsendranks;
404:   PetscMPIInt     nrecvranks;
405:   PetscMPIInt    *sendranks;
406:   PetscMPIInt    *recvranks;
407:   MatStashHeader *sendhdr, *recvhdr;
408:   MatStashFrame  *sendframes; /* pointers to the main messages */
409:   MatStashFrame  *recvframes;
410:   MatStashFrame  *recvframe_active;
411:   PetscInt        recvframe_i;     /* index of block within active frame */
412:   PetscInt        recvframe_count; /* Count actually sent for current frame */
413:   PetscMPIInt     recvcount;       /* Number of receives processed so far */
414:   PetscMPIInt    *some_indices;    /* From last call to MPI_Waitsome */
415:   MPI_Status     *some_statuses;   /* Statuses from last call to MPI_Waitsome */
416:   PetscMPIInt     some_count;      /* Number of requests completed in last call to MPI_Waitsome */
417:   PetscMPIInt     some_i;          /* Index of request currently being processed */
418:   MPI_Request    *sendreqs;
419:   MPI_Request    *recvreqs;
420:   PetscSegBuffer  segsendblocks;
421:   PetscSegBuffer  segrecvframe;
422:   PetscSegBuffer  segrecvblocks;
423:   MPI_Datatype    blocktype;
424:   size_t          blocktype_size;
425:   InsertMode     *insertmode; /* Pointer to check mat->insertmode and set upon message arrival in case no local values have been set. */
426: };

428: #if !PetscDefined(HAVE_MPIUNI)
429: PETSC_INTERN PetscErrorCode MatStashScatterDestroy_BTS(MatStash *);
430: #endif
431: PETSC_INTERN PetscErrorCode MatStashCreate_Private(MPI_Comm, PetscInt, MatStash *);
432: PETSC_INTERN PetscErrorCode MatStashDestroy_Private(MatStash *);
433: PETSC_INTERN PetscErrorCode MatStashScatterEnd_Private(MatStash *);
434: PETSC_INTERN PetscErrorCode MatStashSetInitialSize_Private(MatStash *, PetscInt);
435: PETSC_INTERN PetscErrorCode MatStashGetInfo_Private(MatStash *, PetscInt *, PetscInt *);
436: PETSC_INTERN PetscErrorCode MatStashValuesRow_Private(MatStash *, PetscInt, PetscInt, const PetscInt[], const PetscScalar[], PetscBool);
437: PETSC_INTERN PetscErrorCode MatStashValuesCol_Private(MatStash *, PetscInt, PetscInt, const PetscInt[], const PetscScalar[], PetscInt, PetscBool);
438: PETSC_INTERN PetscErrorCode MatStashValuesRowBlocked_Private(MatStash *, PetscInt, PetscInt, const PetscInt[], const PetscScalar[], PetscInt, PetscInt, PetscInt);
439: PETSC_INTERN PetscErrorCode MatStashValuesColBlocked_Private(MatStash *, PetscInt, PetscInt, const PetscInt[], const PetscScalar[], PetscInt, PetscInt, PetscInt);
440: PETSC_INTERN PetscErrorCode MatStashScatterBegin_Private(Mat, MatStash *, PetscInt *);
441: PETSC_INTERN PetscErrorCode MatStashScatterGetMesg_Private(MatStash *, PetscMPIInt *, PetscInt **, PetscInt **, PetscScalar **, PetscInt *);
442: PETSC_INTERN PetscErrorCode MatGetInfo_External(Mat, MatInfoType, MatInfo *);

444: typedef struct {
445:   PetscInt  dim;
446:   PetscInt  dims[4];
447:   PetscInt  starts[4];
448:   PetscBool noc; /* this is a single component problem, hence user will not set MatStencil.c */
449: } MatStencilInfo;

451: /* Info about using compressed row format */
452: typedef struct {
453:   PetscBool use;    /* indicates compressed rows have been checked and will be used */
454:   PetscInt  nrows;  /* number of non-zero rows */
455:   PetscInt *i;      /* compressed row pointer  */
456:   PetscInt *rindex; /* compressed row index               */
457: } Mat_CompressedRow;
458: PETSC_EXTERN PetscErrorCode MatCheckCompressedRow(Mat, PetscInt, Mat_CompressedRow *, PetscInt *, PetscInt, PetscReal);

460: typedef struct { /* used by MatCreateRedundantMatrix() for reusing matredundant */
461:   PetscInt     nzlocal, nsends, nrecvs;
462:   PetscMPIInt *send_rank, *recv_rank;
463:   PetscInt    *sbuf_nz, *rbuf_nz, *sbuf_j, **rbuf_j;
464:   PetscScalar *sbuf_a, **rbuf_a;
465:   MPI_Comm     subcomm; /* when user does not provide a subcomm */
466:   IS           isrow, iscol;
467:   Mat         *matseq;
468: } Mat_Redundant;

470: typedef struct { /* used by MatProduct() */
471:   MatProductType type;
472:   char          *alg;
473:   Mat            A, B, C, Dwork;
474:   PetscBool      symbolic_used_the_fact_A_is_symmetric; /* Symbolic phase took advantage of the fact that A is symmetric, and optimized e.g. AtB as AB. Then, .. */
475:   PetscBool      symbolic_used_the_fact_B_is_symmetric; /* .. in the numeric phase, if a new A is not symmetric (but has the same sparsity as the old A therefore .. */
476:   PetscBool      symbolic_used_the_fact_C_is_symmetric; /* MatMatMult(A,B,MAT_REUSE_MATRIX,..&C) is still legitimate), we need to redo symbolic! */
477:   PetscObjectParameterDeclare(PetscReal, fill);
478:   PetscBool api_user; /* used to distinguish command line options and to indicate the matrix values are ready to be consumed at symbolic phase if needed */
479:   PetscBool setfromoptionscalled;

481:   /* Some products may display the information on the algorithm used */
482:   PetscErrorCode (*view)(Mat, PetscViewer);

484:   /* nonzero state of A at the last symbolic phase, used by MatProductComputeWithMat_Private() to run that phase again when the nonzero pattern of A changes */
485:   PetscObjectState Anonzerostate;

487:   /* many products have intermediate data structures, each specific to Mat types and product type */
488:   PetscBool          clear;   /* whether or not to clear the data structures after MatProductNumeric has been called */
489:   void              *data;    /* where to stash those structures */
490:   PetscCtxDestroyFn *destroy; /* freeing data */
491: } Mat_Product;

493: struct _p_Mat {
494:   PETSCHEADER(struct _MatOps);
495:   PetscLayout      rmap, cmap;
496:   void            *data;                                    /* implementation-specific data */
497:   MatFactorType    factortype;                              /* MAT_FACTOR_LU, ILU, CHOLESKY or ICC */
498:   PetscBool        trivialsymbolic;                         /* indicates the symbolic factorization doesn't actually do a symbolic factorization, it is delayed to the numeric factorization */
499:   PetscBool        canuseordering;                          /* factorization can use ordering provide to routine (most PETSc implementations) */
500:   MatOrderingType  preferredordering[MAT_FACTOR_NUM_TYPES]; /* what is the preferred (or default) ordering for the matrix solver type */
501:   PetscBool        assembled;                               /* is the matrix assembled? */
502:   PetscBool        was_assembled;                           /* new values inserted into assembled mat */
503:   PetscInt         num_ass;                                 /* number of times matrix has been assembled */
504:   PetscObjectState nonzerostate;                            /* each time new nonzeros locations are introduced into the matrix this is updated */
505:   PetscObjectState ass_nonzerostate;                        /* nonzero state at last assembly */
506:   MatInfo          info;                                    /* matrix information */
507:   InsertMode       insertmode;                              /* have values been inserted in matrix or added? */
508:   MatStash         stash, bstash;                           /* used for assembling off-proc mat emements */
509:   MatNullSpace     nullsp;                                  /* null space (operator is singular) */
510:   MatNullSpace     transnullsp;                             /* null space of transpose of operator */
511:   MatNullSpace     nearnullsp;                              /* near null space to be used by multigrid methods */
512:   PetscInt         congruentlayouts;                        /* are the rows and columns layouts congruent? */
513:   PetscBool        preallocated;
514:   MatStencilInfo   stencil; /* information for structured grid */
515:   PetscBool3       symmetric, hermitian, structurally_symmetric, spd;
516:   PetscBool        symmetry_eternal, structural_symmetry_eternal, spd_eternal;
517:   PetscBool        nooffprocentries, nooffproczerorows;
518:   PetscBool        assembly_subset; /* set by MAT_SUBSET_OFF_PROC_ENTRIES */
519:   PetscBool        submat_singleis; /* for efficient PCSetUp_ASM() */
520:   PetscBool        structure_only;
521:   PetscBool        sortedfull;      /* full, sorted rows are inserted */
522:   PetscBool        force_diagonals; /* set by MAT_FORCE_DIAGONAL_ENTRIES */
523: #if PetscDefined(HAVE_DEVICE)
524:   PetscOffloadMask offloadmask; /* a mask which indicates where the valid matrix data is (GPU, CPU or both) */
525:   PetscBool        boundtocpu;
526:   PetscBool        bindingpropagates;
527: #endif
528:   char                *defaultrandtype;
529:   void                *spptr; /* pointer for special library like SuperLU */
530:   char                *solvertype;
531:   PetscBool            checksymmetryonassembly, checknullspaceonassembly;
532:   PetscReal            checksymmetrytol;
533:   Mat                  schur;                            /* Schur complement matrix */
534:   MatFactorSchurStatus schur_status;                     /* status of the Schur complement matrix */
535:   Mat_Redundant       *redundant;                        /* used by MatCreateRedundantMatrix() */
536:   PetscBool            erroriffailure;                   /* Generate an error if detected (for example a zero pivot) instead of returning */
537:   MatFactorError       factorerrortype;                  /* type of error in factorization */
538:   PetscReal            factorerror_zeropivot_value;      /* If numerical zero pivot was detected this is the computed value */
539:   PetscInt             factorerror_zeropivot_row;        /* Row where zero pivot was detected */
540:   PetscInt             nblocks, *bsizes;                 /* support for MatSetVariableBlockSizes() */
541:   PetscInt             p_cstart, p_rank, p_cend, n_rank; /* Information from parallel MatComputeVariableBlockEnvelope() */
542:   PetscBool            p_parallel;
543:   char                *defaultvectype;
544:   Mat_Product         *product;
545:   PetscBool            form_explicit_transpose; /* hint to generate an explicit mat tranpsose for operations like MatMultTranspose() */
546:   PetscBool            transupdated;            /* whether or not the explicitly generated transpose is up-to-date */
547:   char                *factorprefix;            /* the prefix to use with factored matrix that is created */
548:   PetscBool            hash_active;             /* indicates MatSetValues() is being handled by hashing */
549:   Vec                  dot_vec;                 /* work vector used by MatADot_Default() */
550: };

552: PETSC_INTERN PetscErrorCode MatAXPY_Basic(Mat, PetscScalar, Mat, MatStructure);
553: PETSC_INTERN PetscErrorCode MatAXPY_BasicWithPreallocation(Mat, Mat, PetscScalar, Mat, MatStructure);
554: PETSC_INTERN PetscErrorCode MatAXPY_Basic_Preallocate(Mat, Mat, Mat *);
555: PETSC_INTERN PetscErrorCode MatAXPY_Dense_Nest(Mat, PetscScalar, Mat);

557: /*
558:     Utility for MatZeroRows
559: */
560: PETSC_INTERN PetscErrorCode MatZeroRowsMapLocal_Private(Mat, PetscInt, const PetscInt *, PetscInt *, PetscInt **);

562: /*
563:     Utility for MatView/MatLoad
564: */
565: PETSC_INTERN PetscErrorCode MatView_Binary_BlockSizes(Mat, PetscViewer);
566: PETSC_INTERN PetscErrorCode MatLoad_Binary_BlockSizes(Mat, PetscViewer);

568: /*
569:     Object for partitioning graphs
570: */

572: typedef struct _MatPartitioningOps *MatPartitioningOps;
573: struct _MatPartitioningOps {
574:   PetscErrorCode (*apply)(MatPartitioning, IS *);
575:   PetscErrorCode (*applynd)(MatPartitioning, IS *);
576:   PetscErrorCode (*setfromoptions)(MatPartitioning, PetscOptionItems);
577:   PetscErrorCode (*destroy)(MatPartitioning);
578:   PetscErrorCode (*view)(MatPartitioning, PetscViewer);
579:   PetscErrorCode (*improve)(MatPartitioning, IS *);
580: };

582: struct _p_MatPartitioning {
583:   PETSCHEADER(struct _MatPartitioningOps);
584:   Mat        adj;
585:   PetscInt  *vertex_weights;
586:   PetscReal *part_weights;
587:   PetscInt   n;    /* number of partitions */
588:   PetscInt   ncon; /* number of vertex weights per vertex */
589:   void      *data;
590:   PetscBool  use_edge_weights; /* A flag indicates whether or not to use edge weights */
591: };

593: /* needed for parallel nested dissection by ParMETIS */
594: PETSC_INTERN PetscErrorCode MatPartitioningSizesToSep_Private(PetscInt, PetscInt[], PetscInt[], PetscInt[]);

596: /* shared by the MatPartitioning and PetscPartitioner bindings to PT-SCOTCH */
597: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscPTSCOTCHPartitionGraph_Private(MPI_Comm, const PetscInt[], PetscInt[], PetscInt[], PetscInt[], PetscInt[], PetscBool, PetscInt, PetscInt[], PetscInt, double, PetscInt[]);

599: /*
600:     Object for coarsen graphs
601: */
602: typedef struct _MatCoarsenOps *MatCoarsenOps;
603: struct _MatCoarsenOps {
604:   PetscErrorCode (*apply)(MatCoarsen);
605:   PetscErrorCode (*setfromoptions)(MatCoarsen, PetscOptionItems);
606:   PetscErrorCode (*destroy)(MatCoarsen);
607:   PetscErrorCode (*view)(MatCoarsen, PetscViewer);
608: };

610: #define MAT_COARSEN_STRENGTH_INDEX_SIZE 3
611: struct _p_MatCoarsen {
612:   PETSCHEADER(struct _MatCoarsenOps);
613:   Mat   graph;
614:   void *subctx;
615:   /* */
616:   PetscBool         strict_aggs;
617:   IS                perm;
618:   PetscCoarsenData *agg_lists;
619:   PetscInt          max_it;    /* number of iterations in HEM */
620:   PetscReal         threshold; /* HEM can filter interim graphs */
621:   PetscInt          strength_index_size;
622:   PetscInt          strength_index[MAT_COARSEN_STRENGTH_INDEX_SIZE];
623: };

625: PETSC_EXTERN PetscErrorCode MatCoarsenMISKSetDistance(MatCoarsen, PetscInt);
626: PETSC_EXTERN PetscErrorCode MatCoarsenMISKGetDistance(MatCoarsen, PetscInt *);

628: /*
629:     Used in aijdevice.h
630: */
631: typedef struct {
632:   PetscInt    *i;
633:   PetscInt    *j;
634:   PetscScalar *a;
635:   PetscInt     n;
636:   PetscInt     ignorezeroentries;
637: } PetscCSRDataStructure;

639: /*
640:     MatFDColoring is used to compute Jacobian matrices efficiently
641:   via coloring. The data structure is explained below in an example.

643:    Color =   0    1     0    2   |   2      3       0
644:    ---------------------------------------------------
645:             00   01              |          05
646:             10   11              |   14     15               Processor  0
647:                        22    23  |          25
648:                        32    33  |
649:    ===================================================
650:                                  |   44     45     46
651:             50                   |          55               Processor 1
652:                                  |   64            66
653:    ---------------------------------------------------

655:     ncolors = 4;

657:     ncolumns      = {2,1,1,0}
658:     columns       = {{0,2},{1},{3},{}}
659:     nrows         = {4,2,3,3}
660:     rows          = {{0,1,2,3},{0,1},{1,2,3},{0,1,2}}
661:     vwscale       = {dx(0),dx(1),dx(2),dx(3)}               MPI Vec
662:     vscale        = {dx(0),dx(1),dx(2),dx(3),dx(4),dx(5)}   Seq Vec

664:     ncolumns      = {1,0,1,1}
665:     columns       = {{6},{},{4},{5}}
666:     nrows         = {3,0,2,2}
667:     rows          = {{0,1,2},{},{1,2},{1,2}}
668:     vwscale       = {dx(4),dx(5),dx(6)}              MPI Vec
669:     vscale        = {dx(0),dx(4),dx(5),dx(6)}        Seq Vec

671:     See the routine MatFDColoringApply() for how this data is used
672:     to compute the Jacobian.

674: */
675: typedef struct {
676:   PetscInt     row;
677:   PetscInt     col;
678:   PetscScalar *valaddr; /* address of value */
679: } MatEntry;

681: typedef struct {
682:   PetscInt     row;
683:   PetscScalar *valaddr; /* address of value */
684: } MatEntry2;

686: struct _p_MatFDColoring {
687:   PETSCHEADER(int);
688:   PetscInt                M, N, m;          /* total rows, columns; local rows */
689:   PetscInt                rstart;           /* first row owned by local processor */
690:   PetscInt                ncolors;          /* number of colors */
691:   PetscInt               *ncolumns;         /* number of local columns for a color */
692:   PetscInt              **columns;          /* lists the local columns of each color (using global column numbering) */
693:   IS                     *isa;              /* these are the IS that contain the column values given in columns */
694:   PetscInt               *nrows;            /* number of local rows for each color */
695:   MatEntry               *matentry;         /* holds (row, column, address of value) for Jacobian matrix entry */
696:   MatEntry2              *matentry2;        /* holds (row, address of value) for Jacobian matrix entry */
697:   PetscScalar            *dy;               /* store a block of F(x+dx)-F(x) when J is in BAIJ format */
698:   PetscReal               error_rel;        /* square root of relative error in computing function */
699:   PetscReal               umin;             /* minimum allowable u'dx value */
700:   Vec                     w1, w2, w3;       /* work vectors used in computing Jacobian */
701:   PetscBool               fset;             /* indicates that the initial function value F(X) is set */
702:   MatFDColoringFn        *f;                /* function that defines Jacobian */
703:   void                   *fctx;             /* optional user-defined context for use by the function f */
704:   Vec                     vscale;           /* holds FD scaling, i.e. 1/dx for each perturbed column */
705:   PetscInt                currentcolor;     /* color for which function evaluation is being done now */
706:   const char             *htype;            /* "wp" or "ds" */
707:   ISColoringType          ctype;            /* IS_COLORING_GLOBAL or IS_COLORING_LOCAL */
708:   PetscInt                brows, bcols;     /* number of block rows or columns for speedup inserting the dense matrix into sparse Jacobian */
709:   PetscBool               setupcalled;      /* true if setup has been called */
710:   PetscBool               viewed;           /* true if the -mat_fd_coloring_view has been triggered already */
711:   PetscFortranCallbackFn *ftn_func_pointer; /* serve the same purpose as *fortran_func_pointers in PETSc objects */
712:   void                   *ftn_func_cntx;
713:   PetscObjectId           matid; /* matrix this object was created with, must always be the same */
714: };

716: typedef struct _MatColoringOps *MatColoringOps;
717: struct _MatColoringOps {
718:   PetscErrorCode (*destroy)(MatColoring);
719:   PetscErrorCode (*setfromoptions)(MatColoring, PetscOptionItems);
720:   PetscErrorCode (*view)(MatColoring, PetscViewer);
721:   PetscErrorCode (*apply)(MatColoring, ISColoring *);
722:   PetscErrorCode (*weights)(MatColoring, PetscReal **, PetscInt **);
723: };

725: struct _p_MatColoring {
726:   PETSCHEADER(struct _MatColoringOps);
727:   Mat                   mat;
728:   PetscInt              dist;         /* distance of the coloring */
729:   PetscInt              maxcolors;    /* the maximum number of colors returned, maxcolors=1 for MIS */
730:   void                 *data;         /* inner context */
731:   PetscBool             valid;        /* check to see if what is produced is a valid coloring */
732:   MatColoringWeightType weight_type;  /* type of weight computation to be performed */
733:   PetscReal            *user_weights; /* custom weights and permutation */
734:   PetscInt             *user_lperm;
735:   PetscBool             valid_iscoloring; /* check to see if matcoloring is produced a valid iscoloring */
736: };

738: struct _p_MatTransposeColoring {
739:   PETSCHEADER(int);
740:   PetscInt       M, N, m;      /* total rows, columns; local rows */
741:   PetscInt       rstart;       /* first row owned by local processor */
742:   PetscInt       ncolors;      /* number of colors */
743:   PetscInt      *ncolumns;     /* number of local columns for a color */
744:   PetscInt      *nrows;        /* number of local rows for each color */
745:   PetscInt       currentcolor; /* color for which function evaluation is being done now */
746:   ISColoringType ctype;        /* IS_COLORING_GLOBAL or IS_COLORING_LOCAL */

748:   PetscInt *colorforrow, *colorforcol; /* pointer to rows and columns */
749:   PetscInt *rows;                      /* lists the local rows for each color (using the local row numbering) */
750:   PetscInt *den2sp;                    /* maps (row,color) in the dense matrix to index of sparse matrix array a->a */
751:   PetscInt *columns;                   /* lists the local columns of each color (using global column numbering) */
752:   PetscInt  brows;                     /* number of rows for efficient implementation of MatTransColoringApplyDenToSp() */
753:   PetscInt *lstart;                    /* array used for loop over row blocks of Csparse */
754: };

756: /*
757:    Null space context for preconditioner/operators
758: */
759: struct _p_MatNullSpace {
760:   PETSCHEADER(int);
761:   PetscBool             has_cnst;
762:   PetscInt              n;
763:   Vec                  *vecs;
764:   PetscScalar          *alpha;  /* for projections */
765:   MatNullSpaceRemoveFn *remove; /* for user provided removal function */
766:   void                 *rmctx;  /* context for remove() function */
767: };

769: /*
770:    Internal data structure for MATMPIDENSE
771: */
772: typedef struct {
773:   Mat A; /* local submatrix */

775:   /* The following variables are used for matrix assembly */
776:   PetscBool    donotstash;        /* Flag indicating if values should be stashed */
777:   MPI_Request *send_waits;        /* array of send requests */
778:   MPI_Request *recv_waits;        /* array of receive requests */
779:   PetscInt     nsends, nrecvs;    /* numbers of sends and receives */
780:   PetscScalar *svalues, *rvalues; /* sending and receiving data */
781:   PetscInt     rmax;              /* maximum message length */

783:   /* The following variables are used for matrix-vector products */
784:   Vec       lvec;        /* local vector */
785:   PetscSF   Mvctx;       /* for mat-mult communications */
786:   PetscBool roworiented; /* if true, row-oriented input (default) */

788:   /* Support for MatDenseGetColumnVec and MatDenseGetSubMatrix */
789:   Mat                cmat;     /* matrix representation of a given subset of columns */
790:   Vec                cvec;     /* vector representation of a given column */
791:   const PetscScalar *ptrinuse; /* holds array to be restored (just a placeholder) */
792:   PetscInt           vecinuse; /* if cvec is in use (col = vecinuse-1) */
793:   PetscInt           matinuse; /* if cmat is in use (cbegin = matinuse-1) */
794:   /* if this is from MatDenseGetSubMatrix, which columns and rows does it correspond to? */
795:   PetscInt sub_rbegin;
796:   PetscInt sub_rend;
797:   PetscInt sub_cbegin;
798:   PetscInt sub_cend;
799: } Mat_MPIDense;

801: /*
802:    Checking zero pivot for LU, ILU preconditioners.
803: */
804: typedef struct {
805:   PetscInt    nshift, nshift_max;
806:   PetscReal   shift_amount, shift_lo, shift_hi, shift_top, shift_fraction;
807:   PetscBool   newshift;
808:   PetscReal   rs; /* active row sum of abs(off-diagonals) */
809:   PetscScalar pv; /* pivot of the active row */
810: } FactorShiftCtx;

812: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat, Mat);

814: PETSC_EXTERN PetscErrorCode MatFactorDumpMatrix(Mat);
815: PETSC_INTERN PetscErrorCode MatSetBlockSizes_Default(Mat, PetscInt, PetscInt);

817: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatShift_Basic(Mat, PetscScalar);
818: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatProductComputeWithMat_Private(Mat, Mat, MatProductType, Mat);

820: static inline PetscErrorCode MatPivotCheck_nz(PETSC_UNUSED Mat mat, const MatFactorInfo *info, FactorShiftCtx *sctx, PETSC_UNUSED PetscInt row)
821: {
822:   PetscReal _rs   = sctx->rs;
823:   PetscReal _zero = info->zeropivot * _rs;

825:   PetscFunctionBegin;
826:   if (PetscAbsScalar(sctx->pv) <= _zero && !PetscIsNanScalar(sctx->pv)) {
827:     /* force |diag| > zeropivot*rs */
828:     if (!sctx->nshift) sctx->shift_amount = info->shiftamount;
829:     else sctx->shift_amount *= 2.0;
830:     sctx->newshift = PETSC_TRUE;
831:     sctx->nshift++;
832:   } else {
833:     sctx->newshift = PETSC_FALSE;
834:   }
835:   PetscFunctionReturn(PETSC_SUCCESS);
836: }

838: static inline PetscErrorCode MatPivotCheck_pd(PETSC_UNUSED Mat mat, const MatFactorInfo *info, FactorShiftCtx *sctx, PETSC_UNUSED PetscInt row)
839: {
840:   PetscReal _rs   = sctx->rs;
841:   PetscReal _zero = info->zeropivot * _rs;

843:   PetscFunctionBegin;
844:   if (PetscRealPart(sctx->pv) <= _zero && !PetscIsNanScalar(sctx->pv)) {
845:     /* force matfactor to be diagonally dominant */
846:     if (sctx->nshift == sctx->nshift_max) {
847:       sctx->shift_fraction = sctx->shift_hi;
848:     } else {
849:       sctx->shift_lo       = sctx->shift_fraction;
850:       sctx->shift_fraction = (sctx->shift_hi + sctx->shift_lo) / (PetscReal)2.;
851:     }
852:     sctx->shift_amount = sctx->shift_fraction * sctx->shift_top;
853:     sctx->nshift++;
854:     sctx->newshift = PETSC_TRUE;
855:   } else {
856:     sctx->newshift = PETSC_FALSE;
857:   }
858:   PetscFunctionReturn(PETSC_SUCCESS);
859: }

861: static inline PetscErrorCode MatPivotCheck_inblocks(PETSC_UNUSED Mat mat, const MatFactorInfo *info, FactorShiftCtx *sctx, PETSC_UNUSED PetscInt row)
862: {
863:   PetscReal _zero = info->zeropivot;

865:   PetscFunctionBegin;
866:   if (PetscAbsScalar(sctx->pv) <= _zero && !PetscIsNanScalar(sctx->pv)) {
867:     sctx->pv += info->shiftamount;
868:     sctx->shift_amount = 0.0;
869:     sctx->nshift++;
870:   }
871:   sctx->newshift = PETSC_FALSE;
872:   PetscFunctionReturn(PETSC_SUCCESS);
873: }

875: static inline PetscErrorCode MatPivotCheck_none(Mat fact, Mat mat, const MatFactorInfo *info, FactorShiftCtx *sctx, PetscInt row)
876: {
877:   PetscReal _zero = info->zeropivot;

879:   PetscFunctionBegin;
880:   sctx->newshift = PETSC_FALSE;
881:   if (PetscAbsScalar(sctx->pv) <= _zero && !PetscIsNanScalar(sctx->pv)) {
882:     PetscCheck(!mat->erroriffailure, PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Zero pivot row %" PetscInt_FMT " value %g tolerance %g", row, (double)PetscAbsScalar(sctx->pv), (double)_zero);
883:     PetscCall(PetscInfo(mat, "Detected zero pivot in factorization in row %" PetscInt_FMT " value %g tolerance %g\n", row, (double)PetscAbsScalar(sctx->pv), (double)_zero));
884:     fact->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
885:     fact->factorerror_zeropivot_value = PetscAbsScalar(sctx->pv);
886:     fact->factorerror_zeropivot_row   = row;
887:   }
888:   PetscFunctionReturn(PETSC_SUCCESS);
889: }

891: static inline PetscErrorCode MatPivotCheck(Mat fact, Mat mat, const MatFactorInfo *info, FactorShiftCtx *sctx, PetscInt row)
892: {
893:   PetscFunctionBegin;
894:   if (info->shifttype == (PetscReal)MAT_SHIFT_NONZERO) PetscCall(MatPivotCheck_nz(mat, info, sctx, row));
895:   else if (info->shifttype == (PetscReal)MAT_SHIFT_POSITIVE_DEFINITE) PetscCall(MatPivotCheck_pd(mat, info, sctx, row));
896:   else if (info->shifttype == (PetscReal)MAT_SHIFT_INBLOCKS) PetscCall(MatPivotCheck_inblocks(mat, info, sctx, row));
897:   else PetscCall(MatPivotCheck_none(fact, mat, info, sctx, row));
898:   PetscFunctionReturn(PETSC_SUCCESS);
899: }

901: #include <petscbt.h>
902: /*
903:   Create and initialize a linked list
904:   Input Parameters:
905:     idx_start - starting index of the list
906:     lnk_max   - max value of lnk indicating the end of the list
907:     nlnk      - max length of the list
908:   Output Parameters:
909:     lnk       - list initialized
910:     bt        - PetscBT (bitarray) with all bits set to false
911:     lnk_empty - flg indicating the list is empty
912: */
913: #define PetscLLCreate(idx_start, lnk_max, nlnk, lnk, bt) ((PetscErrorCode)(PetscMalloc1(nlnk, &(lnk)) || PetscBTCreate(nlnk, &(bt)) || ((lnk)[idx_start] = lnk_max, PETSC_SUCCESS)))

915: #define PetscLLCreate_new(idx_start, lnk_max, nlnk, lnk, bt, lnk_empty) ((PetscErrorCode)(PetscMalloc1(nlnk, &(lnk)) || PetscBTCreate(nlnk, &(bt)) || (lnk_empty = PETSC_TRUE, 0) || ((lnk)[idx_start] = lnk_max, PETSC_SUCCESS)))

917: static inline PetscErrorCode PetscLLInsertLocation_Private(PetscBool assume_sorted, PetscInt k, PetscInt idx_start, PetscInt entry, PetscInt *PETSC_RESTRICT nlnk, PetscInt *PETSC_RESTRICT lnkdata, PetscInt *PETSC_RESTRICT lnk)
918: {
919:   PetscInt location;

921:   PetscFunctionBegin;
922:   /* start from the beginning if entry < previous entry */
923:   if (!assume_sorted && k && entry < *lnkdata) *lnkdata = idx_start;
924:   /* search for insertion location */
925:   do {
926:     location = *lnkdata;
927:     *lnkdata = lnk[location];
928:   } while (entry > *lnkdata);
929:   /* insertion location is found, add entry into lnk */
930:   lnk[location] = entry;
931:   lnk[entry]    = *lnkdata;
932:   ++(*nlnk);
933:   *lnkdata = entry; /* next search starts from here if next_entry > entry */
934:   PetscFunctionReturn(PETSC_SUCCESS);
935: }

937: static inline PetscErrorCode PetscLLAdd_Private(PetscInt nidx, const PetscInt *PETSC_RESTRICT indices, PetscInt idx_start, PetscInt *PETSC_RESTRICT nlnk, PetscInt *PETSC_RESTRICT lnk, PetscBT bt, PetscBool assume_sorted)
938: {
939:   PetscFunctionBegin;
940:   *nlnk = 0;
941:   for (PetscInt k = 0, lnkdata = idx_start; k < nidx; ++k) {
942:     const PetscInt entry = indices[k];

944:     if (!PetscBTLookupSet(bt, entry)) PetscCall(PetscLLInsertLocation_Private(assume_sorted, k, idx_start, entry, nlnk, &lnkdata, lnk));
945:   }
946:   PetscFunctionReturn(PETSC_SUCCESS);
947: }

949: /*
950:   Add an index set into a sorted linked list
951:   Input Parameters:
952:     nidx      - number of input indices
953:     indices   - integer array
954:     idx_start - starting index of the list
955:     lnk       - linked list(an integer array) that is created
956:     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
957:   output Parameters:
958:     nlnk      - number of newly added indices
959:     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from indices
960:     bt        - updated PetscBT (bitarray)
961: */
962: static inline PetscErrorCode PetscLLAdd(PetscInt nidx, const PetscInt *PETSC_RESTRICT indices, PetscInt idx_start, PetscInt *PETSC_RESTRICT nlnk, PetscInt *PETSC_RESTRICT lnk, PetscBT bt)
963: {
964:   PetscFunctionBegin;
965:   PetscCall(PetscLLAdd_Private(nidx, indices, idx_start, nlnk, lnk, bt, PETSC_FALSE));
966:   PetscFunctionReturn(PETSC_SUCCESS);
967: }

969: /*
970:   Add a SORTED ascending index set into a sorted linked list - same as PetscLLAdd() bus skip 'if (_k && _entry < _lnkdata) _lnkdata  = idx_start;'
971:   Input Parameters:
972:     nidx      - number of input indices
973:     indices   - sorted integer array
974:     idx_start - starting index of the list
975:     lnk       - linked list(an integer array) that is created
976:     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
977:   output Parameters:
978:     nlnk      - number of newly added indices
979:     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from indices
980:     bt        - updated PetscBT (bitarray)
981: */
982: static inline PetscErrorCode PetscLLAddSorted(PetscInt nidx, const PetscInt *PETSC_RESTRICT indices, PetscInt idx_start, PetscInt *PETSC_RESTRICT nlnk, PetscInt *PETSC_RESTRICT lnk, PetscBT bt)
983: {
984:   PetscFunctionBegin;
985:   PetscCall(PetscLLAdd_Private(nidx, indices, idx_start, nlnk, lnk, bt, PETSC_TRUE));
986:   PetscFunctionReturn(PETSC_SUCCESS);
987: }

989: /*
990:   Add a permuted index set into a sorted linked list
991:   Input Parameters:
992:     nidx      - number of input indices
993:     indices   - integer array
994:     perm      - permutation of indices
995:     idx_start - starting index of the list
996:     lnk       - linked list(an integer array) that is created
997:     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
998:   output Parameters:
999:     nlnk      - number of newly added indices
1000:     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from indices
1001:     bt        - updated PetscBT (bitarray)
1002: */
1003: static inline PetscErrorCode PetscLLAddPerm(PetscInt nidx, const PetscInt *PETSC_RESTRICT indices, const PetscInt *PETSC_RESTRICT perm, PetscInt idx_start, PetscInt *PETSC_RESTRICT nlnk, PetscInt *PETSC_RESTRICT lnk, PetscBT bt)
1004: {
1005:   PetscFunctionBegin;
1006:   *nlnk = 0;
1007:   for (PetscInt k = 0, lnkdata = idx_start; k < nidx; ++k) {
1008:     const PetscInt entry = perm[indices[k]];

1010:     if (!PetscBTLookupSet(bt, entry)) PetscCall(PetscLLInsertLocation_Private(PETSC_FALSE, k, idx_start, entry, nlnk, &lnkdata, lnk));
1011:   }
1012:   PetscFunctionReturn(PETSC_SUCCESS);
1013: }

1015: #if 0
1016: /* this appears to be unused? */
1017: static inline PetscErrorCode PetscLLAddSorted_new(PetscInt nidx, PetscInt *indices, PetscInt idx_start, PetscBool *lnk_empty, PetscInt *nlnk, PetscInt *lnk, PetscBT bt)
1018: {
1019:   PetscInt lnkdata = idx_start;

1021:   PetscFunctionBegin;
1022:   if (*lnk_empty) {
1023:     for (PetscInt k = 0; k < nidx; ++k) {
1024:       const PetscInt entry = indices[k], location = lnkdata;

1026:       PetscCall(PetscBTSet(bt,entry)); /* mark the new entry */
1027:       lnkdata       = lnk[location];
1028:       /* insertion location is found, add entry into lnk */
1029:       lnk[location] = entry;
1030:       lnk[entry]    = lnkdata;
1031:       lnkdata       = entry; /* next search starts from here */
1032:     }
1033:     /* lnk[indices[nidx-1]] = lnk[idx_start];
1034:        lnk[idx_start]       = indices[0];
1035:        PetscCall(PetscBTSet(bt,indices[0]));
1036:        for (_k=1; _k<nidx; _k++) {
1037:        PetscCall(PetscBTSet(bt,indices[_k]));
1038:        lnk[indices[_k-1]] = indices[_k];
1039:        }
1040:     */
1041:     *nlnk      = nidx;
1042:     *lnk_empty = PETSC_FALSE;
1043:   } else {
1044:     *nlnk = 0;
1045:     for (PetscInt k = 0; k < nidx; ++k) {
1046:       const PetscInt entry = indices[k];

1048:       if (!PetscBTLookupSet(bt,entry)) PetscCall(PetscLLInsertLocation_Private(PETSC_TRUE,k,idx_start,entry,nlnk,&lnkdata,lnk));
1049:     }
1050:   }
1051:   PetscFunctionReturn(PETSC_SUCCESS);
1052: }
1053: #endif

1055: /*
1056:   Add a SORTED index set into a sorted linked list used for LUFactorSymbolic()
1057:   Same as PetscLLAddSorted() with an additional operation:
1058:        count the number of input indices that are no larger than 'diag'
1059:   Input Parameters:
1060:     indices   - sorted integer array
1061:     idx_start - starting index of the list, index of pivot row
1062:     lnk       - linked list(an integer array) that is created
1063:     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
1064:     diag      - index of the active row in LUFactorSymbolic
1065:     nzbd      - number of input indices with indices <= idx_start
1066:     im        - im[idx_start] is initialized as num of nonzero entries in row=idx_start
1067:   output Parameters:
1068:     nlnk      - number of newly added indices
1069:     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from indices
1070:     bt        - updated PetscBT (bitarray)
1071:     im        - im[idx_start]: unchanged if diag is not an entry
1072:                              : num of entries with indices <= diag if diag is an entry
1073: */
1074: static inline PetscErrorCode PetscLLAddSortedLU(const PetscInt *PETSC_RESTRICT indices, PetscInt idx_start, PetscInt *PETSC_RESTRICT nlnk, PetscInt *PETSC_RESTRICT lnk, PetscBT bt, PetscInt diag, PetscInt nzbd, PetscInt *PETSC_RESTRICT im)
1075: {
1076:   const PetscInt nidx = im[idx_start] - nzbd; /* num of entries with idx_start < index <= diag */

1078:   PetscFunctionBegin;
1079:   *nlnk = 0;
1080:   for (PetscInt k = 0, lnkdata = idx_start; k < nidx; ++k) {
1081:     const PetscInt entry = indices[k];

1083:     ++nzbd;
1084:     if (entry == diag) im[idx_start] = nzbd;
1085:     if (!PetscBTLookupSet(bt, entry)) PetscCall(PetscLLInsertLocation_Private(PETSC_TRUE, k, idx_start, entry, nlnk, &lnkdata, lnk));
1086:   }
1087:   PetscFunctionReturn(PETSC_SUCCESS);
1088: }

1090: /*
1091:   Copy data on the list into an array, then initialize the list
1092:   Input Parameters:
1093:     idx_start - starting index of the list
1094:     lnk_max   - max value of lnk indicating the end of the list
1095:     nlnk      - number of data on the list to be copied
1096:     lnk       - linked list
1097:     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
1098:   output Parameters:
1099:     indices   - array that contains the copied data
1100:     lnk       - linked list that is cleaned and initialize
1101:     bt        - PetscBT (bitarray) with all bits set to false
1102: */
1103: static inline PetscErrorCode PetscLLClean(PetscInt idx_start, PetscInt lnk_max, PetscInt nlnk, PetscInt *PETSC_RESTRICT lnk, PetscInt *PETSC_RESTRICT indices, PetscBT bt)
1104: {
1105:   PetscFunctionBegin;
1106:   for (PetscInt j = 0, idx = idx_start; j < nlnk; ++j) {
1107:     idx        = lnk[idx];
1108:     indices[j] = idx;
1109:     PetscCall(PetscBTClear(bt, idx));
1110:   }
1111:   lnk[idx_start] = lnk_max;
1112:   PetscFunctionReturn(PETSC_SUCCESS);
1113: }

1115: /*
1116:   Free memories used by the list
1117: */
1118: #define PetscLLDestroy(lnk, bt) ((PetscErrorCode)(PetscFree(lnk) || PetscBTDestroy(&(bt))))

1120: /* Routines below are used for incomplete matrix factorization */
1121: /*
1122:   Create and initialize a linked list and its levels
1123:   Input Parameters:
1124:     idx_start - starting index of the list
1125:     lnk_max   - max value of lnk indicating the end of the list
1126:     nlnk      - max length of the list
1127:   Output Parameters:
1128:     lnk       - list initialized
1129:     lnk_lvl   - array of size nlnk for storing levels of lnk
1130:     bt        - PetscBT (bitarray) with all bits set to false
1131: */
1132: #define PetscIncompleteLLCreate(idx_start, lnk_max, nlnk, lnk, lnk_lvl, bt) \
1133:   ((PetscErrorCode)(PetscIntMultError(2, nlnk, NULL) || PetscMalloc1(2 * (nlnk), &(lnk)) || PetscBTCreate(nlnk, &(bt)) || ((lnk)[idx_start] = lnk_max, lnk_lvl = (lnk) + (nlnk), PETSC_SUCCESS)))

1135: static inline PetscErrorCode PetscIncompleteLLInsertLocation_Private(PetscBool assume_sorted, PetscInt k, PetscInt idx_start, PetscInt entry, PetscInt *PETSC_RESTRICT nlnk, PetscInt *PETSC_RESTRICT lnkdata, PetscInt *PETSC_RESTRICT lnk, PetscInt *PETSC_RESTRICT lnklvl, PetscInt newval)
1136: {
1137:   PetscFunctionBegin;
1138:   PetscCall(PetscLLInsertLocation_Private(assume_sorted, k, idx_start, entry, nlnk, lnkdata, lnk));
1139:   lnklvl[entry] = newval;
1140:   PetscFunctionReturn(PETSC_SUCCESS);
1141: }

1143: /*
1144:   Initialize a sorted linked list used for ILU and ICC
1145:   Input Parameters:
1146:     nidx      - number of input idx
1147:     idx       - integer array used for storing column indices
1148:     idx_start - starting index of the list
1149:     perm      - indices of an IS
1150:     lnk       - linked list(an integer array) that is created
1151:     lnklvl    - levels of lnk
1152:     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
1153:   output Parameters:
1154:     nlnk     - number of newly added idx
1155:     lnk      - the sorted(increasing order) linked list containing new and non-redundate entries from idx
1156:     lnklvl   - levels of lnk
1157:     bt       - updated PetscBT (bitarray)
1158: */
1159: static inline PetscErrorCode PetscIncompleteLLInit(PetscInt nidx, const PetscInt *PETSC_RESTRICT idx, PetscInt idx_start, const PetscInt *PETSC_RESTRICT perm, PetscInt *PETSC_RESTRICT nlnk, PetscInt *PETSC_RESTRICT lnk, PetscInt *PETSC_RESTRICT lnklvl, PetscBT bt)
1160: {
1161:   PetscFunctionBegin;
1162:   *nlnk = 0;
1163:   for (PetscInt k = 0, lnkdata = idx_start; k < nidx; ++k) {
1164:     const PetscInt entry = perm[idx[k]];

1166:     if (!PetscBTLookupSet(bt, entry)) PetscCall(PetscIncompleteLLInsertLocation_Private(PETSC_FALSE, k, idx_start, entry, nlnk, &lnkdata, lnk, lnklvl, 0));
1167:   }
1168:   PetscFunctionReturn(PETSC_SUCCESS);
1169: }

1171: static inline PetscErrorCode PetscIncompleteLLAdd_Private(PetscInt nidx, const PetscInt *PETSC_RESTRICT idx, PetscInt level, const PetscInt *PETSC_RESTRICT idxlvl, PetscInt idx_start, PetscInt *PETSC_RESTRICT nlnk, PetscInt *PETSC_RESTRICT lnk, PetscInt *PETSC_RESTRICT lnklvl, PetscBT bt, PetscInt prow_offset, PetscBool assume_sorted)
1172: {
1173:   PetscFunctionBegin;
1174:   *nlnk = 0;
1175:   for (PetscInt k = 0, lnkdata = idx_start; k < nidx; ++k) {
1176:     const PetscInt incrlev = idxlvl[k] + prow_offset + 1;

1178:     if (incrlev <= level) {
1179:       const PetscInt entry = idx[k];

1181:       if (!PetscBTLookupSet(bt, entry)) PetscCall(PetscIncompleteLLInsertLocation_Private(assume_sorted, k, idx_start, entry, nlnk, &lnkdata, lnk, lnklvl, incrlev));
1182:       else if (lnklvl[entry] > incrlev) lnklvl[entry] = incrlev; /* existing entry */
1183:     }
1184:   }
1185:   PetscFunctionReturn(PETSC_SUCCESS);
1186: }

1188: /*
1189:   Add a SORTED index set into a sorted linked list for ICC
1190:   Input Parameters:
1191:     nidx      - number of input indices
1192:     idx       - sorted integer array used for storing column indices
1193:     level     - level of fill, e.g., ICC(level)
1194:     idxlvl    - level of idx
1195:     idx_start - starting index of the list
1196:     lnk       - linked list(an integer array) that is created
1197:     lnklvl    - levels of lnk
1198:     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
1199:     idxlvl_prow - idxlvl[prow], where prow is the row number of the idx
1200:   output Parameters:
1201:     nlnk   - number of newly added indices
1202:     lnk    - the sorted(increasing order) linked list containing new and non-redundate entries from idx
1203:     lnklvl - levels of lnk
1204:     bt     - updated PetscBT (bitarray)
1205:   Note: the level of U(i,j) is set as lvl(i,j) = min{ lvl(i,j), lvl(prow,i)+lvl(prow,j)+1)
1206:         where idx = non-zero columns of U(prow,prow+1:n-1), prow<i
1207: */
1208: static inline PetscErrorCode PetscICCLLAddSorted(PetscInt nidx, const PetscInt *PETSC_RESTRICT idx, PetscInt level, const PetscInt *PETSC_RESTRICT idxlvl, PetscInt idx_start, PetscInt *PETSC_RESTRICT nlnk, PetscInt *PETSC_RESTRICT lnk, PetscInt *PETSC_RESTRICT lnklvl, PetscBT bt, PetscInt idxlvl_prow)
1209: {
1210:   PetscFunctionBegin;
1211:   PetscCall(PetscIncompleteLLAdd_Private(nidx, idx, level, idxlvl, idx_start, nlnk, lnk, lnklvl, bt, idxlvl_prow, PETSC_TRUE));
1212:   PetscFunctionReturn(PETSC_SUCCESS);
1213: }

1215: /*
1216:   Add a SORTED index set into a sorted linked list for ILU
1217:   Input Parameters:
1218:     nidx      - number of input indices
1219:     idx       - sorted integer array used for storing column indices
1220:     level     - level of fill, e.g., ICC(level)
1221:     idxlvl    - level of idx
1222:     idx_start - starting index of the list
1223:     lnk       - linked list(an integer array) that is created
1224:     lnklvl    - levels of lnk
1225:     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
1226:     prow      - the row number of idx
1227:   output Parameters:
1228:     nlnk     - number of newly added idx
1229:     lnk      - the sorted(increasing order) linked list containing new and non-redundate entries from idx
1230:     lnklvl   - levels of lnk
1231:     bt       - updated PetscBT (bitarray)

1233:   Note: the level of factor(i,j) is set as lvl(i,j) = min{ lvl(i,j), lvl(i,prow)+lvl(prow,j)+1)
1234:         where idx = non-zero columns of U(prow,prow+1:n-1), prow<i
1235: */
1236: static inline PetscErrorCode PetscILULLAddSorted(PetscInt nidx, const PetscInt *PETSC_RESTRICT idx, PetscInt level, const PetscInt *PETSC_RESTRICT idxlvl, PetscInt idx_start, PetscInt *PETSC_RESTRICT nlnk, PetscInt *PETSC_RESTRICT lnk, PetscInt *PETSC_RESTRICT lnklvl, PetscBT bt, PetscInt prow)
1237: {
1238:   PetscFunctionBegin;
1239:   PetscCall(PetscIncompleteLLAdd_Private(nidx, idx, level, idxlvl, idx_start, nlnk, lnk, lnklvl, bt, lnklvl[prow], PETSC_TRUE));
1240:   PetscFunctionReturn(PETSC_SUCCESS);
1241: }

1243: /*
1244:   Add a index set into a sorted linked list
1245:   Input Parameters:
1246:     nidx      - number of input idx
1247:     idx   - integer array used for storing column indices
1248:     level     - level of fill, e.g., ICC(level)
1249:     idxlvl - level of idx
1250:     idx_start - starting index of the list
1251:     lnk       - linked list(an integer array) that is created
1252:     lnklvl   - levels of lnk
1253:     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
1254:   output Parameters:
1255:     nlnk      - number of newly added idx
1256:     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from idx
1257:     lnklvl   - levels of lnk
1258:     bt        - updated PetscBT (bitarray)
1259: */
1260: static inline PetscErrorCode PetscIncompleteLLAdd(PetscInt nidx, const PetscInt *PETSC_RESTRICT idx, PetscInt level, const PetscInt *PETSC_RESTRICT idxlvl, PetscInt idx_start, PetscInt *PETSC_RESTRICT nlnk, PetscInt *PETSC_RESTRICT lnk, PetscInt *PETSC_RESTRICT lnklvl, PetscBT bt)
1261: {
1262:   PetscFunctionBegin;
1263:   PetscCall(PetscIncompleteLLAdd_Private(nidx, idx, level, idxlvl, idx_start, nlnk, lnk, lnklvl, bt, 0, PETSC_FALSE));
1264:   PetscFunctionReturn(PETSC_SUCCESS);
1265: }

1267: /*
1268:   Add a SORTED index set into a sorted linked list
1269:   Input Parameters:
1270:     nidx      - number of input indices
1271:     idx   - sorted integer array used for storing column indices
1272:     level     - level of fill, e.g., ICC(level)
1273:     idxlvl - level of idx
1274:     idx_start - starting index of the list
1275:     lnk       - linked list(an integer array) that is created
1276:     lnklvl    - levels of lnk
1277:     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
1278:   output Parameters:
1279:     nlnk      - number of newly added idx
1280:     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from idx
1281:     lnklvl    - levels of lnk
1282:     bt        - updated PetscBT (bitarray)
1283: */
1284: static inline PetscErrorCode PetscIncompleteLLAddSorted(PetscInt nidx, const PetscInt *PETSC_RESTRICT idx, PetscInt level, const PetscInt *PETSC_RESTRICT idxlvl, PetscInt idx_start, PetscInt *PETSC_RESTRICT nlnk, PetscInt *PETSC_RESTRICT lnk, PetscInt *PETSC_RESTRICT lnklvl, PetscBT bt)
1285: {
1286:   PetscFunctionBegin;
1287:   PetscCall(PetscIncompleteLLAdd_Private(nidx, idx, level, idxlvl, idx_start, nlnk, lnk, lnklvl, bt, 0, PETSC_TRUE));
1288:   PetscFunctionReturn(PETSC_SUCCESS);
1289: }

1291: /*
1292:   Copy data on the list into an array, then initialize the list
1293:   Input Parameters:
1294:     idx_start - starting index of the list
1295:     lnk_max   - max value of lnk indicating the end of the list
1296:     nlnk      - number of data on the list to be copied
1297:     lnk       - linked list
1298:     lnklvl    - level of lnk
1299:     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
1300:   output Parameters:
1301:     indices - array that contains the copied data
1302:     lnk     - linked list that is cleaned and initialize
1303:     lnklvl  - level of lnk that is reinitialized
1304:     bt      - PetscBT (bitarray) with all bits set to false
1305: */
1306: static inline PetscErrorCode PetscIncompleteLLClean(PetscInt idx_start, PetscInt lnk_max, PetscInt nlnk, PetscInt *PETSC_RESTRICT lnk, PetscInt *PETSC_RESTRICT lnklvl, PetscInt *PETSC_RESTRICT indices, PetscInt *PETSC_RESTRICT indiceslvl, PetscBT bt)
1307: {
1308:   PetscFunctionBegin;
1309:   for (PetscInt j = 0, idx = idx_start; j < nlnk; ++j) {
1310:     idx           = lnk[idx];
1311:     indices[j]    = idx;
1312:     indiceslvl[j] = lnklvl[idx];
1313:     lnklvl[idx]   = -1;
1314:     PetscCall(PetscBTClear(bt, idx));
1315:   }
1316:   lnk[idx_start] = lnk_max;
1317:   PetscFunctionReturn(PETSC_SUCCESS);
1318: }

1320: /*
1321:   Free memories used by the list
1322: */
1323: #define PetscIncompleteLLDestroy(lnk, bt) ((PetscErrorCode)(PetscFree(lnk) || PetscBTDestroy(&(bt))))

1325: #if !PetscDefined(CLANG_STATIC_ANALYZER)
1326:   #define MatCheckSameLocalSize(A, ar1, B, ar2) \
1327:     do { \
1328:       PetscCheckSameComm(A, ar1, B, ar2); \
1329:       PetscCheck(((A)->rmap->n == (B)->rmap->n) && ((A)->cmap->n == (B)->cmap->n), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Incompatible matrix local sizes: parameter # %d (%" PetscInt_FMT " x %" PetscInt_FMT ") != parameter # %d (%" PetscInt_FMT " x %" PetscInt_FMT ")", ar1, \
1330:                  (A)->rmap->n, (A)->cmap->n, ar2, (B)->rmap->n, (B)->cmap->n); \
1331:     } while (0)
1332:   #define MatCheckSameSize(A, ar1, B, ar2) \
1333:     do { \
1334:       PetscCheck(((A)->rmap->N == (B)->rmap->N) && ((A)->cmap->N == (B)->cmap->N), PetscObjectComm((PetscObject)(A)), PETSC_ERR_ARG_INCOMP, "Incompatible matrix global sizes: parameter # %d (%" PetscInt_FMT " x %" PetscInt_FMT ") != parameter # %d (%" PetscInt_FMT " x %" PetscInt_FMT ")", ar1, \
1335:                  (A)->rmap->N, (A)->cmap->N, ar2, (B)->rmap->N, (B)->cmap->N); \
1336:       MatCheckSameLocalSize(A, ar1, B, ar2); \
1337:     } while (0)
1338: #else
1339: template <typename Tm>
1340: extern void MatCheckSameLocalSize(Tm, int, Tm, int);
1341: template <typename Tm>
1342: extern void MatCheckSameSize(Tm, int, Tm, int);
1343: #endif

1345: #define VecCheckMatCompatible(M, x, ar1, b, ar2) \
1346:   do { \
1347:     PetscCheck((M)->cmap->N == (x)->map->N, PetscObjectComm((PetscObject)(M)), PETSC_ERR_ARG_SIZ, "Vector global length incompatible with matrix: parameter # %d global size %" PetscInt_FMT " != matrix column global size %" PetscInt_FMT, ar1, (x)->map->N, \
1348:                (M)->cmap->N); \
1349:     PetscCheck((M)->rmap->N == (b)->map->N, PetscObjectComm((PetscObject)(M)), PETSC_ERR_ARG_SIZ, "Vector global length incompatible with matrix: parameter # %d global size %" PetscInt_FMT " != matrix row global size %" PetscInt_FMT, ar2, (b)->map->N, \
1350:                (M)->rmap->N); \
1351:   } while (0)

1353: /*
1354:   Create and initialize a condensed linked list -
1355:     same as PetscLLCreate(), but uses a scalable array 'lnk' with size of max number of entries, not O(N).
1356:     Barry suggested this approach (Dec. 6, 2011):
1357:       I've thought of an alternative way of representing a linked list that is efficient but doesn't have the O(N) scaling issue
1358:       (it may be faster than the O(N) even sequentially due to less crazy memory access).

1360:       Instead of having some like  a  2  -> 4 -> 11 ->  22  list that uses slot 2  4 11 and 22 in a big array use a small array with two slots
1361:       for each entry for example  [ 2 1 | 4 3 | 22 -1 | 11 2]   so the first number (of the pair) is the value while the second tells you where
1362:       in the list the next entry is. Inserting a new link means just append another pair at the end. For example say we want to insert 13 into the
1363:       list it would then become [2 1 | 4 3 | 22 -1 | 11 4 | 13 2 ] you just add a pair at the end and fix the point for the one that points to it.
1364:       That is 11 use to point to the 2 slot, after the change 11 points to the 4th slot which has the value 13. Note that values are always next
1365:       to each other so memory access is much better than using the big array.

1367:   Example:
1368:      nlnk_max=5, lnk_max=36:
1369:      Initial list: [0, 0 | 36, 2 | 0, 0 | 0, 0 | 0, 0 | 0, 0 | 0, 0]
1370:      here, head_node has index 2 with value lnk[2]=lnk_max=36,
1371:            0-th entry is used to store the number of entries in the list,
1372:      The initial lnk represents head -> tail(marked by 36) with number of entries = lnk[0]=0.

1374:      Now adding a sorted set {2,4}, the list becomes
1375:      [2, 0 | 36, 4 |2, 6 | 4, 2 | 0, 0 | 0, 0 | 0, 0 ]
1376:      represents head -> 2 -> 4 -> tail with number of entries = lnk[0]=2.

1378:      Then adding a sorted set {0,3,35}, the list
1379:      [5, 0 | 36, 8 | 2, 10 | 4, 12 | 0, 4 | 3, 6 | 35, 2 ]
1380:      represents head -> 0 -> 2 -> 3 -> 4 -> 35 -> tail with number of entries = lnk[0]=5.

1382:   Input Parameters:
1383:     nlnk_max  - max length of the list
1384:     lnk_max   - max value of the entries
1385:   Output Parameters:
1386:     lnk       - list created and initialized
1387:     bt        - PetscBT (bitarray) with all bits set to false. Note: bt has size lnk_max, not nln_max!
1388: */
1389: static inline PetscErrorCode PetscLLCondensedCreate(PetscInt nlnk_max, PetscInt lnk_max, PetscInt **lnk, PetscBT *bt)
1390: {
1391:   PetscInt *llnk, lsize = 0;

1393:   PetscFunctionBegin;
1394:   PetscCall(PetscIntMultError(2, nlnk_max + 2, &lsize));
1395:   PetscCall(PetscMalloc1(lsize, lnk));
1396:   PetscCall(PetscBTCreate(lnk_max, bt));
1397:   llnk    = *lnk;
1398:   llnk[0] = 0;       /* number of entries on the list */
1399:   llnk[2] = lnk_max; /* value in the head node */
1400:   llnk[3] = 2;       /* next for the head node */
1401:   PetscFunctionReturn(PETSC_SUCCESS);
1402: }

1404: /*
1405:   Add a SORTED ascending index set into a sorted linked list. See PetscLLCondensedCreate() for detailed description.
1406:   Input Parameters:
1407:     nidx      - number of input indices
1408:     indices   - sorted integer array
1409:     lnk       - condensed linked list(an integer array) that is created
1410:     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
1411:   output Parameters:
1412:     lnk       - the sorted(increasing order) linked list containing previous and newly added non-redundate indices
1413:     bt        - updated PetscBT (bitarray)
1414: */
1415: static inline PetscErrorCode PetscLLCondensedAddSorted(PetscInt nidx, const PetscInt indices[], PetscInt lnk[], PetscBT bt)
1416: {
1417:   PetscInt location = 2;      /* head */
1418:   PetscInt nlnk     = lnk[0]; /* num of entries on the input lnk */

1420:   PetscFunctionBegin;
1421:   for (PetscInt k = 0; k < nidx; k++) {
1422:     const PetscInt entry = indices[k];
1423:     if (!PetscBTLookupSet(bt, entry)) { /* new entry */
1424:       PetscInt next, lnkdata;

1426:       /* search for insertion location */
1427:       do {
1428:         next     = location + 1;  /* link from previous node to next node */
1429:         location = lnk[next];     /* idx of next node */
1430:         lnkdata  = lnk[location]; /* value of next node */
1431:       } while (entry > lnkdata);
1432:       /* insertion location is found, add entry into lnk */
1433:       const PetscInt newnode = 2 * (nlnk + 2); /* index for this new node */
1434:       lnk[next]              = newnode;        /* connect previous node to the new node */
1435:       lnk[newnode]           = entry;          /* set value of the new node */
1436:       lnk[newnode + 1]       = location;       /* connect new node to next node */
1437:       location               = newnode;        /* next search starts from the new node */
1438:       nlnk++;
1439:     }
1440:   }
1441:   lnk[0] = nlnk; /* number of entries in the list */
1442:   PetscFunctionReturn(PETSC_SUCCESS);
1443: }

1445: static inline PetscErrorCode PetscLLCondensedClean(PetscInt lnk_max, PETSC_UNUSED PetscInt nidx, PetscInt *indices, PetscInt lnk[], PetscBT bt)
1446: {
1447:   const PetscInt nlnk = lnk[0]; /* num of entries on the list */
1448:   PetscInt       next = lnk[3]; /* head node */

1450:   PetscFunctionBegin;
1451:   for (PetscInt k = 0; k < nlnk; k++) {
1452:     indices[k] = lnk[next];
1453:     next       = lnk[next + 1];
1454:     PetscCall(PetscBTClear(bt, indices[k]));
1455:   }
1456:   lnk[0] = 0;       /* num of entries on the list */
1457:   lnk[2] = lnk_max; /* initialize head node */
1458:   lnk[3] = 2;       /* head node */
1459:   PetscFunctionReturn(PETSC_SUCCESS);
1460: }

1462: static inline PetscErrorCode PetscLLCondensedView(PetscInt *lnk)
1463: {
1464:   PetscFunctionBegin;
1465:   PetscCall(PetscPrintf(PETSC_COMM_SELF, "LLCondensed of size %" PetscInt_FMT ", (val,  next)\n", lnk[0]));
1466:   for (PetscInt k = 2; k < lnk[0] + 2; ++k) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT ": (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", 2 * k, lnk[2 * k], lnk[2 * k + 1]));
1467:   PetscFunctionReturn(PETSC_SUCCESS);
1468: }

1470: /*
1471:   Free memories used by the list
1472: */
1473: static inline PetscErrorCode PetscLLCondensedDestroy(PetscInt *lnk, PetscBT bt)
1474: {
1475:   PetscFunctionBegin;
1476:   PetscCall(PetscFree(lnk));
1477:   PetscCall(PetscBTDestroy(&bt));
1478:   PetscFunctionReturn(PETSC_SUCCESS);
1479: }

1481: /*
1482:  Same as PetscLLCondensedCreate(), but does not use non-scalable O(lnk_max) bitarray
1483:   Input Parameters:
1484:     nlnk_max  - max length of the list
1485:   Output Parameters:
1486:     lnk       - list created and initialized
1487: */
1488: static inline PetscErrorCode PetscLLCondensedCreate_Scalable(PetscInt nlnk_max, PetscInt **lnk)
1489: {
1490:   PetscInt *llnk, lsize = 0;

1492:   PetscFunctionBegin;
1493:   PetscCall(PetscIntMultError(2, nlnk_max + 2, &lsize));
1494:   PetscCall(PetscMalloc1(lsize, lnk));
1495:   llnk    = *lnk;
1496:   llnk[0] = 0;             /* number of entries on the list */
1497:   llnk[2] = PETSC_INT_MAX; /* value in the head node */
1498:   llnk[3] = 2;             /* next for the head node */
1499:   PetscFunctionReturn(PETSC_SUCCESS);
1500: }

1502: static inline PetscErrorCode PetscLLCondensedExpand_Scalable(PetscInt nlnk_max, PetscInt **lnk)
1503: {
1504:   PetscInt lsize = 0;

1506:   PetscFunctionBegin;
1507:   PetscCall(PetscIntMultError(2, nlnk_max + 2, &lsize));
1508:   PetscCall(PetscRealloc((size_t)lsize * sizeof(PetscInt), lnk));
1509:   PetscFunctionReturn(PETSC_SUCCESS);
1510: }

1512: static inline PetscErrorCode PetscLLCondensedAddSorted_Scalable(PetscInt nidx, const PetscInt indices[], PetscInt lnk[])
1513: {
1514:   PetscInt location = 2;      /* head */
1515:   PetscInt nlnk     = lnk[0]; /* num of entries on the input lnk */

1517:   for (PetscInt k = 0; k < nidx; k++) {
1518:     const PetscInt entry = indices[k];
1519:     PetscInt       next, lnkdata;

1521:     /* search for insertion location */
1522:     do {
1523:       next     = location + 1;  /* link from previous node to next node */
1524:       location = lnk[next];     /* idx of next node */
1525:       lnkdata  = lnk[location]; /* value of next node */
1526:     } while (entry > lnkdata);
1527:     if (entry < lnkdata) {
1528:       /* insertion location is found, add entry into lnk */
1529:       const PetscInt newnode = 2 * (nlnk + 2); /* index for this new node */
1530:       lnk[next]              = newnode;        /* connect previous node to the new node */
1531:       lnk[newnode]           = entry;          /* set value of the new node */
1532:       lnk[newnode + 1]       = location;       /* connect new node to next node */
1533:       location               = newnode;        /* next search starts from the new node */
1534:       nlnk++;
1535:     }
1536:   }
1537:   lnk[0] = nlnk; /* number of entries in the list */
1538:   return PETSC_SUCCESS;
1539: }

1541: static inline PetscErrorCode PetscLLCondensedClean_Scalable(PETSC_UNUSED PetscInt nidx, PetscInt *indices, PetscInt *lnk)
1542: {
1543:   const PetscInt nlnk = lnk[0];
1544:   PetscInt       next = lnk[3]; /* head node */

1546:   for (PetscInt k = 0; k < nlnk; k++) {
1547:     indices[k] = lnk[next];
1548:     next       = lnk[next + 1];
1549:   }
1550:   lnk[0] = 0; /* num of entries on the list */
1551:   lnk[3] = 2; /* head node */
1552:   return PETSC_SUCCESS;
1553: }

1555: static inline PetscErrorCode PetscLLCondensedDestroy_Scalable(PetscInt *lnk)
1556: {
1557:   return PetscFree(lnk);
1558: }

1560: /*
1561:       lnk[0]   number of links
1562:       lnk[1]   number of entries
1563:       lnk[3n]  value
1564:       lnk[3n+1] len
1565:       lnk[3n+2] link to next value

1567:       The next three are always the first link

1569:       lnk[3]    PETSC_INT_MIN+1
1570:       lnk[4]    1
1571:       lnk[5]    link to first real entry

1573:       The next three are always the last link

1575:       lnk[6]    PETSC_INT_MAX - 1
1576:       lnk[7]    1
1577:       lnk[8]    next valid link (this is the same as lnk[0] but without the decreases)
1578: */

1580: static inline PetscErrorCode PetscLLCondensedCreate_fast(PetscInt nlnk_max, PetscInt **lnk)
1581: {
1582:   PetscInt *llnk;
1583:   PetscInt  lsize = 0;

1585:   PetscFunctionBegin;
1586:   PetscCall(PetscIntMultError(3, nlnk_max + 3, &lsize));
1587:   PetscCall(PetscMalloc1(lsize, lnk));
1588:   llnk    = *lnk;
1589:   llnk[0] = 0;                 /* nlnk: number of entries on the list */
1590:   llnk[1] = 0;                 /* number of integer entries represented in list */
1591:   llnk[3] = PETSC_INT_MIN + 1; /* value in the first node */
1592:   llnk[4] = 1;                 /* count for the first node */
1593:   llnk[5] = 6;                 /* next for the first node */
1594:   llnk[6] = PETSC_INT_MAX - 1; /* value in the last node */
1595:   llnk[7] = 1;                 /* count for the last node */
1596:   llnk[8] = 0;                 /* next valid node to be used */
1597:   PetscFunctionReturn(PETSC_SUCCESS);
1598: }

1600: static inline PetscErrorCode PetscLLCondensedAddSorted_fast(PetscInt nidx, const PetscInt indices[], PetscInt lnk[])
1601: {
1602:   for (PetscInt k = 0, prev = 3 /* first value */; k < nidx; k++) {
1603:     const PetscInt entry = indices[k];
1604:     PetscInt       next  = lnk[prev + 2];

1606:     /* search for insertion location */
1607:     while (entry >= lnk[next]) {
1608:       prev = next;
1609:       next = lnk[next + 2];
1610:     }
1611:     /* entry is in range of previous list */
1612:     if (entry < lnk[prev] + lnk[prev + 1]) continue;
1613:     lnk[1]++;
1614:     /* entry is right after previous list */
1615:     if (entry == lnk[prev] + lnk[prev + 1]) {
1616:       lnk[prev + 1]++;
1617:       if (lnk[next] == entry + 1) { /* combine two contiguous strings */
1618:         lnk[prev + 1] += lnk[next + 1];
1619:         lnk[prev + 2] = lnk[next + 2];
1620:         lnk[0]--;
1621:       }
1622:       continue;
1623:     }
1624:     /* entry is right before next list */
1625:     if (entry == lnk[next] - 1) {
1626:       lnk[next]--;
1627:       lnk[next + 1]++;
1628:       prev = next;
1629:       continue;
1630:     }
1631:     /*  add entry into lnk */
1632:     lnk[prev + 2] = 3 * ((lnk[8]++) + 3); /* connect previous node to the new node */
1633:     prev          = lnk[prev + 2];
1634:     lnk[prev]     = entry; /* set value of the new node */
1635:     lnk[prev + 1] = 1;     /* number of values in contiguous string is one to start */
1636:     lnk[prev + 2] = next;  /* connect new node to next node */
1637:     lnk[0]++;
1638:   }
1639:   return PETSC_SUCCESS;
1640: }

1642: static inline PetscErrorCode PetscLLCondensedClean_fast(PETSC_UNUSED PetscInt nidx, PetscInt *indices, PetscInt *lnk)
1643: {
1644:   const PetscInt nlnk = lnk[0];
1645:   PetscInt       next = lnk[5]; /* first node */

1647:   for (PetscInt k = 0, cnt = 0; k < nlnk; k++) {
1648:     for (PetscInt j = 0; j < lnk[next + 1]; j++) indices[cnt++] = lnk[next] + j;
1649:     next = lnk[next + 2];
1650:   }
1651:   lnk[0] = 0;                 /* nlnk: number of links */
1652:   lnk[1] = 0;                 /* number of integer entries represented in list */
1653:   lnk[3] = PETSC_INT_MIN + 1; /* value in the first node */
1654:   lnk[4] = 1;                 /* count for the first node */
1655:   lnk[5] = 6;                 /* next for the first node */
1656:   lnk[6] = PETSC_INT_MAX - 1; /* value in the last node */
1657:   lnk[7] = 1;                 /* count for the last node */
1658:   lnk[8] = 0;                 /* next valid location to make link */
1659:   return PETSC_SUCCESS;
1660: }

1662: static inline PetscErrorCode PetscLLCondensedView_fast(const PetscInt *lnk)
1663: {
1664:   const PetscInt nlnk = lnk[0];
1665:   PetscInt       next = lnk[5]; /* first node */

1667:   for (PetscInt k = 0; k < nlnk; k++) {
1668: #if 0 /* Debugging code */
1669:     printf("%d value %d len %d next %d\n", next, lnk[next], lnk[next + 1], lnk[next + 2]);
1670: #endif
1671:     next = lnk[next + 2];
1672:   }
1673:   return PETSC_SUCCESS;
1674: }

1676: static inline PetscErrorCode PetscLLCondensedDestroy_fast(PetscInt *lnk)
1677: {
1678:   return PetscFree(lnk);
1679: }

1681: PETSC_EXTERN PetscErrorCode PetscCDCreate(PetscInt, PetscCoarsenData **);
1682: PETSC_EXTERN PetscErrorCode PetscCDDestroy(PetscCoarsenData *);
1683: PETSC_EXTERN PetscErrorCode PetscCDIntNdSetID(PetscCDIntNd *, PetscInt);
1684: PETSC_EXTERN PetscErrorCode PetscCDIntNdGetID(const PetscCDIntNd *, PetscInt *);
1685: PETSC_EXTERN PetscErrorCode PetscCDAppendID(PetscCoarsenData *, PetscInt, PetscInt);
1686: PETSC_EXTERN PetscErrorCode PetscCDMoveAppend(PetscCoarsenData *, PetscInt, PetscInt);
1687: PETSC_EXTERN PetscErrorCode PetscCDAppendNode(PetscCoarsenData *, PetscInt, PetscCDIntNd *);
1688: PETSC_EXTERN PetscErrorCode PetscCDRemoveNextNode(PetscCoarsenData *, PetscInt, PetscCDIntNd *);
1689: PETSC_EXTERN PetscErrorCode PetscCDCountAt(const PetscCoarsenData *, PetscInt, PetscInt *);
1690: PETSC_EXTERN PetscErrorCode PetscCDIsEmptyAt(const PetscCoarsenData *, PetscInt, PetscBool *);
1691: PETSC_EXTERN PetscErrorCode PetscCDSetChunkSize(PetscCoarsenData *, PetscInt);
1692: PETSC_EXTERN PetscErrorCode PetscCDPrint(const PetscCoarsenData *, PetscInt, MPI_Comm);
1693: PETSC_EXTERN PetscErrorCode PetscCDGetNonemptyIS(PetscCoarsenData *, IS *);
1694: PETSC_EXTERN PetscErrorCode PetscCDGetMat(PetscCoarsenData *, Mat *);
1695: PETSC_EXTERN PetscErrorCode PetscCDSetMat(PetscCoarsenData *, Mat);
1696: PETSC_EXTERN PetscErrorCode PetscCDClearMat(PetscCoarsenData *);
1697: PETSC_EXTERN PetscErrorCode PetscCDRemoveAllAt(PetscCoarsenData *, PetscInt);
1698: PETSC_EXTERN PetscErrorCode PetscCDCount(const PetscCoarsenData *, PetscInt *_sz);

1700: PETSC_EXTERN PetscErrorCode PetscCDGetHeadPos(const PetscCoarsenData *, PetscInt, PetscCDIntNd **);
1701: PETSC_EXTERN PetscErrorCode PetscCDGetNextPos(const PetscCoarsenData *, PetscInt, PetscCDIntNd **);
1702: PETSC_EXTERN PetscErrorCode PetscCDGetASMBlocks(const PetscCoarsenData *, const PetscInt, PetscInt *, IS **);

1704: PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL PetscErrorCode MatFDColoringApply_AIJ(Mat, MatFDColoring, Vec, void *);

1706: typedef struct {
1707:   Vec              diag;
1708:   PetscBool        diag_valid;
1709:   Vec              inv_diag;
1710:   PetscBool        inv_diag_valid;
1711:   PetscObjectState diag_state, inv_diag_state;
1712:   PetscInt        *col;
1713:   PetscScalar     *val;
1714: } Mat_Diagonal;

1716: #if PetscDefined(HAVE_CUDA)
1717: PETSC_INTERN PetscErrorCode MatADot_Diagonal_SeqCUDA(Mat, Vec, Vec, PetscScalar *);
1718: PETSC_INTERN PetscErrorCode MatANormSq_Diagonal_SeqCUDA(Mat, Vec, PetscReal *);
1719: #endif
1720: #if PetscDefined(HAVE_HIP)
1721: PETSC_INTERN PetscErrorCode MatADot_Diagonal_SeqHIP(Mat, Vec, Vec, PetscScalar *);
1722: PETSC_INTERN PetscErrorCode MatANormSq_Diagonal_SeqHIP(Mat, Vec, PetscReal *);
1723: #endif
1724: #if PetscDefined(HAVE_KOKKOS_KERNELS)
1725: PETSC_INTERN PetscErrorCode MatADot_Diagonal_SeqKokkos(Mat, Vec, Vec, PetscScalar *);
1726: PETSC_INTERN PetscErrorCode MatANormSq_Diagonal_SeqKokkos(Mat, Vec, PetscReal *);
1727: #endif

1729: PETSC_EXTERN PetscLogEvent MAT_Mult;
1730: PETSC_EXTERN PetscLogEvent MAT_MultAdd;
1731: PETSC_EXTERN PetscLogEvent MAT_MultTranspose;
1732: PETSC_EXTERN PetscLogEvent MAT_MultHermitianTranspose;
1733: PETSC_EXTERN PetscLogEvent MAT_MultTransposeAdd;
1734: PETSC_EXTERN PetscLogEvent MAT_MultHermitianTransposeAdd;
1735: PETSC_EXTERN PetscLogEvent MAT_ADot;
1736: PETSC_EXTERN PetscLogEvent MAT_ANorm;
1737: PETSC_EXTERN PetscLogEvent MAT_Solve;
1738: PETSC_EXTERN PetscLogEvent MAT_Solves;
1739: PETSC_EXTERN PetscLogEvent MAT_SolveAdd;
1740: PETSC_EXTERN PetscLogEvent MAT_SolveTranspose;
1741: PETSC_EXTERN PetscLogEvent MAT_SolveTransposeAdd;
1742: PETSC_EXTERN PetscLogEvent MAT_SOR;
1743: PETSC_EXTERN PetscLogEvent MAT_ForwardSolve;
1744: PETSC_EXTERN PetscLogEvent MAT_BackwardSolve;
1745: PETSC_EXTERN PetscLogEvent MAT_LUFactor;
1746: PETSC_EXTERN PetscLogEvent MAT_LUFactorSymbolic;
1747: PETSC_EXTERN PetscLogEvent MAT_LUFactorNumeric;
1748: PETSC_EXTERN PetscLogEvent MAT_QRFactor;
1749: PETSC_EXTERN PetscLogEvent MAT_QRFactorSymbolic;
1750: PETSC_EXTERN PetscLogEvent MAT_QRFactorNumeric;
1751: PETSC_EXTERN PetscLogEvent MAT_CholeskyFactor;
1752: PETSC_EXTERN PetscLogEvent MAT_CholeskyFactorSymbolic;
1753: PETSC_EXTERN PetscLogEvent MAT_CholeskyFactorNumeric;
1754: PETSC_EXTERN PetscLogEvent MAT_ILUFactor;
1755: PETSC_EXTERN PetscLogEvent MAT_ILUFactorSymbolic;
1756: PETSC_EXTERN PetscLogEvent MAT_ICCFactorSymbolic;
1757: PETSC_EXTERN PetscLogEvent MAT_Copy;
1758: PETSC_EXTERN PetscLogEvent MAT_Convert;
1759: PETSC_EXTERN PetscLogEvent MAT_Scale;
1760: PETSC_EXTERN PetscLogEvent MAT_AssemblyBegin;
1761: PETSC_EXTERN PetscLogEvent MAT_AssemblyEnd;
1762: PETSC_EXTERN PetscLogEvent MAT_SetValues;
1763: PETSC_EXTERN PetscLogEvent MAT_GetValues;
1764: PETSC_EXTERN PetscLogEvent MAT_GetRow;
1765: PETSC_EXTERN PetscLogEvent MAT_GetRowIJ;
1766: PETSC_EXTERN PetscLogEvent MAT_CreateSubMats;
1767: PETSC_EXTERN PetscLogEvent MAT_GetOrdering;
1768: PETSC_EXTERN PetscLogEvent MAT_RedundantMat;
1769: PETSC_EXTERN PetscLogEvent MAT_IncreaseOverlap;
1770: PETSC_EXTERN PetscLogEvent MAT_Partitioning;
1771: PETSC_EXTERN PetscLogEvent MAT_PartitioningND;
1772: PETSC_EXTERN PetscLogEvent MAT_Coarsen;
1773: PETSC_EXTERN PetscLogEvent MAT_ZeroEntries;
1774: PETSC_EXTERN PetscLogEvent MAT_Load;
1775: PETSC_EXTERN PetscLogEvent MAT_View;
1776: PETSC_EXTERN PetscLogEvent MAT_AXPY;
1777: PETSC_EXTERN PetscLogEvent MAT_FDColoringCreate;
1778: PETSC_EXTERN PetscLogEvent MAT_TransposeColoringCreate;
1779: PETSC_EXTERN PetscLogEvent MAT_FDColoringSetUp;
1780: PETSC_EXTERN PetscLogEvent MAT_FDColoringApply;
1781: PETSC_EXTERN PetscLogEvent MAT_Transpose;
1782: PETSC_EXTERN PetscLogEvent MAT_FDColoringFunction;
1783: PETSC_EXTERN PetscLogEvent MAT_CreateSubMat;
1784: PETSC_EXTERN PetscLogEvent MAT_MatSolve;
1785: PETSC_EXTERN PetscLogEvent MAT_MatTrSolve;
1786: PETSC_EXTERN PetscLogEvent MAT_MatMultSymbolic;
1787: PETSC_EXTERN PetscLogEvent MAT_MatMultNumeric;
1788: PETSC_EXTERN PetscLogEvent MAT_Getlocalmatcondensed;
1789: PETSC_EXTERN PetscLogEvent MAT_GetBrowsOfAcols;
1790: PETSC_EXTERN PetscLogEvent MAT_GetBrowsOfAocols;
1791: PETSC_EXTERN PetscLogEvent MAT_PtAPSymbolic;
1792: PETSC_EXTERN PetscLogEvent MAT_PtAPNumeric;
1793: PETSC_EXTERN PetscLogEvent MAT_Seqstompinum;
1794: PETSC_EXTERN PetscLogEvent MAT_Seqstompisym;
1795: PETSC_EXTERN PetscLogEvent MAT_Seqstompi;
1796: PETSC_EXTERN PetscLogEvent MAT_Getlocalmat;
1797: PETSC_EXTERN PetscLogEvent MAT_RARtSymbolic;
1798: PETSC_EXTERN PetscLogEvent MAT_RARtNumeric;
1799: PETSC_EXTERN PetscLogEvent MAT_MatTransposeMultSymbolic;
1800: PETSC_EXTERN PetscLogEvent MAT_MatTransposeMultNumeric;
1801: PETSC_EXTERN PetscLogEvent MAT_TransposeMatMultSymbolic;
1802: PETSC_EXTERN PetscLogEvent MAT_TransposeMatMultNumeric;
1803: PETSC_EXTERN PetscLogEvent MAT_MatMatMultSymbolic;
1804: PETSC_EXTERN PetscLogEvent MAT_MatMatMultNumeric;
1805: PETSC_EXTERN PetscLogEvent MAT_Getsymtransreduced;
1806: PETSC_EXTERN PetscLogEvent MAT_GetSeqNonzeroStructure;
1807: PETSC_EXTERN PetscLogEvent MATMFFD_Mult;
1808: PETSC_EXTERN PetscLogEvent MAT_GetMultiProcBlock;
1809: PETSC_EXTERN PetscLogEvent MAT_CUSPARSECopyToGPU;
1810: PETSC_EXTERN PetscLogEvent MAT_CUSPARSECopyFromGPU;
1811: PETSC_EXTERN PetscLogEvent MAT_CUSPARSEGenerateTranspose;
1812: PETSC_EXTERN PetscLogEvent MAT_CUSPARSESolveAnalysis;
1813: PETSC_EXTERN PetscLogEvent MAT_HIPSPARSECopyToGPU;
1814: PETSC_EXTERN PetscLogEvent MAT_HIPSPARSECopyFromGPU;
1815: PETSC_EXTERN PetscLogEvent MAT_HIPSPARSEGenerateTranspose;
1816: PETSC_EXTERN PetscLogEvent MAT_HIPSPARSESolveAnalysis;
1817: PETSC_EXTERN PetscLogEvent MAT_SetValuesBatch;
1818: PETSC_EXTERN PetscLogEvent MAT_CreateGraph;
1819: PETSC_EXTERN PetscLogEvent MAT_ViennaCLCopyToGPU;
1820: PETSC_EXTERN PetscLogEvent MAT_DenseCopyToGPU;
1821: PETSC_EXTERN PetscLogEvent MAT_DenseCopyFromGPU;
1822: PETSC_EXTERN PetscLogEvent MAT_Merge;
1823: PETSC_EXTERN PetscLogEvent MAT_Residual;
1824: PETSC_EXTERN PetscLogEvent MAT_SetRandom;
1825: PETSC_EXTERN PetscLogEvent MAT_FactorFactS;
1826: PETSC_EXTERN PetscLogEvent MAT_FactorInvS;
1827: PETSC_EXTERN PetscLogEvent MAT_PreallCOO;
1828: PETSC_EXTERN PetscLogEvent MAT_SetVCOO;
1829: PETSC_EXTERN PetscLogEvent MATCOLORING_Apply;
1830: PETSC_EXTERN PetscLogEvent MATCOLORING_Comm;
1831: PETSC_EXTERN PetscLogEvent MATCOLORING_Local;
1832: PETSC_EXTERN PetscLogEvent MATCOLORING_ISCreate;
1833: PETSC_EXTERN PetscLogEvent MATCOLORING_SetUp;
1834: PETSC_EXTERN PetscLogEvent MATCOLORING_Weights;
1835: PETSC_EXTERN PetscLogEvent MAT_H2Opus_Build;
1836: PETSC_EXTERN PetscLogEvent MAT_H2Opus_Compress;
1837: PETSC_EXTERN PetscLogEvent MAT_H2Opus_Orthog;
1838: PETSC_EXTERN PetscLogEvent MAT_H2Opus_LR;
1839: PETSC_EXTERN PetscLogEvent MAT_CUDACopyToGPU;
1840: PETSC_EXTERN PetscLogEvent MAT_HIPCopyToGPU;

1842: #if PetscDefined(CLANG_STATIC_ANALYZER)
1843:   #define MatGetDiagonalMarkers(SeqXXX, bs)
1844: #else
1845:   /*
1846:    Adds diagonal pointers to sparse matrix nonzero structure and determines if all diagonal entries are present

1848:    Rechecks the matrix data structure automatically if the nonzero structure of the matrix changed since the last call

1850:    Potential optimization: since the a->j[j] are sorted this could use bisection to find the diagonal

1852:    Developer Note:
1853:    Uses the C preprocessor as a template mechanism to produce MatGetDiagonal_Seq[SB]AIJ() to avoid duplicate code
1854: */
1855:   #define MatGetDiagonalMarkers(SeqXXX, bs) \
1856:     PetscErrorCode MatGetDiagonalMarkers_##SeqXXX(Mat A, const PetscInt *diag[], PetscBool *diagDense) \
1857:     { \
1858:       Mat_##SeqXXX *a = (Mat_##SeqXXX *)A->data; \
1859: \
1860:       PetscFunctionBegin; \
1861:       if (A->factortype != MAT_FACTOR_NONE) { \
1862:         if (diagDense) *diagDense = PETSC_TRUE; \
1863:         if (diag) *diag = a->diag; \
1864:         PetscFunctionReturn(PETSC_SUCCESS); \
1865:       } \
1866:       PetscCheck(diag != NULL || diagDense != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "At least one of diag or diagDense must be requested"); \
1867:       if (a->diagNonzeroState != A->nonzerostate || (diag != NULL && a->diag == NULL)) { \
1868:         const PetscInt m = A->rmap->n / (bs); \
1869: \
1870:         if (diag == NULL && a->diag == NULL) { \
1871:           a->diagDense = PETSC_TRUE; \
1872:           for (PetscInt i = 0; i < m; i++) { \
1873:             PetscBool found = PETSC_FALSE; \
1874: \
1875:             for (PetscInt j = a->i[i]; j < a->i[i + 1]; j++) { \
1876:               if (a->j[j] == i) { \
1877:                 found = PETSC_TRUE; \
1878:                 break; \
1879:               } \
1880:             } \
1881:             if (!found) { \
1882:               a->diagDense        = PETSC_FALSE; \
1883:               *diagDense          = a->diagDense; \
1884:               a->diagNonzeroState = A->nonzerostate; \
1885:               PetscFunctionReturn(PETSC_SUCCESS); \
1886:             } \
1887:           } \
1888:         } else { \
1889:           if (a->diag == NULL) PetscCall(PetscMalloc1(m, &a->diag)); \
1890:           a->diagDense = PETSC_TRUE; \
1891:           for (PetscInt i = 0; i < m; i++) { \
1892:             PetscBool found = PETSC_FALSE; \
1893: \
1894:             a->diag[i] = a->i[i + 1]; \
1895:             for (PetscInt j = a->i[i]; j < a->i[i + 1]; j++) { \
1896:               if (a->j[j] == i) { \
1897:                 a->diag[i] = j; \
1898:                 found      = PETSC_TRUE; \
1899:                 break; \
1900:               } \
1901:             } \
1902:             if (!found) a->diagDense = PETSC_FALSE; \
1903:           } \
1904:         } \
1905:         a->diagNonzeroState = A->nonzerostate; \
1906:       } \
1907:       if (diag) *diag = a->diag; \
1908:       if (diagDense) *diagDense = a->diagDense; \
1909:       PetscFunctionReturn(PETSC_SUCCESS); \
1910:     }
1911: #endif