1 // Copyright (c) 2017-2026, Lawrence Livermore National Security, LLC and other CEED contributors.
2 // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3 //
4 // SPDX-License-Identifier: BSD-2-Clause
5 //
6 // This file is part of CEED: http://github.com/ceed
7
8 #include <ceed-impl.h>
9 #include <ceed.h>
10 #include <ceed/backend.h>
11 #include <stdbool.h>
12 #include <stdio.h>
13 #include <string.h>
14
15 /// @file
16 /// Implementation of CeedElemRestriction interfaces
17
18 /// ----------------------------------------------------------------------------
19 /// CeedElemRestriction Library Internal Functions
20 /// ----------------------------------------------------------------------------
21 /// @addtogroup CeedElemRestrictionDeveloper
22 /// @{
23
24 /**
25 @brief Permute and pad offsets for a blocked `CeedElemRestriction`
26
27 @param[in] offsets Array of shape `[num_elem, elem_size]`
28 @param[out] block_offsets Array of permuted and padded array values of shape `[num_block, elem_size, block_size]`
29 @param[in] num_block Number of blocks
30 @param[in] num_elem Number of elements
31 @param[in] block_size Number of elements in a block
32 @param[in] elem_size Size of each element
33
34 @return An error code: 0 - success, otherwise - failure
35
36 @ref Utility
37 **/
CeedPermutePadOffsets(const CeedInt * offsets,CeedInt * block_offsets,CeedInt num_block,CeedInt num_elem,CeedInt block_size,CeedInt elem_size)38 int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *block_offsets, CeedInt num_block, CeedInt num_elem, CeedInt block_size,
39 CeedInt elem_size) {
40 for (CeedInt e = 0; e < num_block * block_size; e += block_size) {
41 for (CeedInt j = 0; j < block_size; j++) {
42 for (CeedInt k = 0; k < elem_size; k++) {
43 block_offsets[e * elem_size + k * block_size + j] = offsets[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
44 }
45 }
46 }
47 return CEED_ERROR_SUCCESS;
48 }
49
50 /**
51 @brief Permute and pad orientations for a blocked `CeedElemRestriction`
52
53 @param[in] orients Array of shape `[num_elem, elem_size]`
54 @param[out] block_orients Array of permuted and padded array values of shape `[num_block, elem_size, block_size]`
55 @param[in] num_block Number of blocks
56 @param[in] num_elem Number of elements
57 @param[in] block_size Number of elements in a block
58 @param[in] elem_size Size of each element
59
60 @return An error code: 0 - success, otherwise - failure
61
62 @ref Utility
63 **/
CeedPermutePadOrients(const bool * orients,bool * block_orients,CeedInt num_block,CeedInt num_elem,CeedInt block_size,CeedInt elem_size)64 int CeedPermutePadOrients(const bool *orients, bool *block_orients, CeedInt num_block, CeedInt num_elem, CeedInt block_size, CeedInt elem_size) {
65 for (CeedInt e = 0; e < num_block * block_size; e += block_size) {
66 for (CeedInt j = 0; j < block_size; j++) {
67 for (CeedInt k = 0; k < elem_size; k++) {
68 block_orients[e * elem_size + k * block_size + j] = orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
69 }
70 }
71 }
72 return CEED_ERROR_SUCCESS;
73 }
74
75 /**
76 @brief Permute and pad curl-conforming orientations for a blocked `CeedElemRestriction`
77
78 @param[in] curl_orients Array of shape `[num_elem, elem_size]`
79 @param[out] block_curl_orients Array of permuted and padded array values of shape `[num_block, elem_size, block_size]`
80 @param[in] num_block Number of blocks
81 @param[in] num_elem Number of elements
82 @param[in] block_size Number of elements in a block
83 @param[in] elem_size Size of each element
84
85 @return An error code: 0 - success, otherwise - failure
86
87 @ref Utility
88 **/
CeedPermutePadCurlOrients(const CeedInt8 * curl_orients,CeedInt8 * block_curl_orients,CeedInt num_block,CeedInt num_elem,CeedInt block_size,CeedInt elem_size)89 int CeedPermutePadCurlOrients(const CeedInt8 *curl_orients, CeedInt8 *block_curl_orients, CeedInt num_block, CeedInt num_elem, CeedInt block_size,
90 CeedInt elem_size) {
91 for (CeedInt e = 0; e < num_block * block_size; e += block_size) {
92 for (CeedInt j = 0; j < block_size; j++) {
93 for (CeedInt k = 0; k < elem_size; k++) {
94 block_curl_orients[e * elem_size + k * block_size + j] = curl_orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
95 }
96 }
97 }
98 return CEED_ERROR_SUCCESS;
99 }
100
101 /**
102 @brief View a `CeedElemRestriction` passed as a `CeedObject`
103
104 @param[in] rstr `CeedElemRestriction` to view
105 @param[in] stream Filestream to write to
106
107 @return An error code: 0 - success, otherwise - failure
108
109 @ref Developer
110 **/
CeedElemRestrictionView_Object(CeedObject rstr,FILE * stream)111 static int CeedElemRestrictionView_Object(CeedObject rstr, FILE *stream) {
112 CeedCall(CeedElemRestrictionView((CeedElemRestriction)rstr, stream));
113 return CEED_ERROR_SUCCESS;
114 }
115
116 /**
117 @brief Destroy a `CeedElemRestricton` passed as a `CeedObject`
118
119 @param[in,out] rstr Address of `CeedElemRestriction` to destroy
120
121 @return An error code: 0 - success, otherwise - failure
122
123 @ref Developer
124 **/
CeedElemRestrictionDestroy_Object(CeedObject * rstr)125 static int CeedElemRestrictionDestroy_Object(CeedObject *rstr) {
126 CeedCall(CeedElemRestrictionDestroy((CeedElemRestriction *)rstr));
127 return CEED_ERROR_SUCCESS;
128 }
129
130 /// @}
131
132 /// ----------------------------------------------------------------------------
133 /// CeedElemRestriction Backend API
134 /// ----------------------------------------------------------------------------
135 /// @addtogroup CeedElemRestrictionBackend
136 /// @{
137
138 /**
139 @brief Get the type of a `CeedElemRestriction`
140
141 @param[in] rstr `CeedElemRestriction`
142 @param[out] rstr_type Variable to store restriction type
143
144 @return An error code: 0 - success, otherwise - failure
145
146 @ref Backend
147 **/
CeedElemRestrictionGetType(CeedElemRestriction rstr,CeedRestrictionType * rstr_type)148 int CeedElemRestrictionGetType(CeedElemRestriction rstr, CeedRestrictionType *rstr_type) {
149 *rstr_type = rstr->rstr_type;
150 return CEED_ERROR_SUCCESS;
151 }
152
153 /**
154 @brief Get the strided status of a `CeedElemRestriction`
155
156 @param[in] rstr `CeedElemRestriction`
157 @param[out] is_strided Variable to store strided status
158
159 @return An error code: 0 - success, otherwise - failure
160
161 @ref Backend
162 **/
CeedElemRestrictionIsStrided(CeedElemRestriction rstr,bool * is_strided)163 int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
164 *is_strided = (rstr->rstr_type == CEED_RESTRICTION_STRIDED);
165 return CEED_ERROR_SUCCESS;
166 }
167
168 /**
169 @brief Get the points status of a `CeedElemRestriction`
170
171 @param[in] rstr `CeedElemRestriction`
172 @param[out] is_points Variable to store points status
173
174 @return An error code: 0 - success, otherwise - failure
175
176 @ref Backend
177 **/
CeedElemRestrictionIsAtPoints(CeedElemRestriction rstr,bool * is_points)178 int CeedElemRestrictionIsAtPoints(CeedElemRestriction rstr, bool *is_points) {
179 *is_points = (rstr->rstr_type == CEED_RESTRICTION_POINTS);
180 return CEED_ERROR_SUCCESS;
181 }
182
183 /**
184 @brief Check if two `CeedElemRestriction` created with @ref CeedElemRestrictionCreateAtPoints() and use the same points per element
185
186 @param[in] rstr_a First `CeedElemRestriction`
187 @param[in] rstr_b Second `CeedElemRestriction`
188 @param[out] are_compatible Variable to store compatibility status
189
190 @return An error code: 0 - success, otherwise - failure
191
192 @ref Backend
193 **/
CeedElemRestrictionAtPointsAreCompatible(CeedElemRestriction rstr_a,CeedElemRestriction rstr_b,bool * are_compatible)194 int CeedElemRestrictionAtPointsAreCompatible(CeedElemRestriction rstr_a, CeedElemRestriction rstr_b, bool *are_compatible) {
195 CeedInt num_elem_a, num_elem_b, num_points_a, num_points_b;
196
197 // Cannot compare non-points restrictions
198 CeedCheck(rstr_a->rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr_a), CEED_ERROR_UNSUPPORTED,
199 "First CeedElemRestriction must be AtPoints");
200 CeedCheck(rstr_b->rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr_a), CEED_ERROR_UNSUPPORTED,
201 "Second CeedElemRestriction must be AtPoints");
202
203 CeedCall(CeedElemRestrictionGetNumElements(rstr_a, &num_elem_a));
204 CeedCall(CeedElemRestrictionGetNumElements(rstr_b, &num_elem_b));
205 CeedCall(CeedElemRestrictionGetNumPoints(rstr_a, &num_points_a));
206 CeedCall(CeedElemRestrictionGetNumPoints(rstr_b, &num_points_b));
207
208 // Check size and contents of offsets arrays
209 *are_compatible = true;
210 if (num_elem_a != num_elem_b) *are_compatible = false;
211 if (num_points_a != num_points_b) *are_compatible = false;
212 if (*are_compatible) {
213 const CeedInt *offsets_a, *offsets_b;
214
215 CeedCall(CeedElemRestrictionGetOffsets(rstr_a, CEED_MEM_HOST, &offsets_a));
216 CeedCall(CeedElemRestrictionGetOffsets(rstr_b, CEED_MEM_HOST, &offsets_b));
217 for (CeedInt i = 0; i < num_elem_a + 1 + num_points_a; i++) *are_compatible &= offsets_a[i] == offsets_b[i];
218 CeedCall(CeedElemRestrictionRestoreOffsets(rstr_a, &offsets_a));
219 CeedCall(CeedElemRestrictionRestoreOffsets(rstr_b, &offsets_b));
220 }
221 return CEED_ERROR_SUCCESS;
222 }
223
224 /**
225 @brief Get the strides of a strided `CeedElemRestriction`
226
227 @param[in] rstr `CeedElemRestriction`
228 @param[out] strides Variable to store strides array
229
230 @return An error code: 0 - success, otherwise - failure
231
232 @ref Backend
233 **/
CeedElemRestrictionGetStrides(CeedElemRestriction rstr,CeedInt strides[3])234 int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt strides[3]) {
235 CeedCheck(rstr->strides, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no stride data");
236 for (CeedInt i = 0; i < 3; i++) strides[i] = rstr->strides[i];
237 return CEED_ERROR_SUCCESS;
238 }
239
240 /**
241 @brief Get the backend stride status of a `CeedElemRestriction`
242
243 @param[in] rstr `CeedElemRestriction`
244 @param[out] has_backend_strides Variable to store stride status
245
246 @return An error code: 0 - success, otherwise - failure
247
248 @ref Backend
249 **/
CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr,bool * has_backend_strides)250 int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
251 CeedCheck(rstr->strides, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no stride data");
252 *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
253 (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
254 return CEED_ERROR_SUCCESS;
255 }
256
257 /**
258 @brief Get read-only access to a `CeedElemRestriction` offsets array by @ref CeedMemType
259
260 @param[in] rstr `CeedElemRestriction` to retrieve offsets
261 @param[in] mem_type Memory type on which to access the array.
262 If the backend uses a different memory type, this will perform a copy (possibly cached).
263 @param[out] offsets Array on memory type `mem_type`
264
265 @return An error code: 0 - success, otherwise - failure
266
267 @ref User
268 **/
CeedElemRestrictionGetOffsets(CeedElemRestriction rstr,CeedMemType mem_type,const CeedInt ** offsets)269 int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
270 if (rstr->rstr_base) {
271 CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_base, mem_type, offsets));
272 } else {
273 CeedCheck(rstr->GetOffsets, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
274 "Backend does not implement CeedElemRestrictionGetOffsets");
275 CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
276 rstr->num_readers++;
277 }
278 return CEED_ERROR_SUCCESS;
279 }
280
281 /**
282 @brief Restore an offsets array obtained using @ref CeedElemRestrictionGetOffsets()
283
284 @param[in] rstr `CeedElemRestriction` to restore
285 @param[in] offsets Array of offset data
286
287 @return An error code: 0 - success, otherwise - failure
288
289 @ref User
290 **/
CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr,const CeedInt ** offsets)291 int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
292 if (rstr->rstr_base) {
293 CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_base, offsets));
294 } else {
295 *offsets = NULL;
296 rstr->num_readers--;
297 }
298 return CEED_ERROR_SUCCESS;
299 }
300
301 /**
302 @brief Get read-only access to a `CeedElemRestriction` orientations array by @ref CeedMemType
303
304 @param[in] rstr `CeedElemRestriction` to retrieve orientations
305 @param[in] mem_type Memory type on which to access the array.
306 If the backend uses a different memory type, this will perform a copy (possibly cached).
307 @param[out] orients Array on memory type `mem_type`
308
309 @return An error code: 0 - success, otherwise - failure
310
311 @ref User
312 **/
CeedElemRestrictionGetOrientations(CeedElemRestriction rstr,CeedMemType mem_type,const bool ** orients)313 int CeedElemRestrictionGetOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) {
314 CeedCheck(rstr->GetOrientations, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
315 "Backend does not implement CeedElemRestrictionGetOrientations");
316 CeedCall(rstr->GetOrientations(rstr, mem_type, orients));
317 rstr->num_readers++;
318 return CEED_ERROR_SUCCESS;
319 }
320
321 /**
322 @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetOrientations()
323
324 @param[in] rstr `CeedElemRestriction` to restore
325 @param[in] orients Array of orientation data
326
327 @return An error code: 0 - success, otherwise - failure
328
329 @ref User
330 **/
CeedElemRestrictionRestoreOrientations(CeedElemRestriction rstr,const bool ** orients)331 int CeedElemRestrictionRestoreOrientations(CeedElemRestriction rstr, const bool **orients) {
332 *orients = NULL;
333 rstr->num_readers--;
334 return CEED_ERROR_SUCCESS;
335 }
336
337 /**
338 @brief Get read-only access to a `CeedElemRestriction` curl-conforming orientations array by @ref CeedMemType
339
340 @param[in] rstr `CeedElemRestriction` to retrieve curl-conforming orientations
341 @param[in] mem_type Memory type on which to access the array.
342 If the backend uses a different memory type, this will perform a copy (possibly cached).
343 @param[out] curl_orients Array on memory type `mem_type`
344
345 @return An error code: 0 - success, otherwise - failure
346
347 @ref User
348 **/
CeedElemRestrictionGetCurlOrientations(CeedElemRestriction rstr,CeedMemType mem_type,const CeedInt8 ** curl_orients)349 int CeedElemRestrictionGetCurlOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt8 **curl_orients) {
350 CeedCheck(rstr->GetCurlOrientations, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
351 "Backend does not implement CeedElemRestrictionGetCurlOrientations");
352 CeedCall(rstr->GetCurlOrientations(rstr, mem_type, curl_orients));
353 rstr->num_readers++;
354 return CEED_ERROR_SUCCESS;
355 }
356
357 /**
358 @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetCurlOrientations()
359
360 @param[in] rstr `CeedElemRestriction` to restore
361 @param[in] curl_orients Array of orientation data
362
363 @return An error code: 0 - success, otherwise - failure
364
365 @ref User
366 **/
CeedElemRestrictionRestoreCurlOrientations(CeedElemRestriction rstr,const CeedInt8 ** curl_orients)367 int CeedElemRestrictionRestoreCurlOrientations(CeedElemRestriction rstr, const CeedInt8 **curl_orients) {
368 *curl_orients = NULL;
369 rstr->num_readers--;
370 return CEED_ERROR_SUCCESS;
371 }
372
373 /**
374
375 @brief Get the L-vector layout of a strided `CeedElemRestriction`
376
377 @param[in] rstr `CeedElemRestriction`
378 @param[out] layout Variable to store layout array, stored as `[nodes, components, elements]`.
379 The data for node `i`, component `j`, element `k` in the E-vector is given by `i*layout[0] + j*layout[1] + k*layout[2]`.
380
381 @return An error code: 0 - success, otherwise - failure
382
383 @ref Backend
384 **/
CeedElemRestrictionGetLLayout(CeedElemRestriction rstr,CeedInt layout[3])385 int CeedElemRestrictionGetLLayout(CeedElemRestriction rstr, CeedInt layout[3]) {
386 bool has_backend_strides;
387 CeedRestrictionType rstr_type;
388
389 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
390 CeedCheck(rstr_type == CEED_RESTRICTION_STRIDED, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR,
391 "Only strided CeedElemRestriction have strided L-vector layout");
392 CeedCall(CeedElemRestrictionHasBackendStrides(rstr, &has_backend_strides));
393 if (has_backend_strides) {
394 CeedCheck(rstr->l_layout[0], CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no L-vector layout data");
395 for (CeedInt i = 0; i < 3; i++) layout[i] = rstr->l_layout[i];
396 } else {
397 CeedCall(CeedElemRestrictionGetStrides(rstr, layout));
398 }
399 return CEED_ERROR_SUCCESS;
400 }
401
402 /**
403
404 @brief Set the L-vector layout of a strided `CeedElemRestriction`
405
406 @param[in] rstr `CeedElemRestriction`
407 @param[in] layout Variable to containing layout array, stored as `[nodes, components, elements]`.
408 The data for node `i`, component `j`, element `k` in the E-vector is given by `i*layout[0] + j*layout[1] + k*layout[2]`.
409
410 @return An error code: 0 - success, otherwise - failure
411
412 @ref Backend
413 **/
CeedElemRestrictionSetLLayout(CeedElemRestriction rstr,CeedInt layout[3])414 int CeedElemRestrictionSetLLayout(CeedElemRestriction rstr, CeedInt layout[3]) {
415 CeedRestrictionType rstr_type;
416
417 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
418 CeedCheck(rstr_type == CEED_RESTRICTION_STRIDED, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR,
419 "Only strided CeedElemRestriction have strided L-vector layout");
420 for (CeedInt i = 0; i < 3; i++) rstr->l_layout[i] = layout[i];
421 return CEED_ERROR_SUCCESS;
422 }
423
424 /**
425
426 @brief Get the E-vector layout of a `CeedElemRestriction`
427
428 @param[in] rstr `CeedElemRestriction`
429 @param[out] layout Variable to store layout array, stored as `[nodes, components, elements]`.
430 The data for node `i`, component `j`, element `k` in the E-vector is given by `i*layout[0] + j*layout[1] + k*layout[2]`.
431
432 @return An error code: 0 - success, otherwise - failure
433
434 @ref Backend
435 **/
CeedElemRestrictionGetELayout(CeedElemRestriction rstr,CeedInt layout[3])436 int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
437 CeedCheck(rstr->e_layout[0], CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no E-vector layout data");
438 for (CeedInt i = 0; i < 3; i++) layout[i] = rstr->e_layout[i];
439 return CEED_ERROR_SUCCESS;
440 }
441
442 /**
443
444 @brief Set the E-vector layout of a `CeedElemRestriction`
445
446 @param[in] rstr `CeedElemRestriction`
447 @param[in] layout Variable to containing layout array, stored as `[nodes, components, elements]`.
448 The data for node `i`, component `j`, element `k` in the E-vector is given by `i*layout[0] + j*layout[1] + k*layout[2]`.
449
450 @return An error code: 0 - success, otherwise - failure
451
452 @ref Backend
453 **/
CeedElemRestrictionSetELayout(CeedElemRestriction rstr,CeedInt layout[3])454 int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
455 for (CeedInt i = 0; i < 3; i++) rstr->e_layout[i] = layout[i];
456 return CEED_ERROR_SUCCESS;
457 }
458
459 /**
460
461 @brief Get the E-vector element offset of a `CeedElemRestriction` at points
462
463 @param[in] rstr `CeedElemRestriction`
464 @param[in] elem Element number index into E-vector for
465 @param[out] elem_offset Offset for element `elem` in the E-vector.
466 The data for point `i`, component `j`, element `elem` in the E-vector is given by `i*e_layout[0] + j*e_layout[1] + elem_offset`.
467
468 @return An error code: 0 - success, otherwise - failure
469
470 @ref Backend
471 **/
CeedElemRestrictionGetAtPointsElementOffset(CeedElemRestriction rstr,CeedInt elem,CeedSize * elem_offset)472 int CeedElemRestrictionGetAtPointsElementOffset(CeedElemRestriction rstr, CeedInt elem, CeedSize *elem_offset) {
473 CeedInt num_comp;
474 CeedRestrictionType rstr_type;
475
476 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
477 CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
478 "Can only compute offset for a points CeedElemRestriction");
479
480 // Backend method
481 if (rstr->GetAtPointsElementOffset) {
482 CeedCall(rstr->GetAtPointsElementOffset(rstr, elem, elem_offset));
483 return CEED_ERROR_SUCCESS;
484 }
485
486 // Default layout (CPU)
487 *elem_offset = 0;
488 CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
489 for (CeedInt i = 0; i < elem; i++) {
490 CeedInt num_points;
491
492 CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, i, &num_points));
493 *elem_offset += num_points * num_comp;
494 }
495 return CEED_ERROR_SUCCESS;
496 }
497
498 /**
499
500 @brief Set the E-vector size of a `CeedElemRestriction` at points
501
502 @param[in,out] rstr `CeedElemRestriction`
503 @param[in] e_size New E-vector size; must be longer than the current E-vector size
504
505 @return An error code: 0 - success, otherwise - failure
506
507 @ref Backend
508 **/
CeedElemRestrictionSetAtPointsEVectorSize(CeedElemRestriction rstr,CeedSize e_size)509 int CeedElemRestrictionSetAtPointsEVectorSize(CeedElemRestriction rstr, CeedSize e_size) {
510 CeedRestrictionType rstr_type;
511
512 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
513 CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
514 "Can only compute offset for a points CeedElemRestriction");
515 CeedCheck(e_size >= rstr->e_size, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
516 "Can only increase the size of the E-vector for the CeedElemRestriction."
517 " Current size: %" CeedSize_FMT " New size: %" CeedSize_FMT,
518 rstr->e_size, e_size);
519 rstr->e_size = e_size;
520 return CEED_ERROR_SUCCESS;
521 }
522
523 /**
524 @brief Get the backend data of a `CeedElemRestriction`
525
526 @param[in] rstr `CeedElemRestriction`
527 @param[out] data Variable to store data
528
529 @return An error code: 0 - success, otherwise - failure
530
531 @ref Backend
532 **/
CeedElemRestrictionGetData(CeedElemRestriction rstr,void * data)533 int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
534 *(void **)data = rstr->data;
535 return CEED_ERROR_SUCCESS;
536 }
537
538 /**
539 @brief Set the backend data of a `CeedElemRestriction`
540
541 @param[in,out] rstr `CeedElemRestriction`
542 @param[in] data Data to set
543
544 @return An error code: 0 - success, otherwise - failure
545
546 @ref Backend
547 **/
CeedElemRestrictionSetData(CeedElemRestriction rstr,void * data)548 int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
549 rstr->data = data;
550 return CEED_ERROR_SUCCESS;
551 }
552
553 /**
554 @brief Increment the reference counter for a `CeedElemRestriction`
555
556 @param[in,out] rstr `CeedElemRestriction` to increment the reference counter
557
558 @return An error code: 0 - success, otherwise - failure
559
560 @ref Backend
561 **/
CeedElemRestrictionReference(CeedElemRestriction rstr)562 int CeedElemRestrictionReference(CeedElemRestriction rstr) {
563 CeedCall(CeedObjectReference((CeedObject)rstr));
564 return CEED_ERROR_SUCCESS;
565 }
566
567 /**
568 @brief Estimate number of FLOPs required to apply `CeedElemRestriction` in `t_mode`
569
570 @param[in] rstr `CeedElemRestriction` to estimate FLOPs for
571 @param[in] t_mode Apply restriction or transpose
572 @param[out] flops Address of variable to hold FLOPs estimate
573
574 @ref Backend
575 **/
CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr,CeedTransposeMode t_mode,CeedSize * flops)576 int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
577 CeedSize e_size, scale = 0;
578 CeedRestrictionType rstr_type;
579
580 CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &e_size));
581 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
582 if (t_mode == CEED_TRANSPOSE) {
583 switch (rstr_type) {
584 case CEED_RESTRICTION_POINTS:
585 scale = 0;
586 break;
587 case CEED_RESTRICTION_STRIDED:
588 case CEED_RESTRICTION_STANDARD:
589 scale = 1;
590 break;
591 case CEED_RESTRICTION_ORIENTED:
592 scale = 2;
593 break;
594 case CEED_RESTRICTION_CURL_ORIENTED:
595 scale = 6;
596 break;
597 }
598 } else {
599 switch (rstr_type) {
600 case CEED_RESTRICTION_STRIDED:
601 case CEED_RESTRICTION_STANDARD:
602 case CEED_RESTRICTION_POINTS:
603 scale = 0;
604 break;
605 case CEED_RESTRICTION_ORIENTED:
606 scale = 1;
607 break;
608 case CEED_RESTRICTION_CURL_ORIENTED:
609 scale = 5;
610 break;
611 }
612 }
613 *flops = e_size * scale;
614 return CEED_ERROR_SUCCESS;
615 }
616
617 /// @}
618
619 /// @cond DOXYGEN_SKIP
620 static struct CeedElemRestriction_private ceed_elemrestriction_none;
621 /// @endcond
622
623 /// ----------------------------------------------------------------------------
624 /// CeedElemRestriction Public API
625 /// ----------------------------------------------------------------------------
626 /// @addtogroup CeedElemRestrictionUser
627 /// @{
628
629 /// Indicate that the stride is determined by the backend
630 const CeedInt CEED_STRIDES_BACKEND[3] = {0};
631
632 /// Argument for @ref CeedOperatorSetField() indicating that the field does not require a `CeedElemRestriction`
633 const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
634
635 /**
636 @brief Create a `CeedElemRestriction`
637
638 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction`
639 @param[in] num_elem Number of elements described in the `offsets` array
640 @param[in] elem_size Size (number of "nodes") per element
641 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields)
642 @param[in] comp_stride Stride between components for the same L-vector "node".
643 Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`.
644 @param[in] l_size The size of the L-vector.
645 This vector may be larger than the elements and fields given by this restriction.
646 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType
647 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode
648 @param[in] offsets Array of shape `[num_elem, elem_size]`.
649 Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where 0 <= i < @a num_elem.
650 All offsets must be in the range `[0, l_size - 1]`.
651 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored
652
653 @return An error code: 0 - success, otherwise - failure
654
655 @ref User
656 **/
CeedElemRestrictionCreate(Ceed ceed,CeedInt num_elem,CeedInt elem_size,CeedInt num_comp,CeedInt comp_stride,CeedSize l_size,CeedMemType mem_type,CeedCopyMode copy_mode,const CeedInt * offsets,CeedElemRestriction * rstr)657 int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
658 CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
659 if (!ceed->ElemRestrictionCreate) {
660 Ceed delegate;
661
662 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
663 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreate");
664 CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
665 CeedCall(CeedDestroy(&delegate));
666 return CEED_ERROR_SUCCESS;
667 }
668
669 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
670 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
671 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
672 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
673
674 CeedCall(CeedCalloc(1, rstr));
675 CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, CeedElemRestrictionDestroy_Object, &(*rstr)->obj));
676 (*rstr)->num_elem = num_elem;
677 (*rstr)->elem_size = elem_size;
678 (*rstr)->num_comp = num_comp;
679 (*rstr)->comp_stride = comp_stride;
680 (*rstr)->l_size = l_size;
681 (*rstr)->e_size = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
682 (*rstr)->num_block = num_elem;
683 (*rstr)->block_size = 1;
684 (*rstr)->rstr_type = CEED_RESTRICTION_STANDARD;
685 CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
686 return CEED_ERROR_SUCCESS;
687 }
688
689 /**
690 @brief Create a `CeedElemRestriction` with orientation signs
691
692 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction`
693 @param[in] num_elem Number of elements described in the `offsets` array
694 @param[in] elem_size Size (number of "nodes") per element
695 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields)
696 @param[in] comp_stride Stride between components for the same L-vector "node".
697 Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`.
698 @param[in] l_size The size of the L-vector.
699 This vector may be larger than the elements and fields given by this restriction.
700 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType
701 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode
702 @param[in] offsets Array of shape `[num_elem, elem_size]`.
703 Row i holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`.
704 All offsets must be in the range `[0, l_size - 1]`.
705 @param[in] orients Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation
706 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored
707
708 @return An error code: 0 - success, otherwise - failure
709
710 @ref User
711 **/
CeedElemRestrictionCreateOriented(Ceed ceed,CeedInt num_elem,CeedInt elem_size,CeedInt num_comp,CeedInt comp_stride,CeedSize l_size,CeedMemType mem_type,CeedCopyMode copy_mode,const CeedInt * offsets,const bool * orients,CeedElemRestriction * rstr)712 int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
713 CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients,
714 CeedElemRestriction *rstr) {
715 if (!ceed->ElemRestrictionCreate) {
716 Ceed delegate;
717
718 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
719 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateOriented");
720 CeedCall(CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orients,
721 rstr));
722 CeedCall(CeedDestroy(&delegate));
723 return CEED_ERROR_SUCCESS;
724 }
725
726 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
727 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
728 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
729 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
730
731 CeedCall(CeedCalloc(1, rstr));
732 CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, CeedElemRestrictionDestroy_Object, &(*rstr)->obj));
733 (*rstr)->num_elem = num_elem;
734 (*rstr)->elem_size = elem_size;
735 (*rstr)->num_comp = num_comp;
736 (*rstr)->comp_stride = comp_stride;
737 (*rstr)->l_size = l_size;
738 (*rstr)->e_size = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
739 (*rstr)->num_block = num_elem;
740 (*rstr)->block_size = 1;
741 (*rstr)->rstr_type = CEED_RESTRICTION_ORIENTED;
742 CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, orients, NULL, *rstr));
743 return CEED_ERROR_SUCCESS;
744 }
745
746 /**
747 @brief Create a `CeedElemRestriction` with a general tridiagonal transformation matrix for curl-conforming elements
748
749 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction`
750 @param[in] num_elem Number of elements described in the `offsets` array
751 @param[in] elem_size Size (number of "nodes") per element
752 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields)
753 @param[in] comp_stride Stride between components for the same L-vector "node".
754 Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`.
755 @param[in] l_size The size of the L-vector.
756 This vector may be larger than the elements and fields given by this restriction.
757 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType
758 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode
759 @param[in] offsets Array of shape `[num_elem, elem_size]`.
760 Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`.
761 All offsets must be in the range `[0, l_size - 1]`.
762 @param[in] curl_orients Array of shape `[num_elem, 3 * elem_size]` representing a row-major tridiagonal matrix (`curl_orients[i * 3 * elem_size] = curl_orients[(i + 1) * 3 * elem_size - 1] = 0`, where `0 <= i < num_elem`) which is applied to the element unknowns upon restriction.
763 This orientation matrix allows for pairs of face degrees of freedom on elements for \f$H(\mathrm{curl})\f$ spaces to be coupled in the element restriction operation, which is a way to resolve face orientation issues for 3D meshes (https://dl.acm.org/doi/pdf/10.1145/3524456).
764 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored
765
766 @return An error code: 0 - success, otherwise - failure
767
768 @ref User
769 **/
CeedElemRestrictionCreateCurlOriented(Ceed ceed,CeedInt num_elem,CeedInt elem_size,CeedInt num_comp,CeedInt comp_stride,CeedSize l_size,CeedMemType mem_type,CeedCopyMode copy_mode,const CeedInt * offsets,const CeedInt8 * curl_orients,CeedElemRestriction * rstr)770 int CeedElemRestrictionCreateCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
771 CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const CeedInt8 *curl_orients,
772 CeedElemRestriction *rstr) {
773 if (!ceed->ElemRestrictionCreate) {
774 Ceed delegate;
775
776 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
777 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateCurlOriented");
778 CeedCall(CeedElemRestrictionCreateCurlOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
779 curl_orients, rstr));
780 CeedCall(CeedDestroy(&delegate));
781 return CEED_ERROR_SUCCESS;
782 }
783
784 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
785 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
786 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
787 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
788
789 CeedCall(CeedCalloc(1, rstr));
790 CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, CeedElemRestrictionDestroy_Object, &(*rstr)->obj));
791 (*rstr)->num_elem = num_elem;
792 (*rstr)->elem_size = elem_size;
793 (*rstr)->num_comp = num_comp;
794 (*rstr)->comp_stride = comp_stride;
795 (*rstr)->l_size = l_size;
796 (*rstr)->e_size = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
797 (*rstr)->num_block = num_elem;
798 (*rstr)->block_size = 1;
799 (*rstr)->rstr_type = CEED_RESTRICTION_CURL_ORIENTED;
800 CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, curl_orients, *rstr));
801 return CEED_ERROR_SUCCESS;
802 }
803
804 /**
805 @brief Create a strided `CeedElemRestriction`
806
807 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction`
808 @param[in] num_elem Number of elements described by the restriction
809 @param[in] elem_size Size (number of "nodes") per element
810 @param[in] num_comp Number of field components per interpolation "node" (1 for scalar fields)
811 @param[in] l_size The size of the L-vector.
812 This vector may be larger than the elements and fields given by this restriction.
813 @param[in] strides Array for strides between `[nodes, components, elements]`.
814 Data for node `i`, component `j`, element `k` can be found in the L-vector at index `i*strides[0] + j*strides[1] + k*strides[2]`.
815 @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend.
816 `CEED_STRIDES_BACKEND` should only be used pass data between `CeedOperator` created with the same `Ceed` backend.
817 The L-vector layout will, in general, be different between `Ceed` backends.
818 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored
819
820 @return An error code: 0 - success, otherwise - failure
821
822 @ref User
823 **/
CeedElemRestrictionCreateStrided(Ceed ceed,CeedInt num_elem,CeedInt elem_size,CeedInt num_comp,CeedSize l_size,const CeedInt strides[3],CeedElemRestriction * rstr)824 int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
825 CeedElemRestriction *rstr) {
826 if (!ceed->ElemRestrictionCreate) {
827 Ceed delegate;
828
829 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
830 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateStrided");
831 CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
832 CeedCall(CeedDestroy(&delegate));
833 return CEED_ERROR_SUCCESS;
834 }
835
836 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
837 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
838 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
839 CeedCheck(l_size >= (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, ceed, CEED_ERROR_DIMENSION,
840 "L-vector size must be at least num_elem * elem_size * num_comp. Expected: > %" CeedSize_FMT " Found: %" CeedSize_FMT,
841 (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, l_size);
842
843 CeedCall(CeedCalloc(1, rstr));
844 CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, CeedElemRestrictionDestroy_Object, &(*rstr)->obj));
845 (*rstr)->num_elem = num_elem;
846 (*rstr)->elem_size = elem_size;
847 (*rstr)->num_comp = num_comp;
848 (*rstr)->l_size = l_size;
849 (*rstr)->e_size = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
850 (*rstr)->num_block = num_elem;
851 (*rstr)->block_size = 1;
852 (*rstr)->rstr_type = CEED_RESTRICTION_STRIDED;
853 CeedCall(CeedMalloc(3, &(*rstr)->strides));
854 for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
855 CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
856 return CEED_ERROR_SUCCESS;
857 }
858
859 /**
860 @brief Create a points `CeedElemRestriction`, for restricting for restricting from a all local points to the current element in which they are located.
861
862 The offsets array is arranged as
863
864 element_0_start_index
865 element_1_start_index
866 ...
867 element_n_start_index
868 element_n_stop_index
869 element_0_point_0
870 element_0_point_1
871 ...
872
873 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction`
874 @param[in] num_elem Number of elements described in the `offsets` array
875 @param[in] num_points Number of points described in the `offsets` array
876 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields).
877 Components are assumed to be contiguous by point.
878 @param[in] l_size The size of the L-vector.
879 This vector may be larger than the elements and fields given by this restriction.
880 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType
881 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode
882 @param[in] offsets Array of size `num_elem + 1 + num_points`.
883 The first portion of the offsets array holds the ranges of indices corresponding to each element.
884 The second portion holds the indices for each element.
885 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored
886
887 @return An error code: 0 - success, otherwise - failure
888
889 @ref Backend
890 **/
CeedElemRestrictionCreateAtPoints(Ceed ceed,CeedInt num_elem,CeedInt num_points,CeedInt num_comp,CeedSize l_size,CeedMemType mem_type,CeedCopyMode copy_mode,const CeedInt * offsets,CeedElemRestriction * rstr)891 int CeedElemRestrictionCreateAtPoints(Ceed ceed, CeedInt num_elem, CeedInt num_points, CeedInt num_comp, CeedSize l_size, CeedMemType mem_type,
892 CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
893 if (!ceed->ElemRestrictionCreateAtPoints) {
894 Ceed delegate;
895
896 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
897 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateAtPoints");
898 CeedCall(CeedElemRestrictionCreateAtPoints(delegate, num_elem, num_points, num_comp, l_size, mem_type, copy_mode, offsets, rstr));
899 CeedCall(CeedDestroy(&delegate));
900 return CEED_ERROR_SUCCESS;
901 }
902
903 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
904 CeedCheck(num_points >= 0, ceed, CEED_ERROR_DIMENSION, "Number of points must be non-negative");
905 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
906 CeedCheck(l_size >= (CeedSize)num_points * num_comp, ceed, CEED_ERROR_DIMENSION,
907 "L-vector must be at least num_points * num_comp. Expected: > %" CeedSize_FMT " Found: %" CeedSize_FMT, (CeedSize)num_points * num_comp,
908 l_size);
909
910 CeedCall(CeedCalloc(1, rstr));
911 CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, CeedElemRestrictionDestroy_Object, &(*rstr)->obj));
912 (*rstr)->num_elem = num_elem;
913 (*rstr)->num_points = num_points;
914 (*rstr)->num_comp = num_comp;
915 (*rstr)->comp_stride = 1;
916 (*rstr)->l_size = l_size;
917 (*rstr)->e_size = (CeedSize)num_points * (CeedSize)num_comp;
918 (*rstr)->num_block = num_elem;
919 (*rstr)->block_size = 1;
920 (*rstr)->rstr_type = CEED_RESTRICTION_POINTS;
921 CeedCall(ceed->ElemRestrictionCreateAtPoints(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
922 return CEED_ERROR_SUCCESS;
923 }
924
925 /**
926 @brief Create a blocked `CeedElemRestriction`, typically only used by backends
927
928 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction`
929 @param[in] num_elem Number of elements described in the `offsets` array
930 @param[in] elem_size Size (number of unknowns) per element
931 @param[in] block_size Number of elements in a block
932 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields)
933 @param[in] comp_stride Stride between components for the same L-vector "node".
934 Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`.
935 @param[in] l_size The size of the L-vector.
936 This vector may be larger than the elements and fields given by this restriction.
937 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType
938 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode
939 @param[in] offsets Array of shape `[num_elem, elem_size]`.
940 Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`.
941 All offsets must be in the range `[0, l_size - 1]`.
942 The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend.
943 The default reordering is to interlace elements.
944 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored
945
946 @return An error code: 0 - success, otherwise - failure
947
948 @ref Backend
949 **/
CeedElemRestrictionCreateBlocked(Ceed ceed,CeedInt num_elem,CeedInt elem_size,CeedInt block_size,CeedInt num_comp,CeedInt comp_stride,CeedSize l_size,CeedMemType mem_type,CeedCopyMode copy_mode,const CeedInt * offsets,CeedElemRestriction * rstr)950 int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedInt comp_stride,
951 CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
952 CeedElemRestriction *rstr) {
953 CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
954
955 if (!ceed->ElemRestrictionCreateBlocked) {
956 Ceed delegate;
957
958 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
959 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlocked");
960 CeedCall(CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
961 rstr));
962 CeedCall(CeedDestroy(&delegate));
963 return CEED_ERROR_SUCCESS;
964 }
965
966 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
967 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
968 CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
969 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
970 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
971
972 CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
973 CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
974
975 CeedCall(CeedCalloc(1, rstr));
976 CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, CeedElemRestrictionDestroy_Object, &(*rstr)->obj));
977 (*rstr)->num_elem = num_elem;
978 (*rstr)->elem_size = elem_size;
979 (*rstr)->num_comp = num_comp;
980 (*rstr)->comp_stride = comp_stride;
981 (*rstr)->l_size = l_size;
982 (*rstr)->e_size = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
983 (*rstr)->num_block = num_block;
984 (*rstr)->block_size = block_size;
985 (*rstr)->rstr_type = CEED_RESTRICTION_STANDARD;
986 CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL, NULL, *rstr));
987 if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
988 return CEED_ERROR_SUCCESS;
989 }
990
991 /**
992 @brief Create a blocked oriented `CeedElemRestriction`, typically only used by backends
993
994 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction`
995 @param[in] num_elem Number of elements described in the `offsets` array.
996 @param[in] elem_size Size (number of unknowns) per element
997 @param[in] block_size Number of elements in a block
998 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields)
999 @param[in] comp_stride Stride between components for the same L-vector "node".
1000 Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`.
1001 @param[in] l_size The size of the L-vector.
1002 This vector may be larger than the elements and fields given by this restriction.
1003 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType
1004 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode
1005 @param[in] offsets Array of shape `[num_elem, elem_size]`.
1006 Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`.
1007 All offsets must be in the range `[0, l_size - 1]`.
1008 The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend.
1009 The default reordering is to interlace elements.
1010 @param[in] orients Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation.
1011 Will also be permuted and padded similarly to `offsets`.
1012 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored
1013
1014 @return An error code: 0 - success, otherwise - failure
1015
1016 @ref Backend
1017 **/
CeedElemRestrictionCreateBlockedOriented(Ceed ceed,CeedInt num_elem,CeedInt elem_size,CeedInt block_size,CeedInt num_comp,CeedInt comp_stride,CeedSize l_size,CeedMemType mem_type,CeedCopyMode copy_mode,const CeedInt * offsets,const bool * orients,CeedElemRestriction * rstr)1018 int CeedElemRestrictionCreateBlockedOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
1019 CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
1020 const CeedInt *offsets, const bool *orients, CeedElemRestriction *rstr) {
1021 bool *block_orients;
1022 CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
1023
1024 if (!ceed->ElemRestrictionCreateBlocked) {
1025 Ceed delegate;
1026
1027 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
1028 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedOriented");
1029 CeedCall(CeedElemRestrictionCreateBlockedOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode,
1030 offsets, orients, rstr));
1031 CeedCall(CeedDestroy(&delegate));
1032 return CEED_ERROR_SUCCESS;
1033 }
1034
1035 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
1036 CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
1037 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
1038 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
1039
1040 CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
1041 CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_orients));
1042 CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
1043 CeedCall(CeedPermutePadOrients(orients, block_orients, num_block, num_elem, block_size, elem_size));
1044
1045 CeedCall(CeedCalloc(1, rstr));
1046 CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, CeedElemRestrictionDestroy_Object, &(*rstr)->obj));
1047 (*rstr)->num_elem = num_elem;
1048 (*rstr)->elem_size = elem_size;
1049 (*rstr)->num_comp = num_comp;
1050 (*rstr)->comp_stride = comp_stride;
1051 (*rstr)->l_size = l_size;
1052 (*rstr)->e_size = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1053 (*rstr)->num_block = num_block;
1054 (*rstr)->block_size = block_size;
1055 (*rstr)->rstr_type = CEED_RESTRICTION_ORIENTED;
1056 CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, (const bool *)block_orients, NULL,
1057 *rstr));
1058 if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
1059 return CEED_ERROR_SUCCESS;
1060 }
1061
1062 /**
1063 @brief Create a blocked curl-oriented `CeedElemRestriction`, typically only used by backends
1064
1065 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction`
1066 @param[in] num_elem Number of elements described in the `offsets` array.
1067 @param[in] elem_size Size (number of unknowns) per element
1068 @param[in] block_size Number of elements in a block
1069 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields)
1070 @param[in] comp_stride Stride between components for the same L-vector "node".
1071 Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`.
1072 @param[in] l_size The size of the L-vector.
1073 This vector may be larger than the elements and fields given by this restriction.
1074 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType
1075 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode
1076 @param[in] offsets Array of shape `[num_elem, elem_size]`.
1077 Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`.
1078 All offsets must be in the range `[0, l_size - 1]`.
1079 The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend.
1080 The default reordering is to interlace elements.
1081 @param[in] curl_orients Array of shape `[num_elem, 3 * elem_size]` representing a row-major tridiagonal matrix (`curl_orients[i * 3 * elem_size] = curl_orients[(i + 1) * 3 * elem_size - 1] = 0`, where `0 <= i < num_elem`) which is applied to the element unknowns upon restriction.
1082 This orientation matrix allows for pairs of face degrees of freedom on elements for \f$H(\mathrm{curl})\f$ spaces to be coupled in the element restriction operation, which is a way to resolve face orientation issues for 3D meshes (https://dl.acm.org/doi/pdf/10.1145/3524456).
1083 Will also be permuted and padded similarly to offsets.
1084 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored
1085
1086 @return An error code: 0 - success, otherwise - failure
1087
1088 @ref Backend
1089 **/
CeedElemRestrictionCreateBlockedCurlOriented(Ceed ceed,CeedInt num_elem,CeedInt elem_size,CeedInt block_size,CeedInt num_comp,CeedInt comp_stride,CeedSize l_size,CeedMemType mem_type,CeedCopyMode copy_mode,const CeedInt * offsets,const CeedInt8 * curl_orients,CeedElemRestriction * rstr)1090 int CeedElemRestrictionCreateBlockedCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
1091 CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
1092 const CeedInt *offsets, const CeedInt8 *curl_orients, CeedElemRestriction *rstr) {
1093 CeedInt8 *block_curl_orients;
1094 CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
1095
1096 if (!ceed->ElemRestrictionCreateBlocked) {
1097 Ceed delegate;
1098
1099 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
1100 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedCurlOriented");
1101 CeedCall(CeedElemRestrictionCreateBlockedCurlOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type,
1102 copy_mode, offsets, curl_orients, rstr));
1103 CeedCall(CeedDestroy(&delegate));
1104 return CEED_ERROR_SUCCESS;
1105 }
1106
1107 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
1108 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
1109 CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
1110 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
1111 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
1112
1113 CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
1114 CeedCall(CeedCalloc(num_block * block_size * 3 * elem_size, &block_curl_orients));
1115 CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
1116 CeedCall(CeedPermutePadCurlOrients(curl_orients, block_curl_orients, num_block, num_elem, block_size, 3 * elem_size));
1117
1118 CeedCall(CeedCalloc(1, rstr));
1119 CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, CeedElemRestrictionDestroy_Object, &(*rstr)->obj));
1120 (*rstr)->num_elem = num_elem;
1121 (*rstr)->elem_size = elem_size;
1122 (*rstr)->num_comp = num_comp;
1123 (*rstr)->comp_stride = comp_stride;
1124 (*rstr)->l_size = l_size;
1125 (*rstr)->e_size = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1126 (*rstr)->num_block = num_block;
1127 (*rstr)->block_size = block_size;
1128 (*rstr)->rstr_type = CEED_RESTRICTION_CURL_ORIENTED;
1129 CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL,
1130 (const CeedInt8 *)block_curl_orients, *rstr));
1131 if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
1132 return CEED_ERROR_SUCCESS;
1133 }
1134
1135 /**
1136 @brief Create a blocked strided `CeedElemRestriction`, typically only used by backends
1137
1138 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction`
1139 @param[in] num_elem Number of elements described by the restriction
1140 @param[in] elem_size Size (number of "nodes") per element
1141 @param[in] block_size Number of elements in a block
1142 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields)
1143 @param[in] l_size The size of the L-vector.
1144 This vector may be larger than the elements and fields given by this restriction.
1145 @param[in] strides Array for strides between `[nodes, components, elements]`.
1146 Data for node `i`, component `j`, element `k` can be found in the L-vector at index `i*strides[0] + j*strides[1] +k*strides[2]`.
1147 @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend.
1148 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored
1149
1150 @return An error code: 0 - success, otherwise - failure
1151
1152 @ref User
1153 **/
CeedElemRestrictionCreateBlockedStrided(Ceed ceed,CeedInt num_elem,CeedInt elem_size,CeedInt block_size,CeedInt num_comp,CeedSize l_size,const CeedInt strides[3],CeedElemRestriction * rstr)1154 int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedSize l_size,
1155 const CeedInt strides[3], CeedElemRestriction *rstr) {
1156 CeedInt num_block = (num_elem / block_size) + !!(num_elem % block_size);
1157
1158 if (!ceed->ElemRestrictionCreateBlocked) {
1159 Ceed delegate;
1160
1161 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
1162 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedStrided");
1163 CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, block_size, num_comp, l_size, strides, rstr));
1164 CeedCall(CeedDestroy(&delegate));
1165 return CEED_ERROR_SUCCESS;
1166 }
1167
1168 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
1169 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
1170 CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
1171 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
1172 CeedCheck(l_size >= (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, ceed, CEED_ERROR_DIMENSION,
1173 "L-vector size must be at least num_elem * elem_size * num_comp. Expected: > %" CeedSize_FMT " Found: %" CeedSize_FMT,
1174 (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, l_size);
1175
1176 CeedCall(CeedCalloc(1, rstr));
1177 CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, CeedElemRestrictionDestroy_Object, &(*rstr)->obj));
1178 (*rstr)->num_elem = num_elem;
1179 (*rstr)->elem_size = elem_size;
1180 (*rstr)->num_comp = num_comp;
1181 (*rstr)->l_size = l_size;
1182 (*rstr)->e_size = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1183 (*rstr)->num_block = num_block;
1184 (*rstr)->block_size = block_size;
1185 (*rstr)->rstr_type = CEED_RESTRICTION_STRIDED;
1186 CeedCall(CeedMalloc(3, &(*rstr)->strides));
1187 for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
1188 CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
1189 return CEED_ERROR_SUCCESS;
1190 }
1191
1192 /**
1193 @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unsigned version.
1194
1195 Both pointers should be destroyed with @ref CeedElemRestrictionDestroy().
1196
1197 @param[in] rstr `CeedElemRestriction` to create unsigned reference to
1198 @param[in,out] rstr_unsigned Variable to store unsigned `CeedElemRestriction`
1199
1200 @return An error code: 0 - success, otherwise - failure
1201
1202 @ref User
1203 **/
CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr,CeedElemRestriction * rstr_unsigned)1204 int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) {
1205 CeedCall(CeedCalloc(1, rstr_unsigned));
1206
1207 // Copy old rstr
1208 memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private));
1209 CeedCall(CeedObjectCreate(CeedElemRestrictionReturnCeed(rstr), CeedElemRestrictionView_Object, CeedElemRestrictionDestroy_Object,
1210 &(*rstr_unsigned)->obj));
1211 (*rstr_unsigned)->strides = NULL;
1212 if (rstr->strides) {
1213 CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides));
1214 for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i];
1215 }
1216 CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_base));
1217
1218 // Override Apply
1219 (*rstr_unsigned)->Apply = rstr->ApplyUnsigned;
1220 return CEED_ERROR_SUCCESS;
1221 }
1222
1223 /**
1224 @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unoriented version.
1225
1226 Both pointers should be destroyed with @ref CeedElemRestrictionDestroy().
1227
1228 @param[in] rstr `CeedElemRestriction` to create unoriented reference to
1229 @param[in,out] rstr_unoriented Variable to store unoriented `CeedElemRestriction`
1230
1231 @return An error code: 0 - success, otherwise - failure
1232
1233 @ref User
1234 **/
CeedElemRestrictionCreateUnorientedCopy(CeedElemRestriction rstr,CeedElemRestriction * rstr_unoriented)1235 int CeedElemRestrictionCreateUnorientedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unoriented) {
1236 CeedCall(CeedCalloc(1, rstr_unoriented));
1237
1238 // Copy old rstr
1239 memcpy(*rstr_unoriented, rstr, sizeof(struct CeedElemRestriction_private));
1240 CeedCall(CeedObjectCreate(CeedElemRestrictionReturnCeed(rstr), CeedElemRestrictionView_Object, CeedElemRestrictionDestroy_Object,
1241 &(*rstr_unoriented)->obj));
1242 (*rstr_unoriented)->strides = NULL;
1243 if (rstr->strides) {
1244 CeedCall(CeedMalloc(3, &(*rstr_unoriented)->strides));
1245 for (CeedInt i = 0; i < 3; i++) (*rstr_unoriented)->strides[i] = rstr->strides[i];
1246 }
1247 CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unoriented)->rstr_base));
1248
1249 // Override Apply
1250 (*rstr_unoriented)->Apply = rstr->ApplyUnoriented;
1251 return CEED_ERROR_SUCCESS;
1252 }
1253
1254 /**
1255 @brief Copy the pointer to a `CeedElemRestriction`.
1256
1257 Both pointers should be destroyed with @ref CeedElemRestrictionDestroy().
1258
1259 Note: If the value of `*rstr_copy` passed into this function is non-`NULL`, then it is assumed that `*rstr_copy` is a pointer to a `CeedElemRestriction`.
1260 This `CeedElemRestriction` will be destroyed if `*rstr_copy` is the only reference to this `CeedElemRestriction`.
1261
1262 @param[in] rstr `CeedElemRestriction` to copy reference to
1263 @param[in,out] rstr_copy Variable to store copied reference
1264
1265 @return An error code: 0 - success, otherwise - failure
1266
1267 @ref User
1268 **/
CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr,CeedElemRestriction * rstr_copy)1269 int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
1270 if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr));
1271 CeedCall(CeedElemRestrictionDestroy(rstr_copy));
1272 *rstr_copy = rstr;
1273 return CEED_ERROR_SUCCESS;
1274 }
1275
1276 /**
1277 @brief Create `CeedVector` associated with a `CeedElemRestriction`
1278
1279 @param[in] rstr `CeedElemRestriction`
1280 @param[out] l_vec The address of the L-vector to be created, or `NULL`
1281 @param[out] e_vec The address of the E-vector to be created, or `NULL`
1282
1283 @return An error code: 0 - success, otherwise - failure
1284
1285 @ref User
1286 **/
CeedElemRestrictionCreateVector(CeedElemRestriction rstr,CeedVector * l_vec,CeedVector * e_vec)1287 int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
1288 CeedSize e_size, l_size;
1289 Ceed ceed;
1290
1291 CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
1292 CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &l_size));
1293 CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &e_size));
1294 if (l_vec) CeedCall(CeedVectorCreate(ceed, l_size, l_vec));
1295 if (e_vec) CeedCall(CeedVectorCreate(ceed, e_size, e_vec));
1296 CeedCall(CeedDestroy(&ceed));
1297 return CEED_ERROR_SUCCESS;
1298 }
1299
1300 /**
1301 @brief Restrict an L-vector to an E-vector or apply its transpose
1302
1303 @param[in] rstr `CeedElemRestriction`
1304 @param[in] t_mode Apply restriction or transpose
1305 @param[in] u Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE)
1306 @param[out] ru Output vector (of shape `[num_elem * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE).
1307 Ordering of the e-vector is decided by the backend.
1308 @param[in] request Request or @ref CEED_REQUEST_IMMEDIATE
1309
1310 @return An error code: 0 - success, otherwise - failure
1311
1312 @ref User
1313 **/
CeedElemRestrictionApply(CeedElemRestriction rstr,CeedTransposeMode t_mode,CeedVector u,CeedVector ru,CeedRequest * request)1314 int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
1315 CeedSize min_u_len, min_ru_len, len;
1316 CeedInt num_elem;
1317
1318 if (t_mode == CEED_NOTRANSPOSE) {
1319 CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &min_ru_len));
1320 CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len));
1321 } else {
1322 CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &min_u_len));
1323 CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len));
1324 }
1325 CeedCall(CeedVectorGetLength(u, &len));
1326 CeedCheck(min_u_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1327 "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_ru_len,
1328 min_u_len);
1329 CeedCall(CeedVectorGetLength(ru, &len));
1330 CeedCheck(min_ru_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1331 "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_u_len,
1332 min_ru_len);
1333 CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
1334 if (num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
1335 return CEED_ERROR_SUCCESS;
1336 }
1337
1338 /**
1339 @brief Restrict an L-vector of points to a single element or apply its transpose
1340
1341 @param[in] rstr `CeedElemRestriction`
1342 @param[in] elem Element number in range `[0, num_elem)`
1343 @param[in] t_mode Apply restriction or transpose
1344 @param[in] u Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE)
1345 @param[out] ru Output vector (of shape [`num_points * num_comp]` when `t_mode` = @ref CEED_NOTRANSPOSE).
1346 Ordering of the e-vector is decided by the backend.
1347 @param[in] request Request or @ref CEED_REQUEST_IMMEDIATE
1348
1349 @return An error code: 0 - success, otherwise - failure
1350
1351 @ref User
1352 **/
CeedElemRestrictionApplyAtPointsInElement(CeedElemRestriction rstr,CeedInt elem,CeedTransposeMode t_mode,CeedVector u,CeedVector ru,CeedRequest * request)1353 int CeedElemRestrictionApplyAtPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
1354 CeedRequest *request) {
1355 CeedSize min_u_len, min_ru_len, len;
1356 CeedInt num_elem;
1357
1358 CeedCheck(rstr->ApplyAtPointsInElement, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
1359 "Backend does not implement CeedElemRestrictionApplyAtPointsInElement");
1360
1361 if (t_mode == CEED_NOTRANSPOSE) {
1362 CeedInt num_points, num_comp;
1363
1364 CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len));
1365 CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &num_points));
1366 CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1367 min_ru_len = (CeedSize)num_points * (CeedSize)num_comp;
1368 } else {
1369 CeedInt num_points, num_comp;
1370
1371 CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &num_points));
1372 CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1373 min_u_len = (CeedSize)num_points * (CeedSize)num_comp;
1374 CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len));
1375 }
1376 CeedCall(CeedVectorGetLength(u, &len));
1377 CeedCheck(min_u_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1378 "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT
1379 ") for element %" CeedInt_FMT,
1380 len, min_ru_len, min_u_len, elem);
1381 CeedCall(CeedVectorGetLength(ru, &len));
1382 CeedCheck(min_ru_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1383 "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT
1384 ") for element %" CeedInt_FMT,
1385 len, min_ru_len, min_u_len, elem);
1386 CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
1387 CeedCheck(elem < num_elem, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1388 "Cannot retrieve element %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", elem, elem, num_elem);
1389 if (num_elem > 0) CeedCall(rstr->ApplyAtPointsInElement(rstr, elem, t_mode, u, ru, request));
1390 return CEED_ERROR_SUCCESS;
1391 }
1392
1393 /**
1394 @brief Restrict an L-vector to a block of an E-vector or apply its transpose
1395
1396 @param[in] rstr `CeedElemRestriction`
1397 @param[in] block Block number to restrict to/from, i.e. `block = 0` will handle elements `[0 : block_size]` and `block = 3` will handle elements `[3*block_size : 4*block_size]`
1398 @param[in] t_mode Apply restriction or transpose
1399 @param[in] u Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE)
1400 @param[out] ru Output vector (of shape `[block_size * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE).
1401 Ordering of the e-vector is decided by the backend.
1402 @param[in] request Request or @ref CEED_REQUEST_IMMEDIATE
1403
1404 @return An error code: 0 - success, otherwise - failure
1405
1406 @ref Backend
1407 **/
CeedElemRestrictionApplyBlock(CeedElemRestriction rstr,CeedInt block,CeedTransposeMode t_mode,CeedVector u,CeedVector ru,CeedRequest * request)1408 int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
1409 CeedRequest *request) {
1410 CeedSize min_u_len, min_ru_len, len;
1411 CeedInt block_size, num_elem;
1412
1413 CeedCheck(rstr->ApplyBlock, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
1414 "Backend does not implement CeedElemRestrictionApplyBlock");
1415
1416 CeedCall(CeedElemRestrictionGetBlockSize(rstr, &block_size));
1417 if (t_mode == CEED_NOTRANSPOSE) {
1418 CeedInt elem_size, num_comp;
1419
1420 CeedCall(CeedElemRestrictionGetElementSize(rstr, &elem_size));
1421 CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1422 CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len));
1423 min_ru_len = (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1424 } else {
1425 CeedInt elem_size, num_comp;
1426
1427 CeedCall(CeedElemRestrictionGetElementSize(rstr, &elem_size));
1428 CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1429 CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len));
1430 min_u_len = (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1431 }
1432 CeedCall(CeedVectorGetLength(u, &len));
1433 CeedCheck(min_u_len == len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1434 "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_u_len,
1435 min_ru_len);
1436 CeedCall(CeedVectorGetLength(ru, &len));
1437 CeedCheck(min_ru_len == len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1438 "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_ru_len,
1439 min_u_len);
1440 CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
1441 CeedCheck(block_size * block <= num_elem, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1442 "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, block_size * block,
1443 num_elem);
1444 CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
1445 return CEED_ERROR_SUCCESS;
1446 }
1447
1448 /**
1449 @brief Get the `Ceed` associated with a `CeedElemRestriction`
1450
1451 @param[in] rstr `CeedElemRestriction`
1452 @param[out] ceed Variable to store `Ceed`
1453
1454 @return An error code: 0 - success, otherwise - failure
1455
1456 @ref Advanced
1457 **/
CeedElemRestrictionGetCeed(CeedElemRestriction rstr,Ceed * ceed)1458 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
1459 CeedCall(CeedObjectGetCeed((CeedObject)rstr, ceed));
1460 return CEED_ERROR_SUCCESS;
1461 }
1462
1463 /**
1464 @brief Return the `Ceed` associated with a `CeedElemRestriction`
1465
1466 @param[in] rstr `CeedElemRestriction`
1467
1468 @return `Ceed` associated with the `rstr`
1469
1470 @ref Advanced
1471 **/
CeedElemRestrictionReturnCeed(CeedElemRestriction rstr)1472 Ceed CeedElemRestrictionReturnCeed(CeedElemRestriction rstr) { return CeedObjectReturnCeed((CeedObject)rstr); }
1473
1474 /**
1475 @brief Get the L-vector component stride
1476
1477 @param[in] rstr `CeedElemRestriction`
1478 @param[out] comp_stride Variable to store component stride
1479
1480 @return An error code: 0 - success, otherwise - failure
1481
1482 @ref Advanced
1483 **/
CeedElemRestrictionGetCompStride(CeedElemRestriction rstr,CeedInt * comp_stride)1484 int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
1485 *comp_stride = rstr->comp_stride;
1486 return CEED_ERROR_SUCCESS;
1487 }
1488
1489 /**
1490 @brief Get the total number of elements in the range of a `CeedElemRestriction`
1491
1492 @param[in] rstr `CeedElemRestriction`
1493 @param[out] num_elem Variable to store number of elements
1494
1495 @return An error code: 0 - success, otherwise - failure
1496
1497 @ref Advanced
1498 **/
CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,CeedInt * num_elem)1499 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
1500 *num_elem = rstr->num_elem;
1501 return CEED_ERROR_SUCCESS;
1502 }
1503
1504 /**
1505 @brief Get the size of elements in the `CeedElemRestriction`
1506
1507 @param[in] rstr `CeedElemRestriction`
1508 @param[out] elem_size Variable to store size of elements
1509
1510 @return An error code: 0 - success, otherwise - failure
1511
1512 @ref Advanced
1513 **/
CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,CeedInt * elem_size)1514 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
1515 *elem_size = rstr->elem_size;
1516 return CEED_ERROR_SUCCESS;
1517 }
1518
1519 /**
1520
1521 @brief Get the number of points in the offsets array for a points `CeedElemRestriction`
1522
1523 @param[in] rstr `CeedElemRestriction`
1524 @param[out] num_points The number of points in the offsets array
1525
1526 @return An error code: 0 - success, otherwise - failure
1527
1528 @ref User
1529 **/
CeedElemRestrictionGetNumPoints(CeedElemRestriction rstr,CeedInt * num_points)1530 int CeedElemRestrictionGetNumPoints(CeedElemRestriction rstr, CeedInt *num_points) {
1531 CeedRestrictionType rstr_type;
1532
1533 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
1534 CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
1535 "Can only retrieve the number of points for a points CeedElemRestriction");
1536
1537 *num_points = rstr->num_points;
1538 return CEED_ERROR_SUCCESS;
1539 }
1540
1541 /**
1542
1543 @brief Get the number of points in an element of a `CeedElemRestriction` at points
1544
1545 @param[in] rstr `CeedElemRestriction`
1546 @param[in] elem Index number of element to retrieve the number of points for
1547 @param[out] num_points The number of points in the element at index elem
1548
1549 @return An error code: 0 - success, otherwise - failure
1550
1551 @ref User
1552 **/
CeedElemRestrictionGetNumPointsInElement(CeedElemRestriction rstr,CeedInt elem,CeedInt * num_points)1553 int CeedElemRestrictionGetNumPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedInt *num_points) {
1554 CeedRestrictionType rstr_type;
1555 const CeedInt *offsets;
1556
1557 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
1558 CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
1559 "Can only retrieve the number of points for a points CeedElemRestriction");
1560
1561 CeedCall(CeedElemRestrictionGetOffsets(rstr, CEED_MEM_HOST, &offsets));
1562 *num_points = offsets[elem + 1] - offsets[elem];
1563 CeedCall(CeedElemRestrictionRestoreOffsets(rstr, &offsets));
1564 return CEED_ERROR_SUCCESS;
1565 }
1566
1567 /**
1568 @brief Get the minimum and/or maximum number of points in an element for a `CeedElemRestriction` at points
1569
1570 @param[in] rstr `CeedElemRestriction`
1571 @param[out] min_points Variable to minimum number of points in an element, or `NULL`
1572 @param[out] max_points Variable to maximum number of points in an element, or `NULL`
1573
1574 @return An error code: 0 - success, otherwise - failure
1575
1576 @ref Advanced
1577 **/
CeedElemRestrictionGetMinMaxPointsInElement(CeedElemRestriction rstr,CeedInt * min_points,CeedInt * max_points)1578 int CeedElemRestrictionGetMinMaxPointsInElement(CeedElemRestriction rstr, CeedInt *min_points, CeedInt *max_points) {
1579 CeedInt num_elem, num_points;
1580 CeedRestrictionType rstr_type;
1581
1582 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
1583 CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
1584 "Cannot compute min/max points for a CeedElemRestriction that does not use points");
1585
1586 CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
1587
1588 // Exit early if there are no elements
1589 if (num_elem == 0) {
1590 if (min_points) *min_points = 0;
1591 if (max_points) *max_points = 0;
1592 return CEED_ERROR_SUCCESS;
1593 }
1594
1595 // Initialize to the number of points in the first element
1596 CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, 0, &num_points));
1597 if (min_points) *min_points = num_points;
1598 if (max_points) *max_points = num_points;
1599 for (CeedInt e = 1; e < num_elem; e++) {
1600 CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, e, &num_points));
1601 if (min_points) *min_points = CeedIntMin(num_points, *min_points);
1602 if (max_points) *max_points = CeedIntMax(num_points, *max_points);
1603 }
1604 return CEED_ERROR_SUCCESS;
1605 }
1606
1607 /**
1608 @brief Get the maximum number of points in an element for a `CeedElemRestriction` at points
1609
1610 @param[in] rstr `CeedElemRestriction`
1611 @param[out] max_points Variable to store maximum number of points in an element
1612
1613 @return An error code: 0 - success, otherwise - failure
1614
1615 @ref User
1616
1617 @see CeedElemRestrictionGetMinMaxPointsInElement()
1618 **/
CeedElemRestrictionGetMaxPointsInElement(CeedElemRestriction rstr,CeedInt * max_points)1619 int CeedElemRestrictionGetMaxPointsInElement(CeedElemRestriction rstr, CeedInt *max_points) {
1620 return CeedElemRestrictionGetMinMaxPointsInElement(rstr, NULL, max_points);
1621 }
1622
1623 /**
1624 @brief Get the minimum number of points in an element for a `CeedElemRestriction` at points
1625
1626 @param[in] rstr `CeedElemRestriction`
1627 @param[out] min_points Variable to store minimum number of points in an element
1628
1629 @return An error code: 0 - success, otherwise - failure
1630
1631 @ref User
1632
1633 @see CeedElemRestrictionGetMinMaxPointsInElement()
1634 **/
CeedElemRestrictionGetMinPointsInElement(CeedElemRestriction rstr,CeedInt * min_points)1635 int CeedElemRestrictionGetMinPointsInElement(CeedElemRestriction rstr, CeedInt *min_points) {
1636 return CeedElemRestrictionGetMinMaxPointsInElement(rstr, min_points, NULL);
1637 }
1638
1639 /**
1640 @brief Get the size of the l-vector for a `CeedElemRestriction`
1641
1642 @param[in] rstr `CeedElemRestriction`
1643 @param[out] l_size Variable to store l-vector size
1644
1645 @return An error code: 0 - success, otherwise - failure
1646
1647 @ref Advanced
1648 **/
CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr,CeedSize * l_size)1649 int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
1650 *l_size = rstr->l_size;
1651 return CEED_ERROR_SUCCESS;
1652 }
1653
1654 /**
1655 @brief Get the size of the e-vector for a `CeedElemRestriction`
1656
1657 @param[in] rstr `CeedElemRestriction`
1658 @param[out] e_size Variable to store e-vector size
1659
1660 @return An error code: 0 - success, otherwise - failure
1661
1662 @ref Advanced
1663 **/
CeedElemRestrictionGetEVectorSize(CeedElemRestriction rstr,CeedSize * e_size)1664 int CeedElemRestrictionGetEVectorSize(CeedElemRestriction rstr, CeedSize *e_size) {
1665 *e_size = rstr->e_size;
1666 return CEED_ERROR_SUCCESS;
1667 }
1668
1669 /**
1670 @brief Get the number of components in the elements of a `CeedElemRestriction`
1671
1672 @param[in] rstr `CeedElemRestriction`
1673 @param[out] num_comp Variable to store number of components
1674
1675 @return An error code: 0 - success, otherwise - failure
1676
1677 @ref Advanced
1678 **/
CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,CeedInt * num_comp)1679 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
1680 *num_comp = rstr->num_comp;
1681 return CEED_ERROR_SUCCESS;
1682 }
1683
1684 /**
1685 @brief Get the number of blocks in a `CeedElemRestriction`
1686
1687 @param[in] rstr `CeedElemRestriction`
1688 @param[out] num_block Variable to store number of blocks
1689
1690 @return An error code: 0 - success, otherwise - failure
1691
1692 @ref Advanced
1693 **/
CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,CeedInt * num_block)1694 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
1695 *num_block = rstr->num_block;
1696 return CEED_ERROR_SUCCESS;
1697 }
1698
1699 /**
1700 @brief Get the size of blocks in the `CeedElemRestriction`
1701
1702 @param[in] rstr `CeedElemRestriction`
1703 @param[out] block_size Variable to store size of blocks
1704
1705 @return An error code: 0 - success, otherwise - failure
1706
1707 @ref Advanced
1708 **/
CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,CeedInt * block_size)1709 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *block_size) {
1710 *block_size = rstr->block_size;
1711 return CEED_ERROR_SUCCESS;
1712 }
1713
1714 /**
1715 @brief Get the multiplicity of nodes in a `CeedElemRestriction`
1716
1717 @param[in] rstr `CeedElemRestriction`
1718 @param[out] mult Vector to store multiplicity (of size `l_size`)
1719
1720 @return An error code: 0 - success, otherwise - failure
1721
1722 @ref User
1723 **/
CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,CeedVector mult)1724 int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
1725 CeedVector e_vec;
1726
1727 // Create e_vec to hold intermediate computation in E^T (E 1)
1728 CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
1729
1730 // Compute e_vec = E * 1
1731 CeedCall(CeedVectorSetValue(mult, 1.0));
1732 CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
1733 // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
1734 CeedCall(CeedVectorSetValue(mult, 0.0));
1735 CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
1736 // Cleanup
1737 CeedCall(CeedVectorDestroy(&e_vec));
1738 return CEED_ERROR_SUCCESS;
1739 }
1740
1741 /**
1742 @brief Set the number of tabs to indent for @ref CeedElemRestrictionView() output
1743
1744 @param[in] rstr `CeedElemRestriction` to set the number of view tabs
1745 @param[in] num_tabs Number of view tabs to set
1746
1747 @return Error code: 0 - success, otherwise - failure
1748
1749 @ref User
1750 **/
CeedElemRestrictionSetNumViewTabs(CeedElemRestriction rstr,CeedInt num_tabs)1751 int CeedElemRestrictionSetNumViewTabs(CeedElemRestriction rstr, CeedInt num_tabs) {
1752 CeedCall(CeedObjectSetNumViewTabs((CeedObject)rstr, num_tabs));
1753 return CEED_ERROR_SUCCESS;
1754 }
1755
1756 /**
1757 @brief Get the number of tabs to indent for @ref CeedElemRestrictionView() output
1758
1759 @param[in] rstr `CeedElemRestriction` to get the number of view tabs
1760 @param[out] num_tabs Number of view tabs
1761
1762 @return Error code: 0 - success, otherwise - failure
1763
1764 @ref User
1765 **/
CeedElemRestrictionGetNumViewTabs(CeedElemRestriction rstr,CeedInt * num_tabs)1766 int CeedElemRestrictionGetNumViewTabs(CeedElemRestriction rstr, CeedInt *num_tabs) {
1767 CeedCall(CeedObjectGetNumViewTabs((CeedObject)rstr, num_tabs));
1768 return CEED_ERROR_SUCCESS;
1769 }
1770
1771 /**
1772 @brief View a `CeedElemRestriction`
1773
1774 @param[in] rstr `CeedElemRestriction` to view
1775 @param[in] stream Stream to write; typically `stdout` or a file
1776
1777 @return Error code: 0 - success, otherwise - failure
1778
1779 @ref User
1780 **/
CeedElemRestrictionView(CeedElemRestriction rstr,FILE * stream)1781 int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
1782 char *tabs = NULL;
1783 CeedRestrictionType rstr_type;
1784
1785 {
1786 CeedInt num_tabs = 0;
1787
1788 CeedCall(CeedElemRestrictionGetNumViewTabs(rstr, &num_tabs));
1789 CeedCall(CeedCalloc(CEED_TAB_WIDTH * num_tabs + 1, &tabs));
1790 for (CeedInt i = 0; i < CEED_TAB_WIDTH * num_tabs; i++) tabs[i] = ' ';
1791 }
1792
1793 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
1794 if (rstr_type == CEED_RESTRICTION_POINTS) {
1795 CeedInt max_points;
1796
1797 CeedCall(CeedElemRestrictionGetMaxPointsInElement(rstr, &max_points));
1798 fprintf(stream,
1799 "%sCeedElemRestriction at points from (%" CeedSize_FMT ", %" CeedInt_FMT ") to %" CeedInt_FMT " elements with a maximum of %" CeedInt_FMT
1800 " points on an element\n",
1801 tabs, rstr->l_size, rstr->num_comp, rstr->num_elem, max_points);
1802 } else {
1803 char strides_str[500];
1804
1805 if (rstr->strides) {
1806 sprintf(strides_str, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
1807 } else {
1808 sprintf(strides_str, "%" CeedInt_FMT, rstr->comp_stride);
1809 }
1810 fprintf(stream,
1811 "%s%sCeedElemRestriction from (%" CeedSize_FMT ", %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT
1812 " nodes each and %s %s\n",
1813 tabs, rstr->block_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
1814 rstr->strides ? "strides" : "component stride", strides_str);
1815 }
1816 CeedCall(CeedFree(&tabs));
1817 return CEED_ERROR_SUCCESS;
1818 }
1819
1820 /**
1821 @brief Destroy a `CeedElemRestriction`
1822
1823 @param[in,out] rstr `CeedElemRestriction` to destroy
1824
1825 @return An error code: 0 - success, otherwise - failure
1826
1827 @ref User
1828 **/
CeedElemRestrictionDestroy(CeedElemRestriction * rstr)1829 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1830 if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || CeedObjectDereference((CeedObject)*rstr) > 0) {
1831 *rstr = NULL;
1832 return CEED_ERROR_SUCCESS;
1833 }
1834 CeedCheck((*rstr)->num_readers == 0, CeedElemRestrictionReturnCeed(*rstr), CEED_ERROR_ACCESS,
1835 "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
1836
1837 // Only destroy backend data once between rstr and unsigned copy
1838 if ((*rstr)->rstr_base) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_base));
1839 else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
1840
1841 CeedCall(CeedFree(&(*rstr)->strides));
1842 CeedCall(CeedObjectDestroy_Private(&(*rstr)->obj));
1843 CeedCall(CeedFree(rstr));
1844 return CEED_ERROR_SUCCESS;
1845 }
1846
1847 /// @}
1848