xref: /libCEED/rust/libceed-sys/c-src/backends/ref/ceed-ref-restriction.c (revision fc0567d9dd43c4a8f0744c44d73ac6beb4777ae6)
1 // Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC.
2 // Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707.
3 // All Rights reserved. See files LICENSE and NOTICE for details.
4 //
5 // This file is part of CEED, a collection of benchmarks, miniapps, software
6 // libraries and APIs for efficient high-order finite element and spectral
7 // element discretizations for exascale applications. For more information and
8 // source code availability see http://github.com/ceed.
9 //
10 // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11 // a collaborative effort of two U.S. Department of Energy organizations (Office
12 // of Science and the National Nuclear Security Administration) responsible for
13 // the planning and preparation of a capable exascale ecosystem, including
14 // software, applications, hardware, advanced system engineering and early
15 // testbed platforms, in support of the nation's exascale computing imperative.
16 
17 #include <ceed/ceed.h>
18 #include <ceed/backend.h>
19 #include <stdbool.h>
20 #include <string.h>
21 #include "ceed-ref.h"
22 
23 //------------------------------------------------------------------------------
24 // Core ElemRestriction Apply Code
25 //------------------------------------------------------------------------------
26 static inline int CeedElemRestrictionApply_Ref_Core(CeedElemRestriction r,
27     const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
28     CeedInt start, CeedInt stop, CeedTransposeMode t_mode, CeedVector u,
29     CeedVector v, CeedRequest *request) {
30   int ierr;
31   CeedElemRestriction_Ref *impl;
32   ierr = CeedElemRestrictionGetData(r, &impl); CeedChkBackend(ierr);
33   const CeedScalar *uu;
34   CeedScalar *vv;
35   CeedInt num_elem, elem_size, v_offset;
36   ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChkBackend(ierr);
37   ierr = CeedElemRestrictionGetElementSize(r, &elem_size); CeedChkBackend(ierr);
38   v_offset = start*blk_size*elem_size*num_comp;
39 
40   ierr = CeedVectorGetArrayRead(u, CEED_MEM_HOST, &uu); CeedChkBackend(ierr);
41   if (t_mode == CEED_TRANSPOSE) {
42     // Sum into for transpose mode, e-vec to l-vec
43     ierr = CeedVectorGetArray(v, CEED_MEM_HOST, &vv); CeedChkBackend(ierr);
44   } else {
45     // Overwrite for notranspose mode, l-vec to e-vec
46     ierr = CeedVectorGetArrayWrite(v, CEED_MEM_HOST, &vv); CeedChkBackend(ierr);
47   }
48   // Restriction from L-vector to E-vector
49   // Perform: v = r * u
50   if (t_mode == CEED_NOTRANSPOSE) {
51     // No offsets provided, Identity Restriction
52     if (!impl->offsets) {
53       bool has_backend_strides;
54       ierr = CeedElemRestrictionHasBackendStrides(r, &has_backend_strides);
55       CeedChkBackend(ierr);
56       if (has_backend_strides) {
57         // CPU backend strides are {1, elem_size, elem_size*num_comp}
58         // This if branch is left separate to allow better inlining
59         for (CeedInt e = start*blk_size; e < stop*blk_size; e+=blk_size)
60           CeedPragmaSIMD
61           for (CeedInt k = 0; k < num_comp; k++)
62             CeedPragmaSIMD
63             for (CeedInt n = 0; n < elem_size; n++)
64               CeedPragmaSIMD
65               for (CeedInt j = 0; j < blk_size; j++)
66                 vv[e*elem_size*num_comp + (k*elem_size+n)*blk_size + j - v_offset]
67                   = uu[n + k*elem_size +
68                          CeedIntMin(e+j, num_elem-1)*elem_size*num_comp];
69       } else {
70         // User provided strides
71         CeedInt strides[3];
72         ierr = CeedElemRestrictionGetStrides(r, &strides); CeedChkBackend(ierr);
73         for (CeedInt e = start*blk_size; e < stop*blk_size; e+=blk_size)
74           CeedPragmaSIMD
75           for (CeedInt k = 0; k < num_comp; k++)
76             CeedPragmaSIMD
77             for (CeedInt n = 0; n < elem_size; n++)
78               CeedPragmaSIMD
79               for (CeedInt j = 0; j < blk_size; j++)
80                 vv[e*elem_size*num_comp + (k*elem_size+n)*blk_size + j - v_offset]
81                   = uu[n*strides[0] + k*strides[1] +
82                                     CeedIntMin(e+j, num_elem-1)*strides[2]];
83       }
84     } else {
85       // Offsets provided, standard or blocked restriction
86       // vv has shape [elem_size, num_comp, num_elem], row-major
87       // uu has shape [nnodes, num_comp]
88       for (CeedInt e = start*blk_size; e < stop*blk_size; e+=blk_size)
89         CeedPragmaSIMD
90         for (CeedInt k = 0; k < num_comp; k++)
91           CeedPragmaSIMD
92           for (CeedInt i = 0; i < elem_size*blk_size; i++)
93             vv[elem_size*(k*blk_size+num_comp*e) + i - v_offset]
94               = uu[impl->offsets[i+elem_size*e] + k*comp_stride] *
95                 (impl->orient && impl->orient[i+elem_size*e] ? -1. : 1.);
96     }
97   } else {
98     // Restriction from E-vector to L-vector
99     // Performing v += r^T * u
100     // No offsets provided, Identity Restriction
101     if (!impl->offsets) {
102       bool has_backend_strides;
103       ierr = CeedElemRestrictionHasBackendStrides(r, &has_backend_strides);
104       CeedChkBackend(ierr);
105       if (has_backend_strides) {
106         // CPU backend strides are {1, elem_size, elem_size*num_comp}
107         // This if brach is left separate to allow better inlining
108         for (CeedInt e = start*blk_size; e < stop*blk_size; e+=blk_size)
109           CeedPragmaSIMD
110           for (CeedInt k = 0; k < num_comp; k++)
111             CeedPragmaSIMD
112             for (CeedInt n = 0; n < elem_size; n++)
113               CeedPragmaSIMD
114               for (CeedInt j = 0; j < CeedIntMin(blk_size, num_elem-e); j++)
115                 vv[n + k*elem_size + (e+j)*elem_size*num_comp]
116                 += uu[e*elem_size*num_comp + (k*elem_size+n)*blk_size + j - v_offset];
117       } else {
118         // User provided strides
119         CeedInt strides[3];
120         ierr = CeedElemRestrictionGetStrides(r, &strides); CeedChkBackend(ierr);
121         for (CeedInt e = start*blk_size; e < stop*blk_size; e+=blk_size)
122           CeedPragmaSIMD
123           for (CeedInt k = 0; k < num_comp; k++)
124             CeedPragmaSIMD
125             for (CeedInt n = 0; n < elem_size; n++)
126               CeedPragmaSIMD
127               for (CeedInt j = 0; j < CeedIntMin(blk_size, num_elem-e); j++)
128                 vv[n*strides[0] + k*strides[1] + (e+j)*strides[2]]
129                 += uu[e*elem_size*num_comp + (k*elem_size+n)*blk_size + j - v_offset];
130       }
131     } else {
132       // Offsets provided, standard or blocked restriction
133       // uu has shape [elem_size, num_comp, num_elem]
134       // vv has shape [nnodes, num_comp]
135       for (CeedInt e = start*blk_size; e < stop*blk_size; e+=blk_size)
136         for (CeedInt k = 0; k < num_comp; k++)
137           for (CeedInt i = 0; i < elem_size*blk_size; i+=blk_size)
138             // Iteration bound set to discard padding elements
139             for (CeedInt j = i; j < i+CeedIntMin(blk_size, num_elem-e); j++)
140               vv[impl->offsets[j+e*elem_size] + k*comp_stride]
141               += uu[elem_size*(k*blk_size+num_comp*e) + j - v_offset] *
142                  (impl->orient && impl->orient[j+e*elem_size] ? -1. : 1.);
143     }
144   }
145   ierr = CeedVectorRestoreArrayRead(u, &uu); CeedChkBackend(ierr);
146   ierr = CeedVectorRestoreArray(v, &vv); CeedChkBackend(ierr);
147   if (request != CEED_REQUEST_IMMEDIATE && request != CEED_REQUEST_ORDERED)
148     *request = NULL;
149   return CEED_ERROR_SUCCESS;
150 }
151 
152 //------------------------------------------------------------------------------
153 // ElemRestriction Apply - Common Sizes
154 //------------------------------------------------------------------------------
155 static int CeedElemRestrictionApply_Ref_110(CeedElemRestriction r,
156     const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
157     CeedInt start, CeedInt stop, CeedTransposeMode t_mode, CeedVector u,
158     CeedVector v, CeedRequest *request) {
159   return CeedElemRestrictionApply_Ref_Core(r, 1, 1, comp_stride, start, stop,
160          t_mode, u, v, request);
161 }
162 
163 static int CeedElemRestrictionApply_Ref_111(CeedElemRestriction r,
164     const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
165     CeedInt start, CeedInt stop, CeedTransposeMode t_mode, CeedVector u,
166     CeedVector v, CeedRequest *request) {
167   return CeedElemRestrictionApply_Ref_Core(r, 1, 1, 1, start, stop, t_mode,
168          u, v, request);
169 }
170 
171 static int CeedElemRestrictionApply_Ref_180(CeedElemRestriction r,
172     const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
173     CeedInt start, CeedInt stop, CeedTransposeMode t_mode, CeedVector u,
174     CeedVector v, CeedRequest *request) {
175   return CeedElemRestrictionApply_Ref_Core(r, 1, 8, comp_stride, start, stop,
176          t_mode, u, v, request);
177 }
178 
179 static int CeedElemRestrictionApply_Ref_181(CeedElemRestriction r,
180     const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
181     CeedInt start, CeedInt stop, CeedTransposeMode t_mode, CeedVector u,
182     CeedVector v, CeedRequest *request) {
183   return CeedElemRestrictionApply_Ref_Core(r, 1, 8, 1, start, stop, t_mode,
184          u, v, request);
185 }
186 
187 static int CeedElemRestrictionApply_Ref_310(CeedElemRestriction r,
188     const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
189     CeedInt start, CeedInt stop, CeedTransposeMode t_mode, CeedVector u,
190     CeedVector v, CeedRequest *request) {
191   return CeedElemRestrictionApply_Ref_Core(r, 3, 1, comp_stride, start, stop,
192          t_mode, u, v, request);
193 }
194 
195 static int CeedElemRestrictionApply_Ref_311(CeedElemRestriction r,
196     const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
197     CeedInt start, CeedInt stop, CeedTransposeMode t_mode, CeedVector u,
198     CeedVector v, CeedRequest *request) {
199   return CeedElemRestrictionApply_Ref_Core(r, 3, 1, 1, start, stop, t_mode,
200          u, v, request);
201 }
202 
203 static int CeedElemRestrictionApply_Ref_380(CeedElemRestriction r,
204     const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
205     CeedInt start, CeedInt stop, CeedTransposeMode t_mode, CeedVector u,
206     CeedVector v, CeedRequest *request) {
207   return CeedElemRestrictionApply_Ref_Core(r, 3, 8, comp_stride, start, stop,
208          t_mode, u, v, request);
209 }
210 
211 static int CeedElemRestrictionApply_Ref_381(CeedElemRestriction r,
212     const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
213     CeedInt start, CeedInt stop, CeedTransposeMode t_mode, CeedVector u,
214     CeedVector v, CeedRequest *request) {
215   return CeedElemRestrictionApply_Ref_Core(r, 3, 8, 1, start, stop, t_mode,
216          u, v, request);
217 }
218 
219 // LCOV_EXCL_START
220 static int CeedElemRestrictionApply_Ref_510(CeedElemRestriction r,
221     const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
222     CeedInt start, CeedInt stop, CeedTransposeMode t_mode, CeedVector u,
223     CeedVector v, CeedRequest *request) {
224   return CeedElemRestrictionApply_Ref_Core(r, 5, 1, comp_stride, start, stop,
225          t_mode, u, v, request);
226 }
227 // LCOV_EXCL_STOP
228 
229 static int CeedElemRestrictionApply_Ref_511(CeedElemRestriction r,
230     const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
231     CeedInt start, CeedInt stop, CeedTransposeMode t_mode, CeedVector u,
232     CeedVector v, CeedRequest *request) {
233   return CeedElemRestrictionApply_Ref_Core(r, 5, 1, 1, start, stop, t_mode,
234          u, v, request);
235 }
236 
237 // LCOV_EXCL_START
238 static int CeedElemRestrictionApply_Ref_580(CeedElemRestriction r,
239     const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
240     CeedInt start, CeedInt stop, CeedTransposeMode t_mode, CeedVector u,
241     CeedVector v, CeedRequest *request) {
242   return CeedElemRestrictionApply_Ref_Core(r, 5, 8, comp_stride, start, stop,
243          t_mode, u, v, request);
244 }
245 // LCOV_EXCL_STOP
246 
247 static int CeedElemRestrictionApply_Ref_581(CeedElemRestriction r,
248     const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
249     CeedInt start, CeedInt stop, CeedTransposeMode t_mode, CeedVector u,
250     CeedVector v, CeedRequest *request) {
251   return CeedElemRestrictionApply_Ref_Core(r, 5, 8, 1, start, stop, t_mode,
252          u, v, request);
253 }
254 
255 //------------------------------------------------------------------------------
256 // ElemRestriction Apply
257 //------------------------------------------------------------------------------
258 static int CeedElemRestrictionApply_Ref(CeedElemRestriction r,
259                                         CeedTransposeMode t_mode, CeedVector u,
260                                         CeedVector v, CeedRequest *request) {
261   int ierr;
262   CeedInt num_blk, blk_size, num_comp, comp_stride;
263   ierr = CeedElemRestrictionGetNumBlocks(r, &num_blk); CeedChkBackend(ierr);
264   ierr = CeedElemRestrictionGetBlockSize(r, &blk_size); CeedChkBackend(ierr);
265   ierr = CeedElemRestrictionGetNumComponents(r, &num_comp); CeedChkBackend(ierr);
266   ierr = CeedElemRestrictionGetCompStride(r, &comp_stride); CeedChkBackend(ierr);
267   CeedElemRestriction_Ref *impl;
268   ierr = CeedElemRestrictionGetData(r, &impl); CeedChkBackend(ierr);
269 
270   return impl->Apply(r, num_comp, blk_size, comp_stride, 0, num_blk, t_mode, u, v,
271                      request);
272 }
273 
274 //------------------------------------------------------------------------------
275 // ElemRestriction Apply Block
276 //------------------------------------------------------------------------------
277 static int CeedElemRestrictionApplyBlock_Ref(CeedElemRestriction r,
278     CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
279     CeedRequest *request) {
280   int ierr;
281   CeedInt blk_size, num_comp, comp_stride;
282   ierr = CeedElemRestrictionGetBlockSize(r, &blk_size); CeedChkBackend(ierr);
283   ierr = CeedElemRestrictionGetNumComponents(r, &num_comp); CeedChkBackend(ierr);
284   ierr = CeedElemRestrictionGetCompStride(r, &comp_stride); CeedChkBackend(ierr);
285   CeedElemRestriction_Ref *impl;
286   ierr = CeedElemRestrictionGetData(r, &impl); CeedChkBackend(ierr);
287 
288   return impl->Apply(r, num_comp, blk_size, comp_stride, block, block+1, t_mode,
289                      u, v, request);
290 }
291 
292 //------------------------------------------------------------------------------
293 // ElemRestriction Get Offsets
294 //------------------------------------------------------------------------------
295 static int CeedElemRestrictionGetOffsets_Ref(CeedElemRestriction rstr,
296     CeedMemType mem_type, const CeedInt **offsets) {
297   int ierr;
298   CeedElemRestriction_Ref *impl;
299   ierr = CeedElemRestrictionGetData(rstr, &impl); CeedChkBackend(ierr);
300   Ceed ceed;
301   ierr = CeedElemRestrictionGetCeed(rstr, &ceed); CeedChkBackend(ierr);
302 
303   if (mem_type != CEED_MEM_HOST)
304     // LCOV_EXCL_START
305     return CeedError(ceed, CEED_ERROR_BACKEND, "Can only provide to HOST memory");
306   // LCOV_EXCL_STOP
307 
308   *offsets = impl->offsets;
309   return CEED_ERROR_SUCCESS;
310 }
311 
312 //------------------------------------------------------------------------------
313 // ElemRestriction Destroy
314 //------------------------------------------------------------------------------
315 static int CeedElemRestrictionDestroy_Ref(CeedElemRestriction r) {
316   int ierr;
317   CeedElemRestriction_Ref *impl;
318   ierr = CeedElemRestrictionGetData(r, &impl); CeedChkBackend(ierr);
319 
320   ierr = CeedFree(&impl->offsets_allocated); CeedChkBackend(ierr);
321   ierr = CeedFree(&impl); CeedChkBackend(ierr);
322   return CEED_ERROR_SUCCESS;
323 }
324 
325 //------------------------------------------------------------------------------
326 // ElemRestriction Create
327 //------------------------------------------------------------------------------
328 int CeedElemRestrictionCreate_Ref(CeedMemType mem_type, CeedCopyMode copy_mode,
329                                   const CeedInt *offsets,
330                                   CeedElemRestriction r) {
331   int ierr;
332   CeedElemRestriction_Ref *impl;
333   CeedInt num_elem, elem_size, num_blk, blk_size, num_comp, comp_stride;
334   ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChkBackend(ierr);
335   ierr = CeedElemRestrictionGetElementSize(r, &elem_size); CeedChkBackend(ierr);
336   ierr = CeedElemRestrictionGetNumBlocks(r, &num_blk); CeedChkBackend(ierr);
337   ierr = CeedElemRestrictionGetBlockSize(r, &blk_size); CeedChkBackend(ierr);
338   ierr = CeedElemRestrictionGetNumComponents(r, &num_comp); CeedChkBackend(ierr);
339   ierr = CeedElemRestrictionGetCompStride(r, &comp_stride); CeedChkBackend(ierr);
340   Ceed ceed;
341   ierr = CeedElemRestrictionGetCeed(r, &ceed); CeedChkBackend(ierr);
342 
343   if (mem_type != CEED_MEM_HOST)
344     // LCOV_EXCL_START
345     return CeedError(ceed, CEED_ERROR_BACKEND, "Only MemType = HOST supported");
346   // LCOV_EXCL_STOP
347   ierr = CeedCalloc(1, &impl); CeedChkBackend(ierr);
348 
349   // Offsets data
350   bool is_strided;
351   ierr = CeedElemRestrictionIsStrided(r, &is_strided); CeedChkBackend(ierr);
352   if (!is_strided) {
353     // Check indices for ref or memcheck backends
354     Ceed parent_ceed = ceed, curr_ceed = NULL;
355     while (parent_ceed != curr_ceed) {
356       curr_ceed = parent_ceed;
357       ierr = CeedGetParent(curr_ceed, &parent_ceed); CeedChkBackend(ierr);
358     }
359     const char *resource;
360     ierr = CeedGetResource(parent_ceed, &resource); CeedChkBackend(ierr);
361     if (!strcmp(resource, "/cpu/self/ref/serial") ||
362         !strcmp(resource, "/cpu/self/ref/blocked") ||
363         !strcmp(resource, "/cpu/self/memcheck/serial") ||
364         !strcmp(resource, "/cpu/self/memcheck/blocked")) {
365       CeedInt l_size;
366       ierr = CeedElemRestrictionGetLVectorSize(r, &l_size); CeedChkBackend(ierr);
367 
368       for (CeedInt i = 0; i < num_elem*elem_size; i++)
369         if (offsets[i] < 0 || l_size <= offsets[i] + (num_comp - 1) * comp_stride)
370           // LCOV_EXCL_START
371           return CeedError(ceed, CEED_ERROR_BACKEND,
372                            "Restriction offset %d (%d) out of range "
373                            "[0, %d]", i, offsets[i], l_size);
374       // LCOV_EXCL_STOP
375     }
376 
377     // Copy data
378     switch (copy_mode) {
379     case CEED_COPY_VALUES:
380       ierr = CeedMalloc(num_elem*elem_size, &impl->offsets_allocated);
381       CeedChkBackend(ierr);
382       memcpy(impl->offsets_allocated, offsets,
383              num_elem * elem_size * sizeof(offsets[0]));
384       impl->offsets = impl->offsets_allocated;
385       break;
386     case CEED_OWN_POINTER:
387       impl->offsets_allocated = (CeedInt *)offsets;
388       impl->offsets = impl->offsets_allocated;
389       break;
390     case CEED_USE_POINTER:
391       impl->offsets = offsets;
392     }
393   }
394 
395   ierr = CeedElemRestrictionSetData(r, impl); CeedChkBackend(ierr);
396   CeedInt layout[3] = {1, elem_size, elem_size*num_comp};
397   ierr = CeedElemRestrictionSetELayout(r, layout); CeedChkBackend(ierr);
398   ierr = CeedSetBackendFunction(ceed, "ElemRestriction", r, "Apply",
399                                 CeedElemRestrictionApply_Ref); CeedChkBackend(ierr);
400   ierr = CeedSetBackendFunction(ceed, "ElemRestriction", r, "ApplyBlock",
401                                 CeedElemRestrictionApplyBlock_Ref);
402   CeedChkBackend(ierr);
403   ierr = CeedSetBackendFunction(ceed, "ElemRestriction", r, "GetOffsets",
404                                 CeedElemRestrictionGetOffsets_Ref);
405   CeedChkBackend(ierr);
406   ierr = CeedSetBackendFunction(ceed, "ElemRestriction", r, "Destroy",
407                                 CeedElemRestrictionDestroy_Ref); CeedChkBackend(ierr);
408 
409   // Set apply function based upon num_comp, blk_size, and comp_stride
410   CeedInt idx = -1;
411   if (blk_size < 10)
412     idx = 100*num_comp + 10*blk_size + (comp_stride == 1);
413   switch (idx) {
414   case 110:
415     impl->Apply = CeedElemRestrictionApply_Ref_110;
416     break;
417   case 111:
418     impl->Apply = CeedElemRestrictionApply_Ref_111;
419     break;
420   case 180:
421     impl->Apply = CeedElemRestrictionApply_Ref_180;
422     break;
423   case 181:
424     impl->Apply = CeedElemRestrictionApply_Ref_181;
425     break;
426   case 310:
427     impl->Apply = CeedElemRestrictionApply_Ref_310;
428     break;
429   case 311:
430     impl->Apply = CeedElemRestrictionApply_Ref_311;
431     break;
432   case 380:
433     impl->Apply = CeedElemRestrictionApply_Ref_380;
434     break;
435   case 381:
436     impl->Apply = CeedElemRestrictionApply_Ref_381;
437     break;
438   // LCOV_EXCL_START
439   case 510:
440     impl->Apply = CeedElemRestrictionApply_Ref_510;
441     break;
442   // LCOV_EXCL_STOP
443   case 511:
444     impl->Apply = CeedElemRestrictionApply_Ref_511;
445     break;
446   // LCOV_EXCL_START
447   case 580:
448     impl->Apply = CeedElemRestrictionApply_Ref_580;
449     break;
450   // LCOV_EXCL_STOP
451   case 581:
452     impl->Apply = CeedElemRestrictionApply_Ref_581;
453     break;
454   default:
455     impl->Apply = CeedElemRestrictionApply_Ref_Core;
456     break;
457   }
458 
459   return CEED_ERROR_SUCCESS;
460 }
461 
462 //------------------------------------------------------------------------------
463 // ElemRestriction Create Oriented
464 //------------------------------------------------------------------------------
465 int CeedElemRestrictionCreateOriented_Ref(CeedMemType mem_type,
466     CeedCopyMode copy_mode,
467     const CeedInt *offsets, const bool *orient,
468     CeedElemRestriction r) {
469   int ierr;
470   CeedElemRestriction_Ref *impl;
471   CeedInt num_elem, elem_size;
472   // Set up for normal restriction with explicit offsets. This sets up dispatch to
473   // CeedElemRestrictionApply_Ref_* and manages the impl->offsets array copy/allocation.
474   ierr = CeedElemRestrictionCreate_Ref(mem_type, copy_mode, offsets, r);
475   CeedChkBackend(ierr);
476 
477   ierr = CeedElemRestrictionGetData(r, &impl); CeedChkBackend(ierr);
478   ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChkBackend(ierr);
479   ierr = CeedElemRestrictionGetElementSize(r, &elem_size); CeedChkBackend(ierr);
480   switch (copy_mode) {
481   case CEED_COPY_VALUES:
482     ierr = CeedMalloc(num_elem * elem_size, &impl->orient_allocated);
483     CeedChkBackend(ierr);
484     memcpy(impl->orient_allocated, orient,
485            num_elem * elem_size * sizeof(orient[0]));
486     impl->orient = impl->orient_allocated;
487     break;
488   case CEED_OWN_POINTER:
489     impl->orient_allocated = (bool *)orient;
490     impl->orient = impl->orient_allocated;
491     break;
492   case CEED_USE_POINTER:
493     impl->orient = orient;
494   }
495   return CEED_ERROR_SUCCESS;
496 }
497 //------------------------------------------------------------------------------
498