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