Actual source code: pointqueue.c
1: #include <petsc/private/dmpleximpl.h>
3: /*@
4: DMPlexPointQueueCreate - Create a `DMPlexPointQueue`, a simple FIFO queue of `PetscInt` mesh points used by `DMPLEX` traversal routines.
6: Not Collective
8: Input Parameter:
9: . size - the initial capacity of the queue
11: Output Parameter:
12: . queue - the newly created `DMPlexPointQueue`
14: Level: developer
16: Note:
17: The queue grows automatically when full; see `DMPlexPointQueueEnsureSize()`.
19: .seealso: `DMPLEX`, `DMPlexPointQueue`, `DMPlexPointQueueDestroy()`, `DMPlexPointQueueEnqueue()`, `DMPlexPointQueueDequeue()`
20: @*/
21: PetscErrorCode DMPlexPointQueueCreate(PetscInt size, DMPlexPointQueue *queue)
22: {
23: DMPlexPointQueue q;
25: PetscFunctionBegin;
26: PetscCheck(size >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Queue size %" PetscInt_FMT " must be non-negative", size);
27: PetscCall(PetscCalloc1(1, &q));
28: q->size = size;
29: PetscCall(PetscMalloc1(q->size, &q->points));
30: q->num = 0;
31: q->front = 0;
32: q->back = q->size - 1;
33: *queue = q;
34: PetscFunctionReturn(PETSC_SUCCESS);
35: }
37: /*@
38: DMPlexPointQueueDestroy - Destroy a `DMPlexPointQueue` previously created with `DMPlexPointQueueCreate()`.
40: Not Collective
42: Input Parameter:
43: . queue - the queue to destroy; set to `NULL` on return
45: Level: developer
47: .seealso: `DMPLEX`, `DMPlexPointQueue`, `DMPlexPointQueueCreate()`
48: @*/
49: PetscErrorCode DMPlexPointQueueDestroy(DMPlexPointQueue *queue)
50: {
51: DMPlexPointQueue q = *queue;
53: PetscFunctionBegin;
54: PetscCall(PetscFree(q->points));
55: PetscCall(PetscFree(q));
56: *queue = NULL;
57: PetscFunctionReturn(PETSC_SUCCESS);
58: }
60: /*@
61: DMPlexPointQueueEnsureSize - Ensure that a `DMPlexPointQueue` has room for at least one more entry, growing its capacity if it is full.
63: Not Collective
65: Input Parameter:
66: . queue - the queue
68: Level: developer
70: .seealso: `DMPLEX`, `DMPlexPointQueue`, `DMPlexPointQueueCreate()`, `DMPlexPointQueueEnqueue()`
71: @*/
72: PetscErrorCode DMPlexPointQueueEnsureSize(DMPlexPointQueue queue)
73: {
74: PetscInt oldSize;
76: PetscFunctionBegin;
77: if (queue->num < queue->size) PetscFunctionReturn(PETSC_SUCCESS);
78: oldSize = queue->size;
79: queue->size = PetscMax(2 * oldSize, 1);
80: PetscCall(PetscRealloc(queue->size * sizeof(PetscInt), &queue->points));
81: // Full ring: entries are front..oldSize-1 then 0..front-1, so move the wrapped part after the old end
82: if (queue->front > 0) PetscCall(PetscArraycpy(&queue->points[oldSize], queue->points, queue->front));
83: queue->back = queue->front + oldSize - 1;
84: PetscFunctionReturn(PETSC_SUCCESS);
85: }
87: /*@
88: DMPlexPointQueueEnqueue - Add a mesh point to the back of a `DMPlexPointQueue`.
90: Not Collective
92: Input Parameters:
93: + queue - the queue
94: - p - the mesh point to enqueue
96: Level: developer
98: .seealso: `DMPLEX`, `DMPlexPointQueue`, `DMPlexPointQueueDequeue()`, `DMPlexPointQueueBack()`
99: @*/
100: PetscErrorCode DMPlexPointQueueEnqueue(DMPlexPointQueue queue, PetscInt p)
101: {
102: PetscFunctionBegin;
103: PetscCall(DMPlexPointQueueEnsureSize(queue));
104: queue->back = (queue->back + 1) % queue->size;
105: queue->points[queue->back] = p;
106: ++queue->num;
107: PetscFunctionReturn(PETSC_SUCCESS);
108: }
110: /*@
111: DMPlexPointQueueDequeue - Remove and return the mesh point at the front of a `DMPlexPointQueue`.
113: Not Collective
115: Input Parameter:
116: . queue - the queue
118: Output Parameter:
119: . p - the mesh point that was at the front of the queue
121: Level: developer
123: Note:
124: It is an error to dequeue from an empty queue; use `DMPlexPointQueueEmpty()` to check first.
126: .seealso: `DMPLEX`, `DMPlexPointQueue`, `DMPlexPointQueueEnqueue()`, `DMPlexPointQueueFront()`, `DMPlexPointQueueEmpty()`
127: @*/
128: PetscErrorCode DMPlexPointQueueDequeue(DMPlexPointQueue queue, PetscInt *p)
129: {
130: PetscFunctionBegin;
131: PetscCheck(queue->num, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot dequeue from an empty queue");
132: *p = queue->points[queue->front];
133: queue->front = (queue->front + 1) % queue->size;
134: --queue->num;
135: PetscFunctionReturn(PETSC_SUCCESS);
136: }
138: /*@
139: DMPlexPointQueueFront - Return, without removing, the mesh point at the front of a `DMPlexPointQueue`.
141: Not Collective
143: Input Parameter:
144: . queue - the queue
146: Output Parameter:
147: . p - the mesh point at the front of the queue
149: Level: developer
151: .seealso: `DMPLEX`, `DMPlexPointQueue`, `DMPlexPointQueueBack()`, `DMPlexPointQueueDequeue()`, `DMPlexPointQueueEmpty()`
152: @*/
153: PetscErrorCode DMPlexPointQueueFront(DMPlexPointQueue queue, PetscInt *p)
154: {
155: PetscFunctionBegin;
156: PetscCheck(queue->num, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot get the front of an empty queue");
157: *p = queue->points[queue->front];
158: PetscFunctionReturn(PETSC_SUCCESS);
159: }
161: /*@
162: DMPlexPointQueueBack - Return, without removing, the mesh point at the back of a `DMPlexPointQueue`.
164: Not Collective
166: Input Parameter:
167: . queue - the queue
169: Output Parameter:
170: . p - the mesh point at the back of the queue
172: Level: developer
174: .seealso: `DMPLEX`, `DMPlexPointQueue`, `DMPlexPointQueueFront()`, `DMPlexPointQueueEnqueue()`, `DMPlexPointQueueEmpty()`
175: @*/
176: PetscErrorCode DMPlexPointQueueBack(DMPlexPointQueue queue, PetscInt *p)
177: {
178: PetscFunctionBegin;
179: PetscCheck(queue->num, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot get the back of an empty queue");
180: *p = queue->points[queue->back];
181: PetscFunctionReturn(PETSC_SUCCESS);
182: }
184: /*@
185: DMPlexPointQueueEmpty - Returns `PETSC_TRUE` if the queue is empty
187: Not Collective
189: Input Parameter:
190: . queue - the queue
192: Level: developer
194: Note:
195: Unlike most PETSc functions this does not return an error code.
197: .seealso: `DMPLEX`, `DMPlexPointQueue`, `DMPlexPointQueueFront()`, `DMPlexPointQueueEnqueue()`
198: @*/
199: PetscBool DMPlexPointQueueEmpty(DMPlexPointQueue queue)
200: {
201: if (!queue->num) return PETSC_TRUE;
202: return PETSC_FALSE;
203: }
205: /*@
206: DMPlexPointQueueEmptyCollective - Collectively determine whether a `DMPlexPointQueue` is empty on every process of an MPI communicator.
208: Collective
210: Input Parameters:
211: + obj - a `PetscObject` whose MPI communicator is used for the reduction
212: - queue - the queue
214: Output Parameter:
215: . empty - `PETSC_TRUE` if the queue is empty on every process in the MPI communicator, `PETSC_FALSE` otherwise
217: Level: developer
219: .seealso: `DMPLEX`, `DMPlexPointQueue`, `DMPlexPointQueueEmpty()`
220: @*/
221: PetscErrorCode DMPlexPointQueueEmptyCollective(PetscObject obj, DMPlexPointQueue queue, PetscBool *empty)
222: {
223: PetscFunctionBeginHot;
224: *empty = DMPlexPointQueueEmpty(queue);
225: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, empty, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm(obj)));
226: PetscFunctionReturn(PETSC_SUCCESS);
227: }