xref: /petsc/include/petscsys.h (revision 62903a643c6f3b806cfd2df6dfd11354dcefb6c2)
1 /*
2     Provides access to system related and general utility routines.
3 */
4 #if !defined(__PETSCSYS_H)
5 #define __PETSCSYS_H
6 #include "petsc.h"
7 PETSC_EXTERN_CXX_BEGIN
8 
9 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetArchType(char[],size_t);
10 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetHostName(char[],size_t);
11 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetUserName(char[],size_t);
12 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetProgramName(char[],size_t);
13 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSetProgramName(const char[]);
14 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetDate(char[],size_t);
15 
16 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSortInt(PetscInt,PetscInt[]);
17 EXTERN PetscErrorCode PETSC_DLLEXPORT  PetscSortIntWithPermutation(PetscInt,const PetscInt[],PetscInt[]);
18 EXTERN PetscErrorCode PETSC_DLLEXPORT  PetscSortStrWithPermutation(PetscInt,const char*[],PetscInt[]);
19 EXTERN PetscErrorCode PETSC_DLLEXPORT  PetscSortIntWithArray(PetscInt,PetscInt[],PetscInt[]);
20 EXTERN PetscErrorCode PETSC_DLLEXPORT  PetscSortIntWithScalarArray(PetscInt,PetscInt[],PetscScalar[]);
21 EXTERN PetscErrorCode PETSC_DLLEXPORT  PetscSortReal(PetscInt,PetscReal[]);
22 EXTERN PetscErrorCode PETSC_DLLEXPORT  PetscSortRealWithPermutation(PetscInt,const PetscReal[],PetscInt[]);
23 
24 EXTERN PetscErrorCode PETSC_DLLEXPORT  PetscSetDisplay(void);
25 EXTERN PetscErrorCode PETSC_DLLEXPORT  PetscGetDisplay(char[],size_t);
26 
27 extern PetscCookie PETSC_DLLEXPORT PETSC_RANDOM_COOKIE;
28 
29 typedef enum { RANDOM_DEFAULT,RANDOM_DEFAULT_REAL,
30                RANDOM_DEFAULT_IMAGINARY } PetscRandomType;
31 
32 /*S
33      PetscRandom - Abstract PETSc object that manages generating random numbers
34 
35    Level: intermediate
36 
37   Concepts: random numbers
38 
39 .seealso:  PetscRandomCreate(), PetscRandomGetValue()
40 S*/
41 typedef struct _p_PetscRandom*   PetscRandom;
42 
43 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomCreate(MPI_Comm,PetscRandomType,PetscRandom*);
44 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomGetValue(PetscRandom,PetscScalar*);
45 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomGetInterval(PetscRandom,PetscScalar*,PetscScalar*);
46 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomSetInterval(PetscRandom,PetscScalar,PetscScalar);
47 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomSetSeed(PetscRandom,unsigned long);
48 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomGetSeed(PetscRandom,unsigned long *);
49 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomSeed(PetscRandom);
50 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomDestroy(PetscRandom);
51 
52 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetFullPath(const char[],char[],size_t);
53 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetRelativePath(const char[],char[],size_t);
54 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetWorkingDirectory(char[],size_t);
55 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetRealPath(char[],char[]);
56 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetHomeDirectory(char[],size_t);
57 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscTestFile(const char[],char,PetscTruth*);
58 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscTestDirectory(const char[],char,PetscTruth*);
59 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscBinaryRead(int,void*,PetscInt,PetscDataType);
60 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedBinaryRead(MPI_Comm,int,void*,PetscInt,PetscDataType);
61 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedBinaryWrite(MPI_Comm,int,void*,PetscInt,PetscDataType,PetscTruth);
62 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscBinaryWrite(int,void*,PetscInt,PetscDataType,PetscTruth);
63 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscBinaryOpen(const char[],int,int *);
64 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscBinaryClose(int);
65 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSharedTmp(MPI_Comm,PetscTruth *);
66 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSharedWorkingDirectory(MPI_Comm,PetscTruth *);
67 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetTmp(MPI_Comm,char *,size_t);
68 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscFileRetrieve(MPI_Comm,const char *,char *,size_t,PetscTruth*);
69 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscLs(MPI_Comm,const char[],char*,size_t,PetscTruth*);
70 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryCCAAppend(MPI_Comm,PetscDLLibraryList*,const char[]);
71 
72 /*
73    In binary files variables are stored using the following lengths,
74   regardless of how they are stored in memory on any one particular
75   machine. Use these rather then sizeof() in computing sizes for
76   PetscBinarySeek().
77 */
78 #define PETSC_BINARY_INT_SIZE    (32/8)
79 #define PETSC_BINARY_FLOAT_SIZE  (32/8)
80 #define PETSC_BINARY_CHAR_SIZE    (8/8)
81 #define PETSC_BINARY_SHORT_SIZE  (16/8)
82 #define PETSC_BINARY_DOUBLE_SIZE (64/8)
83 #define PETSC_BINARY_SCALAR_SIZE sizeof(PetscScalar)
84 
85 /*E
86   PetscBinarySeekType - argument to PetscBinarySeek()
87 
88   Level: advanced
89 
90 .seealso: PetscBinarySeek(), PetscSynchronizedBinarySeek()
91 E*/
92 typedef enum {PETSC_BINARY_SEEK_SET = 0,PETSC_BINARY_SEEK_CUR = 1,PETSC_BINARY_SEEK_END = 2} PetscBinarySeekType;
93 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscBinarySeek(int,off_t,PetscBinarySeekType,off_t*);
94 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedBinarySeek(MPI_Comm,int,off_t,PetscBinarySeekType,off_t*);
95 
96 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSetDebugger(const char[],PetscTruth);
97 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSetDefaultDebugger(void);
98 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSetDebuggerFromString(char*);
99 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscAttachDebugger(void);
100 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscStopForDebugger(void);
101 
102 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGatherNumberOfMessages(MPI_Comm,PetscMPIInt*,PetscMPIInt*,PetscMPIInt*);
103 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGatherMessageLengths(MPI_Comm,PetscMPIInt,PetscMPIInt,PetscMPIInt*,PetscMPIInt**,PetscMPIInt**);
104 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGatherMessageLengths2(MPI_Comm,PetscMPIInt,PetscMPIInt,PetscMPIInt*,PetscMPIInt*,PetscMPIInt**,PetscMPIInt**,PetscMPIInt**);
105 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscPostIrecvInt(MPI_Comm,PetscMPIInt,PetscMPIInt,PetscMPIInt*,PetscMPIInt*,PetscInt***,MPI_Request**);
106 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscPostIrecvScalar(MPI_Comm,PetscMPIInt,PetscMPIInt,PetscMPIInt*,PetscMPIInt*,PetscScalar***,MPI_Request**);
107 
108 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSSEIsEnabled(MPI_Comm,PetscTruth *,PetscTruth *);
109 
110 /* Parallel communication routines */
111 /*E
112   InsertMode - Whether entries are inserted or added into vectors or matrices
113 
114   Level: beginner
115 
116 .seealso: VecSetValues(), MatSetValues(), VecSetValue(), VecSetValuesBlocked(),
117           VecSetValuesLocal(), VecSetValuesBlockedLocal(), MatSetValuesBlocked(),
118           MatSetValuesBlockedLocal(), MatSetValuesLocal(), VecScatterBegin(), VecScatterEnd()
119 E*/
120 typedef enum {NOT_SET_VALUES, INSERT_VALUES, ADD_VALUES, MAX_VALUES} InsertMode;
121 
122 /*MC
123     INSERT_VALUES - Put a value into a vector or matrix, overwrites any previous value
124 
125     Level: beginner
126 
127 .seealso: InsertMode, VecSetValues(), MatSetValues(), VecSetValue(), VecSetValuesBlocked(),
128           VecSetValuesLocal(), VecSetValuesBlockedLocal(), MatSetValuesBlocked(), ADD_VALUES, INSERT_VALUES,
129           MatSetValuesBlockedLocal(), MatSetValuesLocal(), VecScatterBegin(), VecScatterEnd()
130 
131 M*/
132 
133 /*MC
134     ADD_VALUES - Adds a value into a vector or matrix, if there previously was no value, just puts the
135                 value into that location
136 
137     Level: beginner
138 
139 .seealso: InsertMode, VecSetValues(), MatSetValues(), VecSetValue(), VecSetValuesBlocked(),
140           VecSetValuesLocal(), VecSetValuesBlockedLocal(), MatSetValuesBlocked(), ADD_VALUES, INSERT_VALUES,
141           MatSetValuesBlockedLocal(), MatSetValuesLocal(), VecScatterBegin(), VecScatterEnd()
142 
143 M*/
144 
145 /*MC
146     MAX_VALUES - Puts the maximum of the scattered/gathered value and the current value into each location
147 
148     Level: beginner
149 
150 .seealso: InsertMode, VecScatterBegin(), VecScatterEnd(), ADD_VALUES, INSERT_VALUES
151 
152 M*/
153 
154 /*E
155   ScatterMode - Determines the direction of a scatter
156 
157   Level: beginner
158 
159 .seealso: VecScatter, VecScatterBegin(), VecScatterEnd()
160 E*/
161 typedef enum {SCATTER_FORWARD=0, SCATTER_REVERSE=1, SCATTER_FORWARD_LOCAL=2, SCATTER_REVERSE_LOCAL=3, SCATTER_LOCAL=2} ScatterMode;
162 
163 /*MC
164     SCATTER_FORWARD - Scatters the values as dictated by the VecScatterCreate() call
165 
166     Level: beginner
167 
168 .seealso: VecScatter, ScatterMode, VecScatterCreate(), VecScatterBegin(), VecScatterEnd(), SCATTER_REVERSE, SCATTER_FORWARD_LOCAL,
169           SCATTER_REVERSE_LOCAL
170 
171 M*/
172 
173 /*MC
174     SCATTER_REVERSE - Moves the values in the opposite direction then the directions indicated in
175          in the VecScatterCreate()
176 
177     Level: beginner
178 
179 .seealso: VecScatter, ScatterMode, VecScatterCreate(), VecScatterBegin(), VecScatterEnd(), SCATTER_FORWARD, SCATTER_FORWARD_LOCAL,
180           SCATTER_REVERSE_LOCAL
181 
182 M*/
183 
184 /*MC
185     SCATTER_FORWARD_LOCAL - Scatters the values as dictated by the VecScatterCreate() call except NO parallel communication
186        is done. Any variables that have be moved between processes are ignored
187 
188     Level: developer
189 
190 .seealso: VecScatter, ScatterMode, VecScatterCreate(), VecScatterBegin(), VecScatterEnd(), SCATTER_REVERSE, SCATTER_FORWARD,
191           SCATTER_REVERSE_LOCAL
192 
193 M*/
194 
195 /*MC
196     SCATTER_REVERSE_LOCAL - Moves the values in the opposite direction then the directions indicated in
197          in the VecScatterCreate()  except NO parallel communication
198        is done. Any variables that have be moved between processes are ignored
199 
200     Level: developer
201 
202 .seealso: VecScatter, ScatterMode, VecScatterCreate(), VecScatterBegin(), VecScatterEnd(), SCATTER_FORWARD, SCATTER_FORWARD_LOCAL,
203           SCATTER_REVERSE
204 
205 M*/
206 
207 /*
208   Create and initialize a linked list
209   Input Parameters:
210     idx_start - starting index of the list
211     lnk_max   - max value of lnk indicating the end of the list
212     nlnk      - max length of the list
213   Output Parameters:
214     lnk       - list initialized
215     bt        - PetscBT (bitarray) with all bits set to false
216 */
217 #define PetscLLCreate(idx_start,lnk_max,nlnk,lnk,bt) \
218   (PetscMalloc(nlnk*sizeof(PetscInt),&lnk) || PetscBTCreate(nlnk,bt) || PetscBTMemzero(nlnk,bt) || (lnk[idx_start] = lnk_max,0))
219 
220 /*
221   Add a index set into a sorted linked list
222   Input Parameters:
223     nidx      - number of input indices
224     indices   - interger array
225     idx_start - starting index of the list
226     lnk       - linked list(an integer array) that is created
227     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
228   output Parameters:
229     nlnk      - number of newly added indices
230     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from indices
231     bt        - updated PetscBT (bitarray)
232 */
233 #define PetscLLAdd(nidx,indices,idx_start,nlnk,lnk,bt) 0;\
234 {\
235   PetscInt _k,_entry,_location,_lnkdata;\
236   nlnk     = 0;\
237   _lnkdata = idx_start;\
238   for (_k=0; _k<nidx; _k++){\
239     _entry = indices[_k];\
240     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
241       /* search for insertion location */\
242       /* start from the beginning if _entry < previous _entry */\
243       if (_k && _entry < _lnkdata) _lnkdata  = idx_start;\
244       do {\
245         _location = _lnkdata;\
246         _lnkdata  = lnk[_location];\
247       } while (_entry > _lnkdata);\
248       /* insertion location is found, add entry into lnk */\
249       lnk[_location] = _entry;\
250       lnk[_entry]    = _lnkdata;\
251       nlnk++;\
252       _lnkdata = _entry; /* next search starts from here if next_entry > _entry */\
253     }\
254   }\
255 }
256 
257 /*
258   Add a SORTED index set into a sorted linked list
259   Input Parameters:
260     nidx      - number of input indices
261     indices   - sorted interger array
262     idx_start - starting index of the list
263     lnk       - linked list(an integer array) that is created
264     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
265   output Parameters:
266     nlnk      - number of newly added indices
267     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from indices
268     bt        - updated PetscBT (bitarray)
269 */
270 #define PetscLLAddSorted(nidx,indices,idx_start,nlnk,lnk,bt) 0;\
271 {\
272   PetscInt _k,_entry,_location,_lnkdata;\
273   nlnk      = 0;\
274   _lnkdata  = idx_start;\
275   for (_k=0; _k<nidx; _k++){\
276     _entry = indices[_k];\
277     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
278       /* search for insertion location */\
279       do {\
280         _location = _lnkdata;\
281         _lnkdata  = lnk[_location];\
282       } while (_entry > _lnkdata);\
283       /* insertion location is found, add entry into lnk */\
284       lnk[_location] = _entry;\
285       lnk[_entry]    = _lnkdata;\
286       nlnk++;\
287       _lnkdata = _entry; /* next search starts from here */\
288     }\
289   }\
290 }
291 
292 /*
293   Add a SORTED index set into a sorted linked list used for LUFactorSymbolic()
294   Same as PetscLLAddSorted() with an additional operation:
295        count the number of input indices that are no larger than 'diag'
296   Input Parameters:
297     nidx      - number of input indices
298     indices   - sorted interger array
299     idx_start - starting index of the list
300     lnk       - linked list(an integer array) that is created
301     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
302     diag      - index of the active row in LUFactorSymbolic
303   output Parameters:
304     nlnk      - number of newly added indices
305     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from indices
306     bt        - updated PetscBT (bitarray)
307     nzbd      - number of input indices that are no larger than 'diag'
308 */
309 #define PetscLLAddSortedLU(nidx,indices,idx_start,nlnk,lnk,bt,diag,nzbd) 0;\
310 {\
311   PetscInt _k,_entry,_location,_lnkdata;\
312   nlnk     = 0;\
313   _lnkdata = idx_start;\
314   nzbd     = 0;\
315   for (_k=0; _k<nidx; _k++){\
316     _entry = indices[_k];\
317     if (_entry <= diag) nzbd++;\
318     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
319       /* search for insertion location */\
320       do {\
321         _location = _lnkdata;\
322         _lnkdata  = lnk[_location];\
323       } while (_entry > _lnkdata);\
324       /* insertion location is found, add entry into lnk */\
325       lnk[_location] = _entry;\
326       lnk[_entry]    = _lnkdata;\
327       nlnk++;\
328       _lnkdata = _entry; /* next search starts from here */\
329     }\
330   }\
331 }
332 
333 /*
334   Copy data on the list into an array, then initialize the list
335   Input Parameters:
336     idx_start - starting index of the list
337     lnk_max   - max value of lnk indicating the end of the list
338     nlnk      - number of data on the list to be copied
339     lnk       - linked list
340     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
341   output Parameters:
342     indices   - array that contains the copied data
343     lnk       - linked list that is cleaned and initialize
344     bt        - PetscBT (bitarray) with all bits set to false
345 */
346 #define PetscLLClean(idx_start,lnk_max,nlnk,lnk,indices,bt) 0;\
347 {\
348   PetscInt _j,_idx=idx_start;\
349   for (_j=0; _j<nlnk; _j++){\
350     _idx = lnk[_idx];\
351     *(indices+_j) = _idx;\
352     ierr = PetscBTClear(bt,_idx);CHKERRQ(ierr);\
353   }\
354   lnk[idx_start] = lnk_max;\
355 }
356 /*
357   Free memories used by the list
358 */
359 #define PetscLLDestroy(lnk,bt) (PetscFree(lnk) || PetscBTDestroy(bt))
360 
361 /* Routines below are used for incomplete matrix factorization */
362 /*
363   Create and initialize a linked list and its levels
364   Input Parameters:
365     idx_start - starting index of the list
366     lnk_max   - max value of lnk indicating the end of the list
367     nlnk      - max length of the list
368   Output Parameters:
369     lnk       - list initialized
370     lnk_lvl   - array of size nlnk for storing levels of lnk
371     bt        - PetscBT (bitarray) with all bits set to false
372 */
373 #define PetscIncompleteLLCreate(idx_start,lnk_max,nlnk,lnk,lnk_lvl,bt)\
374   (PetscMalloc(2*nlnk*sizeof(PetscInt),&lnk) || PetscBTCreate(nlnk,bt) || PetscBTMemzero(nlnk,bt) || (lnk[idx_start] = lnk_max,lnk_lvl = lnk + nlnk,0))
375 
376 /*
377   Initialize a sorted linked list used for ILU and ICC
378   Input Parameters:
379     nidx      - number of input idx
380     idx       - interger array used for storing column indices
381     idx_start - starting index of the list
382     perm      - indices of an IS
383     lnk       - linked list(an integer array) that is created
384     lnklvl    - levels of lnk
385     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
386   output Parameters:
387     nlnk     - number of newly added idx
388     lnk      - the sorted(increasing order) linked list containing new and non-redundate entries from idx
389     lnklvl   - levels of lnk
390     bt       - updated PetscBT (bitarray)
391 */
392 #define PetscIncompleteLLInit(nidx,idx,idx_start,perm,nlnk,lnk,lnklvl,bt) 0;\
393 {\
394   PetscInt _k,_entry,_location,_lnkdata;\
395   nlnk     = 0;\
396   _lnkdata = idx_start;\
397   for (_k=0; _k<nidx; _k++){\
398     _entry = perm[idx[_k]];\
399     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
400       /* search for insertion location */\
401       if (_k && _entry < _lnkdata) _lnkdata  = idx_start;\
402       do {\
403         _location = _lnkdata;\
404         _lnkdata  = lnk[_location];\
405       } while (_entry > _lnkdata);\
406       /* insertion location is found, add entry into lnk */\
407       lnk[_location]  = _entry;\
408       lnk[_entry]     = _lnkdata;\
409       lnklvl[_entry] = 0;\
410       nlnk++;\
411       _lnkdata = _entry; /* next search starts from here if next_entry > _entry */\
412     }\
413   }\
414 }
415 
416 /*
417   Add a SORTED index set into a sorted linked list for ILU
418   Input Parameters:
419     nidx      - number of input indices
420     idx       - sorted interger array used for storing column indices
421     level     - level of fill, e.g., ICC(level)
422     idxlvl    - level of idx
423     idx_start - starting index of the list
424     lnk       - linked list(an integer array) that is created
425     lnklvl    - levels of lnk
426     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
427     prow      - the row number of idx
428   output Parameters:
429     nlnk     - number of newly added idx
430     lnk      - the sorted(increasing order) linked list containing new and non-redundate entries from idx
431     lnklvl   - levels of lnk
432     bt       - updated PetscBT (bitarray)
433 
434   Note: the level of factor(i,j) is set as lvl(i,j) = min{ lvl(i,j), lvl(i,prow)+lvl(prow,j)+1)
435         where idx = non-zero columns of U(prow,prow+1:n-1), prow<i
436 */
437 #define PetscILULLAddSorted(nidx,idx,level,idxlvl,idx_start,nlnk,lnk,lnklvl,bt,lnklvl_prow) 0;\
438 {\
439   PetscInt _k,_entry,_location,_lnkdata,_incrlev,_lnklvl_prow=lnklvl[prow];\
440   nlnk     = 0;\
441   _lnkdata = idx_start;\
442   for (_k=0; _k<nidx; _k++){\
443     _incrlev = idxlvl[_k] + _lnklvl_prow + 1;\
444     if (_incrlev > level) continue;\
445     _entry = idx[_k];\
446     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
447       /* search for insertion location */\
448       do {\
449         _location = _lnkdata;\
450         _lnkdata  = lnk[_location];\
451       } while (_entry > _lnkdata);\
452       /* insertion location is found, add entry into lnk */\
453       lnk[_location]  = _entry;\
454       lnk[_entry]     = _lnkdata;\
455       lnklvl[_entry] = _incrlev;\
456       nlnk++;\
457       _lnkdata = _entry; /* next search starts from here if next_entry > _entry */\
458     } else { /* existing entry: update lnklvl */\
459       if (lnklvl[_entry] > _incrlev) lnklvl[_entry] = _incrlev;\
460     }\
461   }\
462 }
463 
464 /*
465   Add a index set into a sorted linked list
466   Input Parameters:
467     nidx      - number of input idx
468     idx   - interger array used for storing column indices
469     level     - level of fill, e.g., ICC(level)
470     idxlvl - level of idx
471     idx_start - starting index of the list
472     lnk       - linked list(an integer array) that is created
473     lnklvl   - levels of lnk
474     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
475   output Parameters:
476     nlnk      - number of newly added idx
477     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from idx
478     lnklvl   - levels of lnk
479     bt        - updated PetscBT (bitarray)
480 */
481 #define PetscIncompleteLLAdd(nidx,idx,level,idxlvl,idx_start,nlnk,lnk,lnklvl,bt) 0;\
482 {\
483   PetscInt _k,_entry,_location,_lnkdata,_incrlev;\
484   nlnk     = 0;\
485   _lnkdata = idx_start;\
486   for (_k=0; _k<nidx; _k++){\
487     _incrlev = idxlvl[_k] + 1;\
488     if (_incrlev > level) continue;\
489     _entry = idx[_k];\
490     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
491       /* search for insertion location */\
492       if (_k && _entry < _lnkdata) _lnkdata  = idx_start;\
493       do {\
494         _location = _lnkdata;\
495         _lnkdata  = lnk[_location];\
496       } while (_entry > _lnkdata);\
497       /* insertion location is found, add entry into lnk */\
498       lnk[_location]  = _entry;\
499       lnk[_entry]     = _lnkdata;\
500       lnklvl[_entry] = _incrlev;\
501       nlnk++;\
502       _lnkdata = _entry; /* next search starts from here if next_entry > _entry */\
503     } else { /* existing entry: update lnklvl */\
504       if (lnklvl[_entry] > _incrlev) lnklvl[_entry] = _incrlev;\
505     }\
506   }\
507 }
508 
509 /*
510   Add a SORTED index set into a sorted linked list
511   Input Parameters:
512     nidx      - number of input indices
513     idx   - sorted interger array used for storing column indices
514     level     - level of fill, e.g., ICC(level)
515     idxlvl - level of idx
516     idx_start - starting index of the list
517     lnk       - linked list(an integer array) that is created
518     lnklvl    - levels of lnk
519     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
520   output Parameters:
521     nlnk      - number of newly added idx
522     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from idx
523     lnklvl    - levels of lnk
524     bt        - updated PetscBT (bitarray)
525 */
526 #define PetscIncompleteLLAddSorted(nidx,idx,level,idxlvl,idx_start,nlnk,lnk,lnklvl,bt) 0;\
527 {\
528   PetscInt _k,_entry,_location,_lnkdata,_incrlev;\
529   nlnk = 0;\
530   _lnkdata = idx_start;\
531   for (_k=0; _k<nidx; _k++){\
532     _incrlev = idxlvl[_k] + 1;\
533     if (_incrlev > level) continue;\
534     _entry = idx[_k];\
535     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
536       /* search for insertion location */\
537       do {\
538         _location = _lnkdata;\
539         _lnkdata  = lnk[_location];\
540       } while (_entry > _lnkdata);\
541       /* insertion location is found, add entry into lnk */\
542       lnk[_location] = _entry;\
543       lnk[_entry]    = _lnkdata;\
544       lnklvl[_entry] = _incrlev;\
545       nlnk++;\
546       _lnkdata = _entry; /* next search starts from here */\
547     } else { /* existing entry: update lnklvl */\
548       if (lnklvl[_entry] > _incrlev) lnklvl[_entry] = _incrlev;\
549     }\
550   }\
551 }
552 
553 /*
554   Add a SORTED index set into a sorted linked list for ICC
555   Input Parameters:
556     nidx      - number of input indices
557     idx       - sorted interger array used for storing column indices
558     level     - level of fill, e.g., ICC(level)
559     idxlvl    - level of idx
560     idx_start - starting index of the list
561     lnk       - linked list(an integer array) that is created
562     lnklvl    - levels of lnk
563     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
564     idxlvl_prow - idxlvl[prow], where prow is the row number of the idx
565   output Parameters:
566     nlnk   - number of newly added indices
567     lnk    - the sorted(increasing order) linked list containing new and non-redundate entries from idx
568     lnklvl - levels of lnk
569     bt     - updated PetscBT (bitarray)
570   Note: the level of U(i,j) is set as lvl(i,j) = min{ lvl(i,j), lvl(prow,i)+lvl(prow,j)+1)
571         where idx = non-zero columns of U(prow,prow+1:n-1), prow<i
572 */
573 #define PetscICCLLAddSorted(nidx,idx,level,idxlvl,idx_start,nlnk,lnk,lnklvl,bt,idxlvl_prow) 0;\
574 {\
575   PetscInt _k,_entry,_location,_lnkdata,_incrlev;\
576   nlnk = 0;\
577   _lnkdata = idx_start;\
578   for (_k=0; _k<nidx; _k++){\
579     _incrlev = idxlvl[_k] + idxlvl_prow + 1;\
580     if (_incrlev > level) continue;\
581     _entry = idx[_k];\
582     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
583       /* search for insertion location */\
584       do {\
585         _location = _lnkdata;\
586         _lnkdata  = lnk[_location];\
587       } while (_entry > _lnkdata);\
588       /* insertion location is found, add entry into lnk */\
589       lnk[_location] = _entry;\
590       lnk[_entry]    = _lnkdata;\
591       lnklvl[_entry] = _incrlev;\
592       nlnk++;\
593       _lnkdata = _entry; /* next search starts from here */\
594     } else { /* existing entry: update lnklvl */\
595       if (lnklvl[_entry] > _incrlev) lnklvl[_entry] = _incrlev;\
596     }\
597   }\
598 }
599 
600 /*
601   Copy data on the list into an array, then initialize the list
602   Input Parameters:
603     idx_start - starting index of the list
604     lnk_max   - max value of lnk indicating the end of the list
605     nlnk      - number of data on the list to be copied
606     lnk       - linked list
607     lnklvl    - level of lnk
608     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
609   output Parameters:
610     indices - array that contains the copied data
611     lnk     - linked list that is cleaned and initialize
612     lnklvl  - level of lnk that is reinitialized
613     bt      - PetscBT (bitarray) with all bits set to false
614 */
615 #define PetscIncompleteLLClean(idx_start,lnk_max,nlnk,lnk,lnklvl,indices,indiceslvl,bt) 0;\
616 {\
617   PetscInt _j,_idx=idx_start;\
618   for (_j=0; _j<nlnk; _j++){\
619     _idx = lnk[_idx];\
620     *(indices+_j) = _idx;\
621     *(indiceslvl+_j) = lnklvl[_idx];\
622     lnklvl[_idx] = -1;\
623     ierr = PetscBTClear(bt,_idx);CHKERRQ(ierr);\
624   }\
625   lnk[idx_start] = lnk_max;\
626 }
627 /*
628   Free memories used by the list
629 */
630 #define PetscIncompleteLLDestroy(lnk,bt) \
631   (PetscFree(lnk) || PetscBTDestroy(bt) || (0))
632 
633 PETSC_EXTERN_CXX_END
634 #endif /* __PETSCSYS_H */
635