xref: /petsc/include/petscsys.h (revision d8ccf1fba21e982ff19766be89df46ec8f3bd34a)
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,RANDOM_DEFAULT_IMAGINARY} PetscRandomType;
30 
31 /*S
32      PetscRandom - Abstract PETSc object that manages generating random numbers
33 
34    Level: intermediate
35 
36   Concepts: random numbers
37 
38 .seealso:  PetscRandomCreate(), PetscRandomGetValue()
39 S*/
40 typedef struct _p_PetscRandom*   PetscRandom;
41 
42 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomCreate(MPI_Comm,PetscRandomType,PetscRandom*);
43 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomGetValue(PetscRandom,PetscScalar*);
44 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomGetInterval(PetscRandom,PetscScalar*,PetscScalar*);
45 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomSetInterval(PetscRandom,PetscScalar,PetscScalar);
46 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomSetSeed(PetscRandom,unsigned long);
47 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomGetSeed(PetscRandom,unsigned long *);
48 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomSeed(PetscRandom);
49 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscRandomDestroy(PetscRandom);
50 
51 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetFullPath(const char[],char[],size_t);
52 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetRelativePath(const char[],char[],size_t);
53 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetWorkingDirectory(char[],size_t);
54 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetRealPath(char[],char[]);
55 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGetHomeDirectory(char[],size_t);
56 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscTestFile(const char[],char,PetscTruth*);
57 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscTestDirectory(const char[],char,PetscTruth*);
58 
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[],PetscFileMode,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 
71 /*
72    In binary files variables are stored using the following lengths,
73   regardless of how they are stored in memory on any one particular
74   machine. Use these rather then sizeof() in computing sizes for
75   PetscBinarySeek().
76 */
77 #define PETSC_BINARY_INT_SIZE    (32/8)
78 #define PETSC_BINARY_FLOAT_SIZE  (32/8)
79 #define PETSC_BINARY_CHAR_SIZE    (8/8)
80 #define PETSC_BINARY_SHORT_SIZE  (16/8)
81 #define PETSC_BINARY_DOUBLE_SIZE (64/8)
82 #define PETSC_BINARY_SCALAR_SIZE sizeof(PetscScalar)
83 
84 /*E
85   PetscBinarySeekType - argument to PetscBinarySeek()
86 
87   Level: advanced
88 
89 .seealso: PetscBinarySeek(), PetscSynchronizedBinarySeek()
90 E*/
91 typedef enum {PETSC_BINARY_SEEK_SET = 0,PETSC_BINARY_SEEK_CUR = 1,PETSC_BINARY_SEEK_END = 2} PetscBinarySeekType;
92 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscBinarySeek(int,off_t,PetscBinarySeekType,off_t*);
93 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedBinarySeek(MPI_Comm,int,off_t,PetscBinarySeekType,off_t*);
94 
95 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSetDebugger(const char[],PetscTruth);
96 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSetDefaultDebugger(void);
97 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSetDebuggerFromString(char*);
98 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscAttachDebugger(void);
99 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscStopForDebugger(void);
100 
101 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGatherNumberOfMessages(MPI_Comm,PetscMPIInt*,PetscMPIInt*,PetscMPIInt*);
102 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGatherMessageLengths(MPI_Comm,PetscMPIInt,PetscMPIInt,PetscMPIInt*,PetscMPIInt**,PetscMPIInt**);
103 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscGatherMessageLengths2(MPI_Comm,PetscMPIInt,PetscMPIInt,PetscMPIInt*,PetscMPIInt*,PetscMPIInt**,PetscMPIInt**,PetscMPIInt**);
104 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscPostIrecvInt(MPI_Comm,PetscMPIInt,PetscMPIInt,PetscMPIInt*,PetscMPIInt*,PetscInt***,MPI_Request**);
105 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscPostIrecvScalar(MPI_Comm,PetscMPIInt,PetscMPIInt,PetscMPIInt*,PetscMPIInt*,PetscScalar***,MPI_Request**);
106 
107 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscSSEIsEnabled(MPI_Comm,PetscTruth *,PetscTruth *);
108 
109 /* Parallel communication routines */
110 /*E
111   InsertMode - Whether entries are inserted or added into vectors or matrices
112 
113   Level: beginner
114 
115 .seealso: VecSetValues(), MatSetValues(), VecSetValue(), VecSetValuesBlocked(),
116           VecSetValuesLocal(), VecSetValuesBlockedLocal(), MatSetValuesBlocked(),
117           MatSetValuesBlockedLocal(), MatSetValuesLocal(), VecScatterBegin(), VecScatterEnd()
118 E*/
119 typedef enum {NOT_SET_VALUES, INSERT_VALUES, ADD_VALUES, MAX_VALUES} InsertMode;
120 
121 /*MC
122     INSERT_VALUES - Put a value into a vector or matrix, overwrites any previous value
123 
124     Level: beginner
125 
126 .seealso: InsertMode, VecSetValues(), MatSetValues(), VecSetValue(), VecSetValuesBlocked(),
127           VecSetValuesLocal(), VecSetValuesBlockedLocal(), MatSetValuesBlocked(), ADD_VALUES, INSERT_VALUES,
128           MatSetValuesBlockedLocal(), MatSetValuesLocal(), VecScatterBegin(), VecScatterEnd()
129 
130 M*/
131 
132 /*MC
133     ADD_VALUES - Adds a value into a vector or matrix, if there previously was no value, just puts the
134                 value into that location
135 
136     Level: beginner
137 
138 .seealso: InsertMode, VecSetValues(), MatSetValues(), VecSetValue(), VecSetValuesBlocked(),
139           VecSetValuesLocal(), VecSetValuesBlockedLocal(), MatSetValuesBlocked(), ADD_VALUES, INSERT_VALUES,
140           MatSetValuesBlockedLocal(), MatSetValuesLocal(), VecScatterBegin(), VecScatterEnd()
141 
142 M*/
143 
144 /*MC
145     MAX_VALUES - Puts the maximum of the scattered/gathered value and the current value into each location
146 
147     Level: beginner
148 
149 .seealso: InsertMode, VecScatterBegin(), VecScatterEnd(), ADD_VALUES, INSERT_VALUES
150 
151 M*/
152 
153 /*E
154   ScatterMode - Determines the direction of a scatter
155 
156   Level: beginner
157 
158 .seealso: VecScatter, VecScatterBegin(), VecScatterEnd()
159 E*/
160 typedef enum {SCATTER_FORWARD=0, SCATTER_REVERSE=1, SCATTER_FORWARD_LOCAL=2, SCATTER_REVERSE_LOCAL=3, SCATTER_LOCAL=2} ScatterMode;
161 
162 /*MC
163     SCATTER_FORWARD - Scatters the values as dictated by the VecScatterCreate() call
164 
165     Level: beginner
166 
167 .seealso: VecScatter, ScatterMode, VecScatterCreate(), VecScatterBegin(), VecScatterEnd(), SCATTER_REVERSE, SCATTER_FORWARD_LOCAL,
168           SCATTER_REVERSE_LOCAL
169 
170 M*/
171 
172 /*MC
173     SCATTER_REVERSE - Moves the values in the opposite direction then the directions indicated in
174          in the VecScatterCreate()
175 
176     Level: beginner
177 
178 .seealso: VecScatter, ScatterMode, VecScatterCreate(), VecScatterBegin(), VecScatterEnd(), SCATTER_FORWARD, SCATTER_FORWARD_LOCAL,
179           SCATTER_REVERSE_LOCAL
180 
181 M*/
182 
183 /*MC
184     SCATTER_FORWARD_LOCAL - Scatters the values as dictated by the VecScatterCreate() call except NO parallel communication
185        is done. Any variables that have be moved between processes are ignored
186 
187     Level: developer
188 
189 .seealso: VecScatter, ScatterMode, VecScatterCreate(), VecScatterBegin(), VecScatterEnd(), SCATTER_REVERSE, SCATTER_FORWARD,
190           SCATTER_REVERSE_LOCAL
191 
192 M*/
193 
194 /*MC
195     SCATTER_REVERSE_LOCAL - Moves the values in the opposite direction then the directions indicated in
196          in the VecScatterCreate()  except NO parallel communication
197        is done. Any variables that have be moved between processes are ignored
198 
199     Level: developer
200 
201 .seealso: VecScatter, ScatterMode, VecScatterCreate(), VecScatterBegin(), VecScatterEnd(), SCATTER_FORWARD, SCATTER_FORWARD_LOCAL,
202           SCATTER_REVERSE
203 
204 M*/
205 
206 /*
207   Create and initialize a linked list
208   Input Parameters:
209     idx_start - starting index of the list
210     lnk_max   - max value of lnk indicating the end of the list
211     nlnk      - max length of the list
212   Output Parameters:
213     lnk       - list initialized
214     bt        - PetscBT (bitarray) with all bits set to false
215 */
216 #define PetscLLCreate(idx_start,lnk_max,nlnk,lnk,bt) \
217   (PetscMalloc(nlnk*sizeof(PetscInt),&lnk) || PetscBTCreate(nlnk,bt) || PetscBTMemzero(nlnk,bt) || (lnk[idx_start] = lnk_max,0))
218 
219 /*
220   Add a index set into a sorted linked list
221   Input Parameters:
222     nidx      - number of input indices
223     indices   - interger array
224     idx_start - starting index of the list
225     lnk       - linked list(an integer array) that is created
226     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
227   output Parameters:
228     nlnk      - number of newly added indices
229     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from indices
230     bt        - updated PetscBT (bitarray)
231 */
232 #define PetscLLAdd(nidx,indices,idx_start,nlnk,lnk,bt) 0;\
233 {\
234   PetscInt _k,_entry,_location,_lnkdata;\
235   nlnk     = 0;\
236   _lnkdata = idx_start;\
237   for (_k=0; _k<nidx; _k++){\
238     _entry = indices[_k];\
239     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
240       /* search for insertion location */\
241       /* start from the beginning if _entry < previous _entry */\
242       if (_k && _entry < _lnkdata) _lnkdata  = idx_start;\
243       do {\
244         _location = _lnkdata;\
245         _lnkdata  = lnk[_location];\
246       } while (_entry > _lnkdata);\
247       /* insertion location is found, add entry into lnk */\
248       lnk[_location] = _entry;\
249       lnk[_entry]    = _lnkdata;\
250       nlnk++;\
251       _lnkdata = _entry; /* next search starts from here if next_entry > _entry */\
252     }\
253   }\
254 }
255 
256 /*
257   Add a SORTED index set into a sorted linked list
258   Input Parameters:
259     nidx      - number of input indices
260     indices   - sorted interger array
261     idx_start - starting index of the list
262     lnk       - linked list(an integer array) that is created
263     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
264   output Parameters:
265     nlnk      - number of newly added indices
266     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from indices
267     bt        - updated PetscBT (bitarray)
268 */
269 #define PetscLLAddSorted(nidx,indices,idx_start,nlnk,lnk,bt) 0;\
270 {\
271   PetscInt _k,_entry,_location,_lnkdata;\
272   nlnk      = 0;\
273   _lnkdata  = idx_start;\
274   for (_k=0; _k<nidx; _k++){\
275     _entry = indices[_k];\
276     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
277       /* search for insertion location */\
278       do {\
279         _location = _lnkdata;\
280         _lnkdata  = lnk[_location];\
281       } while (_entry > _lnkdata);\
282       /* insertion location is found, add entry into lnk */\
283       lnk[_location] = _entry;\
284       lnk[_entry]    = _lnkdata;\
285       nlnk++;\
286       _lnkdata = _entry; /* next search starts from here */\
287     }\
288   }\
289 }
290 
291 /*
292   Add a SORTED index set into a sorted linked list used for LUFactorSymbolic()
293   Same as PetscLLAddSorted() with an additional operation:
294        count the number of input indices that are no larger than 'diag'
295   Input Parameters:
296     indices   - sorted interger array
297     idx_start - starting index of the list
298     lnk       - linked list(an integer array) that is created
299     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
300     diag      - index of the active row in LUFactorSymbolic
301     nzbd      - number of input indices with indices <= idx_start
302   output Parameters:
303     nlnk      - number of newly added indices
304     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from indices
305     bt        - updated PetscBT (bitarray)
306     im        - im[idx_start] =  num of entries with indices <= diag
307 */
308 #define PetscLLAddSortedLU(indices,idx_start,nlnk,lnk,bt,diag,nzbd,im) 0;\
309 {\
310   PetscInt _k,_entry,_location,_lnkdata,_nidx;\
311   nlnk     = 0;\
312   _lnkdata = idx_start;\
313   _nidx = im[idx_start] - nzbd; /* num of entries with idx_start < index <= diag */\
314   for (_k=0; _k<_nidx; _k++){\
315     _entry = indices[_k];\
316     nzbd++;\
317     if ( _entry== diag) im[idx_start] = 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