xref: /petsc/include/petscsys.h (revision 99f44b2557a67de904920324aa721df1e96ce6a2)
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 /*E
110   InsertMode - Whether entries are inserted or added into vectors or matrices
111 
112   Level: beginner
113 
114 .seealso: VecSetValues(), MatSetValues(), VecSetValue(), VecSetValuesBlocked(),
115           VecSetValuesLocal(), VecSetValuesBlockedLocal(), MatSetValuesBlocked(),
116           MatSetValuesBlockedLocal(), MatSetValuesLocal(), VecScatterBegin(), VecScatterEnd()
117 E*/
118 typedef enum {NOT_SET_VALUES, INSERT_VALUES, ADD_VALUES, MAX_VALUES} InsertMode;
119 
120 /*MC
121     INSERT_VALUES - Put a value into a vector or matrix, overwrites any previous value
122 
123     Level: beginner
124 
125 .seealso: InsertMode, VecSetValues(), MatSetValues(), VecSetValue(), VecSetValuesBlocked(),
126           VecSetValuesLocal(), VecSetValuesBlockedLocal(), MatSetValuesBlocked(), ADD_VALUES, INSERT_VALUES,
127           MatSetValuesBlockedLocal(), MatSetValuesLocal(), VecScatterBegin(), VecScatterEnd()
128 
129 M*/
130 
131 /*MC
132     ADD_VALUES - Adds a value into a vector or matrix, if there previously was no value, just puts the
133                 value into that location
134 
135     Level: beginner
136 
137 .seealso: InsertMode, VecSetValues(), MatSetValues(), VecSetValue(), VecSetValuesBlocked(),
138           VecSetValuesLocal(), VecSetValuesBlockedLocal(), MatSetValuesBlocked(), ADD_VALUES, INSERT_VALUES,
139           MatSetValuesBlockedLocal(), MatSetValuesLocal(), VecScatterBegin(), VecScatterEnd()
140 
141 M*/
142 
143 /*MC
144     MAX_VALUES - Puts the maximum of the scattered/gathered value and the current value into each location
145 
146     Level: beginner
147 
148 .seealso: InsertMode, VecScatterBegin(), VecScatterEnd(), ADD_VALUES, INSERT_VALUES
149 
150 M*/
151 
152 /*E
153   ScatterMode - Determines the direction of a scatter
154 
155   Level: beginner
156 
157 .seealso: VecScatter, VecScatterBegin(), VecScatterEnd()
158 E*/
159 typedef enum {SCATTER_FORWARD=0, SCATTER_REVERSE=1, SCATTER_FORWARD_LOCAL=2, SCATTER_REVERSE_LOCAL=3, SCATTER_LOCAL=2} ScatterMode;
160 
161 /*MC
162     SCATTER_FORWARD - Scatters the values as dictated by the VecScatterCreate() call
163 
164     Level: beginner
165 
166 .seealso: VecScatter, ScatterMode, VecScatterCreate(), VecScatterBegin(), VecScatterEnd(), SCATTER_REVERSE, SCATTER_FORWARD_LOCAL,
167           SCATTER_REVERSE_LOCAL
168 
169 M*/
170 
171 /*MC
172     SCATTER_REVERSE - Moves the values in the opposite direction then the directions indicated in
173          in the VecScatterCreate()
174 
175     Level: beginner
176 
177 .seealso: VecScatter, ScatterMode, VecScatterCreate(), VecScatterBegin(), VecScatterEnd(), SCATTER_FORWARD, SCATTER_FORWARD_LOCAL,
178           SCATTER_REVERSE_LOCAL
179 
180 M*/
181 
182 /*MC
183     SCATTER_FORWARD_LOCAL - Scatters the values as dictated by the VecScatterCreate() call except NO parallel communication
184        is done. Any variables that have be moved between processes are ignored
185 
186     Level: developer
187 
188 .seealso: VecScatter, ScatterMode, VecScatterCreate(), VecScatterBegin(), VecScatterEnd(), SCATTER_REVERSE, SCATTER_FORWARD,
189           SCATTER_REVERSE_LOCAL
190 
191 M*/
192 
193 /*MC
194     SCATTER_REVERSE_LOCAL - Moves the values in the opposite direction then the directions indicated in
195          in the VecScatterCreate()  except NO parallel communication
196        is done. Any variables that have be moved between processes are ignored
197 
198     Level: developer
199 
200 .seealso: VecScatter, ScatterMode, VecScatterCreate(), VecScatterBegin(), VecScatterEnd(), SCATTER_FORWARD, SCATTER_FORWARD_LOCAL,
201           SCATTER_REVERSE
202 
203 M*/
204 
205 /*
206   Create and initialize a linked list
207   Input Parameters:
208     idx_start - starting index of the list
209     lnk_max   - max value of lnk indicating the end of the list
210     nlnk      - max length of the list
211   Output Parameters:
212     lnk       - list initialized
213     bt        - PetscBT (bitarray) with all bits set to false
214 */
215 #define PetscLLCreate(idx_start,lnk_max,nlnk,lnk,bt) \
216   (PetscMalloc(nlnk*sizeof(PetscInt),&lnk) || PetscBTCreate(nlnk,bt) || PetscBTMemzero(nlnk,bt) || (lnk[idx_start] = lnk_max,0))
217 
218 /*
219   Add an index set into a sorted linked list
220   Input Parameters:
221     nidx      - number of input indices
222     indices   - interger array
223     idx_start - starting index of the list
224     lnk       - linked list(an integer array) that is created
225     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
226   output Parameters:
227     nlnk      - number of newly added indices
228     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from indices
229     bt        - updated PetscBT (bitarray)
230 */
231 #define PetscLLAdd(nidx,indices,idx_start,nlnk,lnk,bt) 0;\
232 {\
233   PetscInt _k,_entry,_location,_lnkdata;\
234   nlnk     = 0;\
235   _lnkdata = idx_start;\
236   for (_k=0; _k<nidx; _k++){\
237     _entry = indices[_k];\
238     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
239       /* search for insertion location */\
240       /* start from the beginning if _entry < previous _entry */\
241       if (_k && _entry < _lnkdata) _lnkdata  = idx_start;\
242       do {\
243         _location = _lnkdata;\
244         _lnkdata  = lnk[_location];\
245       } while (_entry > _lnkdata);\
246       /* insertion location is found, add entry into lnk */\
247       lnk[_location] = _entry;\
248       lnk[_entry]    = _lnkdata;\
249       nlnk++;\
250       _lnkdata = _entry; /* next search starts from here if next_entry > _entry */\
251     }\
252   }\
253 }
254 
255 /*
256   Add a permuted index set into a sorted linked list
257   Input Parameters:
258     nidx      - number of input indices
259     indices   - interger array
260     perm      - permutation of indices
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 PetscLLAddPerm(nidx,indices,perm,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 = perm[indices[_k]];\
276     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
277       /* search for insertion location */\
278       /* start from the beginning if _entry < previous _entry */\
279       if (_k && _entry < _lnkdata) _lnkdata  = idx_start;\
280       do {\
281         _location = _lnkdata;\
282         _lnkdata  = lnk[_location];\
283       } while (_entry > _lnkdata);\
284       /* insertion location is found, add entry into lnk */\
285       lnk[_location] = _entry;\
286       lnk[_entry]    = _lnkdata;\
287       nlnk++;\
288       _lnkdata = _entry; /* next search starts from here if next_entry > _entry */\
289     }\
290   }\
291 }
292 
293 /*
294   Add a SORTED index set into a sorted linked list
295   Input Parameters:
296     nidx      - number of input indices
297     indices   - sorted interger array
298     idx_start - starting index of the list
299     lnk       - linked list(an integer array) that is created
300     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
301   output Parameters:
302     nlnk      - number of newly added indices
303     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from indices
304     bt        - updated PetscBT (bitarray)
305 */
306 #define PetscLLAddSorted(nidx,indices,idx_start,nlnk,lnk,bt) 0;\
307 {\
308   PetscInt _k,_entry,_location,_lnkdata;\
309   nlnk      = 0;\
310   _lnkdata  = idx_start;\
311   for (_k=0; _k<nidx; _k++){\
312     _entry = indices[_k];\
313     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
314       /* search for insertion location */\
315       do {\
316         _location = _lnkdata;\
317         _lnkdata  = lnk[_location];\
318       } while (_entry > _lnkdata);\
319       /* insertion location is found, add entry into lnk */\
320       lnk[_location] = _entry;\
321       lnk[_entry]    = _lnkdata;\
322       nlnk++;\
323       _lnkdata = _entry; /* next search starts from here */\
324     }\
325   }\
326 }
327 
328 /*
329   Add a SORTED index set into a sorted linked list used for LUFactorSymbolic()
330   Same as PetscLLAddSorted() with an additional operation:
331        count the number of input indices that are no larger than 'diag'
332   Input Parameters:
333     indices   - sorted interger array
334     idx_start - starting index of the list
335     lnk       - linked list(an integer array) that is created
336     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
337     diag      - index of the active row in LUFactorSymbolic
338     nzbd      - number of input indices with indices <= idx_start
339   output Parameters:
340     nlnk      - number of newly added indices
341     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from indices
342     bt        - updated PetscBT (bitarray)
343     im        - im[idx_start] =  num of entries with indices <= diag
344 */
345 #define PetscLLAddSortedLU(indices,idx_start,nlnk,lnk,bt,diag,nzbd,im) 0;\
346 {\
347   PetscInt _k,_entry,_location,_lnkdata,_nidx;\
348   nlnk     = 0;\
349   _lnkdata = idx_start;\
350   _nidx = im[idx_start] - nzbd; /* num of entries with idx_start < index <= diag */\
351   for (_k=0; _k<_nidx; _k++){\
352     _entry = indices[_k];\
353     nzbd++;\
354     if ( _entry== diag) im[idx_start] = nzbd;\
355     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
356       /* search for insertion location */\
357       do {\
358         _location = _lnkdata;\
359         _lnkdata  = lnk[_location];\
360       } while (_entry > _lnkdata);\
361       /* insertion location is found, add entry into lnk */\
362       lnk[_location] = _entry;\
363       lnk[_entry]    = _lnkdata;\
364       nlnk++;\
365       _lnkdata = _entry; /* next search starts from here */\
366     }\
367   }\
368 }
369 
370 /*
371   Copy data on the list into an array, then initialize the list
372   Input Parameters:
373     idx_start - starting index of the list
374     lnk_max   - max value of lnk indicating the end of the list
375     nlnk      - number of data on the list to be copied
376     lnk       - linked list
377     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
378   output Parameters:
379     indices   - array that contains the copied data
380     lnk       - linked list that is cleaned and initialize
381     bt        - PetscBT (bitarray) with all bits set to false
382 */
383 #define PetscLLClean(idx_start,lnk_max,nlnk,lnk,indices,bt) 0;\
384 {\
385   PetscInt _j,_idx=idx_start;\
386   for (_j=0; _j<nlnk; _j++){\
387     _idx = lnk[_idx];\
388     *(indices+_j) = _idx;\
389     ierr = PetscBTClear(bt,_idx);CHKERRQ(ierr);\
390   }\
391   lnk[idx_start] = lnk_max;\
392 }
393 /*
394   Free memories used by the list
395 */
396 #define PetscLLDestroy(lnk,bt) (PetscFree(lnk) || PetscBTDestroy(bt))
397 
398 /* Routines below are used for incomplete matrix factorization */
399 /*
400   Create and initialize a linked list and its levels
401   Input Parameters:
402     idx_start - starting index of the list
403     lnk_max   - max value of lnk indicating the end of the list
404     nlnk      - max length of the list
405   Output Parameters:
406     lnk       - list initialized
407     lnk_lvl   - array of size nlnk for storing levels of lnk
408     bt        - PetscBT (bitarray) with all bits set to false
409 */
410 #define PetscIncompleteLLCreate(idx_start,lnk_max,nlnk,lnk,lnk_lvl,bt)\
411   (PetscMalloc(2*nlnk*sizeof(PetscInt),&lnk) || PetscBTCreate(nlnk,bt) || PetscBTMemzero(nlnk,bt) || (lnk[idx_start] = lnk_max,lnk_lvl = lnk + nlnk,0))
412 
413 /*
414   Initialize a sorted linked list used for ILU and ICC
415   Input Parameters:
416     nidx      - number of input idx
417     idx       - interger array used for storing column indices
418     idx_start - starting index of the list
419     perm      - indices of an IS
420     lnk       - linked list(an integer array) that is created
421     lnklvl    - levels of lnk
422     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
423   output Parameters:
424     nlnk     - number of newly added idx
425     lnk      - the sorted(increasing order) linked list containing new and non-redundate entries from idx
426     lnklvl   - levels of lnk
427     bt       - updated PetscBT (bitarray)
428 */
429 #define PetscIncompleteLLInit(nidx,idx,idx_start,perm,nlnk,lnk,lnklvl,bt) 0;\
430 {\
431   PetscInt _k,_entry,_location,_lnkdata;\
432   nlnk     = 0;\
433   _lnkdata = idx_start;\
434   for (_k=0; _k<nidx; _k++){\
435     _entry = perm[idx[_k]];\
436     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
437       /* search for insertion location */\
438       if (_k && _entry < _lnkdata) _lnkdata  = idx_start;\
439       do {\
440         _location = _lnkdata;\
441         _lnkdata  = lnk[_location];\
442       } while (_entry > _lnkdata);\
443       /* insertion location is found, add entry into lnk */\
444       lnk[_location]  = _entry;\
445       lnk[_entry]     = _lnkdata;\
446       lnklvl[_entry] = 0;\
447       nlnk++;\
448       _lnkdata = _entry; /* next search starts from here if next_entry > _entry */\
449     }\
450   }\
451 }
452 
453 /*
454   Add a SORTED index set into a sorted linked list for ILU
455   Input Parameters:
456     nidx      - number of input indices
457     idx       - sorted interger array used for storing column indices
458     level     - level of fill, e.g., ICC(level)
459     idxlvl    - level of idx
460     idx_start - starting index of the list
461     lnk       - linked list(an integer array) that is created
462     lnklvl    - levels of lnk
463     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
464     prow      - the row number of idx
465   output Parameters:
466     nlnk     - number of newly added idx
467     lnk      - the sorted(increasing order) linked list containing new and non-redundate entries from idx
468     lnklvl   - levels of lnk
469     bt       - updated PetscBT (bitarray)
470 
471   Note: the level of factor(i,j) is set as lvl(i,j) = min{ lvl(i,j), lvl(i,prow)+lvl(prow,j)+1)
472         where idx = non-zero columns of U(prow,prow+1:n-1), prow<i
473 */
474 #define PetscILULLAddSorted(nidx,idx,level,idxlvl,idx_start,nlnk,lnk,lnklvl,bt,lnklvl_prow) 0;\
475 {\
476   PetscInt _k,_entry,_location,_lnkdata,_incrlev,_lnklvl_prow=lnklvl[prow];\
477   nlnk     = 0;\
478   _lnkdata = idx_start;\
479   for (_k=0; _k<nidx; _k++){\
480     _incrlev = idxlvl[_k] + _lnklvl_prow + 1;\
481     if (_incrlev > level) continue;\
482     _entry = idx[_k];\
483     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
484       /* search for insertion location */\
485       do {\
486         _location = _lnkdata;\
487         _lnkdata  = lnk[_location];\
488       } while (_entry > _lnkdata);\
489       /* insertion location is found, add entry into lnk */\
490       lnk[_location]  = _entry;\
491       lnk[_entry]     = _lnkdata;\
492       lnklvl[_entry] = _incrlev;\
493       nlnk++;\
494       _lnkdata = _entry; /* next search starts from here if next_entry > _entry */\
495     } else { /* existing entry: update lnklvl */\
496       if (lnklvl[_entry] > _incrlev) lnklvl[_entry] = _incrlev;\
497     }\
498   }\
499 }
500 
501 /*
502   Add a index set into a sorted linked list
503   Input Parameters:
504     nidx      - number of input idx
505     idx   - interger array used for storing column indices
506     level     - level of fill, e.g., ICC(level)
507     idxlvl - level of idx
508     idx_start - starting index of the list
509     lnk       - linked list(an integer array) that is created
510     lnklvl   - levels of lnk
511     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
512   output Parameters:
513     nlnk      - number of newly added idx
514     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from idx
515     lnklvl   - levels of lnk
516     bt        - updated PetscBT (bitarray)
517 */
518 #define PetscIncompleteLLAdd(nidx,idx,level,idxlvl,idx_start,nlnk,lnk,lnklvl,bt) 0;\
519 {\
520   PetscInt _k,_entry,_location,_lnkdata,_incrlev;\
521   nlnk     = 0;\
522   _lnkdata = idx_start;\
523   for (_k=0; _k<nidx; _k++){\
524     _incrlev = idxlvl[_k] + 1;\
525     if (_incrlev > level) continue;\
526     _entry = idx[_k];\
527     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
528       /* search for insertion location */\
529       if (_k && _entry < _lnkdata) _lnkdata  = idx_start;\
530       do {\
531         _location = _lnkdata;\
532         _lnkdata  = lnk[_location];\
533       } while (_entry > _lnkdata);\
534       /* insertion location is found, add entry into lnk */\
535       lnk[_location]  = _entry;\
536       lnk[_entry]     = _lnkdata;\
537       lnklvl[_entry] = _incrlev;\
538       nlnk++;\
539       _lnkdata = _entry; /* next search starts from here if next_entry > _entry */\
540     } else { /* existing entry: update lnklvl */\
541       if (lnklvl[_entry] > _incrlev) lnklvl[_entry] = _incrlev;\
542     }\
543   }\
544 }
545 
546 /*
547   Add a SORTED index set into a sorted linked list
548   Input Parameters:
549     nidx      - number of input indices
550     idx   - sorted interger array used for storing column indices
551     level     - level of fill, e.g., ICC(level)
552     idxlvl - level of idx
553     idx_start - starting index of the list
554     lnk       - linked list(an integer array) that is created
555     lnklvl    - levels of lnk
556     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
557   output Parameters:
558     nlnk      - number of newly added idx
559     lnk       - the sorted(increasing order) linked list containing new and non-redundate entries from idx
560     lnklvl    - levels of lnk
561     bt        - updated PetscBT (bitarray)
562 */
563 #define PetscIncompleteLLAddSorted(nidx,idx,level,idxlvl,idx_start,nlnk,lnk,lnklvl,bt) 0;\
564 {\
565   PetscInt _k,_entry,_location,_lnkdata,_incrlev;\
566   nlnk = 0;\
567   _lnkdata = idx_start;\
568   for (_k=0; _k<nidx; _k++){\
569     _incrlev = idxlvl[_k] + 1;\
570     if (_incrlev > level) continue;\
571     _entry = idx[_k];\
572     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
573       /* search for insertion location */\
574       do {\
575         _location = _lnkdata;\
576         _lnkdata  = lnk[_location];\
577       } while (_entry > _lnkdata);\
578       /* insertion location is found, add entry into lnk */\
579       lnk[_location] = _entry;\
580       lnk[_entry]    = _lnkdata;\
581       lnklvl[_entry] = _incrlev;\
582       nlnk++;\
583       _lnkdata = _entry; /* next search starts from here */\
584     } else { /* existing entry: update lnklvl */\
585       if (lnklvl[_entry] > _incrlev) lnklvl[_entry] = _incrlev;\
586     }\
587   }\
588 }
589 
590 /*
591   Add a SORTED index set into a sorted linked list for ICC
592   Input Parameters:
593     nidx      - number of input indices
594     idx       - sorted interger array used for storing column indices
595     level     - level of fill, e.g., ICC(level)
596     idxlvl    - level of idx
597     idx_start - starting index of the list
598     lnk       - linked list(an integer array) that is created
599     lnklvl    - levels of lnk
600     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
601     idxlvl_prow - idxlvl[prow], where prow is the row number of the idx
602   output Parameters:
603     nlnk   - number of newly added indices
604     lnk    - the sorted(increasing order) linked list containing new and non-redundate entries from idx
605     lnklvl - levels of lnk
606     bt     - updated PetscBT (bitarray)
607   Note: the level of U(i,j) is set as lvl(i,j) = min{ lvl(i,j), lvl(prow,i)+lvl(prow,j)+1)
608         where idx = non-zero columns of U(prow,prow+1:n-1), prow<i
609 */
610 #define PetscICCLLAddSorted(nidx,idx,level,idxlvl,idx_start,nlnk,lnk,lnklvl,bt,idxlvl_prow) 0;\
611 {\
612   PetscInt _k,_entry,_location,_lnkdata,_incrlev;\
613   nlnk = 0;\
614   _lnkdata = idx_start;\
615   for (_k=0; _k<nidx; _k++){\
616     _incrlev = idxlvl[_k] + idxlvl_prow + 1;\
617     if (_incrlev > level) continue;\
618     _entry = idx[_k];\
619     if (!PetscBTLookupSet(bt,_entry)){  /* new entry */\
620       /* search for insertion location */\
621       do {\
622         _location = _lnkdata;\
623         _lnkdata  = lnk[_location];\
624       } while (_entry > _lnkdata);\
625       /* insertion location is found, add entry into lnk */\
626       lnk[_location] = _entry;\
627       lnk[_entry]    = _lnkdata;\
628       lnklvl[_entry] = _incrlev;\
629       nlnk++;\
630       _lnkdata = _entry; /* next search starts from here */\
631     } else { /* existing entry: update lnklvl */\
632       if (lnklvl[_entry] > _incrlev) lnklvl[_entry] = _incrlev;\
633     }\
634   }\
635 }
636 
637 /*
638   Copy data on the list into an array, then initialize the list
639   Input Parameters:
640     idx_start - starting index of the list
641     lnk_max   - max value of lnk indicating the end of the list
642     nlnk      - number of data on the list to be copied
643     lnk       - linked list
644     lnklvl    - level of lnk
645     bt        - PetscBT (bitarray), bt[idx]=true marks idx is in lnk
646   output Parameters:
647     indices - array that contains the copied data
648     lnk     - linked list that is cleaned and initialize
649     lnklvl  - level of lnk that is reinitialized
650     bt      - PetscBT (bitarray) with all bits set to false
651 */
652 #define PetscIncompleteLLClean(idx_start,lnk_max,nlnk,lnk,lnklvl,indices,indiceslvl,bt) 0;\
653 {\
654   PetscInt _j,_idx=idx_start;\
655   for (_j=0; _j<nlnk; _j++){\
656     _idx = lnk[_idx];\
657     *(indices+_j) = _idx;\
658     *(indiceslvl+_j) = lnklvl[_idx];\
659     lnklvl[_idx] = -1;\
660     ierr = PetscBTClear(bt,_idx);CHKERRQ(ierr);\
661   }\
662   lnk[idx_start] = lnk_max;\
663 }
664 /*
665   Free memories used by the list
666 */
667 #define PetscIncompleteLLDestroy(lnk,bt) (PetscFree(lnk) || PetscBTDestroy(bt))
668 
669 PETSC_EXTERN_CXX_END
670 #endif /* __PETSCSYS_H */
671