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->orient_allocated); CeedChkBackend(ierr); 315 ierr = CeedFree(&impl); CeedChkBackend(ierr); 316 return CEED_ERROR_SUCCESS; 317 } 318 319 //------------------------------------------------------------------------------ 320 // ElemRestriction Create 321 //------------------------------------------------------------------------------ 322 int CeedElemRestrictionCreate_Ref(CeedMemType mem_type, CeedCopyMode copy_mode, 323 const CeedInt *offsets, 324 CeedElemRestriction r) { 325 int ierr; 326 CeedElemRestriction_Ref *impl; 327 CeedInt num_elem, elem_size, num_blk, blk_size, num_comp, comp_stride; 328 ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChkBackend(ierr); 329 ierr = CeedElemRestrictionGetElementSize(r, &elem_size); CeedChkBackend(ierr); 330 ierr = CeedElemRestrictionGetNumBlocks(r, &num_blk); CeedChkBackend(ierr); 331 ierr = CeedElemRestrictionGetBlockSize(r, &blk_size); CeedChkBackend(ierr); 332 ierr = CeedElemRestrictionGetNumComponents(r, &num_comp); CeedChkBackend(ierr); 333 ierr = CeedElemRestrictionGetCompStride(r, &comp_stride); CeedChkBackend(ierr); 334 Ceed ceed; 335 ierr = CeedElemRestrictionGetCeed(r, &ceed); CeedChkBackend(ierr); 336 337 if (mem_type != CEED_MEM_HOST) 338 // LCOV_EXCL_START 339 return CeedError(ceed, CEED_ERROR_BACKEND, "Only MemType = HOST supported"); 340 // LCOV_EXCL_STOP 341 ierr = CeedCalloc(1, &impl); CeedChkBackend(ierr); 342 343 // Offsets data 344 bool is_strided; 345 ierr = CeedElemRestrictionIsStrided(r, &is_strided); CeedChkBackend(ierr); 346 if (!is_strided) { 347 // Check indices for ref or memcheck backends 348 Ceed parent_ceed = ceed, curr_ceed = NULL; 349 while (parent_ceed != curr_ceed) { 350 curr_ceed = parent_ceed; 351 ierr = CeedGetParent(curr_ceed, &parent_ceed); CeedChkBackend(ierr); 352 } 353 const char *resource; 354 ierr = CeedGetResource(parent_ceed, &resource); CeedChkBackend(ierr); 355 if (!strcmp(resource, "/cpu/self/ref/serial") || 356 !strcmp(resource, "/cpu/self/ref/blocked") || 357 !strcmp(resource, "/cpu/self/memcheck/serial") || 358 !strcmp(resource, "/cpu/self/memcheck/blocked")) { 359 CeedSize l_size; 360 ierr = CeedElemRestrictionGetLVectorSize(r, &l_size); CeedChkBackend(ierr); 361 362 for (CeedInt i = 0; i < num_elem*elem_size; i++) 363 if (offsets[i] < 0 || l_size <= offsets[i] + (num_comp - 1) * comp_stride) 364 // LCOV_EXCL_START 365 return CeedError(ceed, CEED_ERROR_BACKEND, 366 "Restriction offset %" CeedInt_FMT " (%" CeedInt_FMT ") out of range " 367 "[0, %" CeedInt_FMT "]", i, offsets[i], l_size); 368 // LCOV_EXCL_STOP 369 } 370 371 // Copy data 372 switch (copy_mode) { 373 case CEED_COPY_VALUES: 374 ierr = CeedMalloc(num_elem*elem_size, &impl->offsets_allocated); 375 CeedChkBackend(ierr); 376 memcpy(impl->offsets_allocated, offsets, 377 num_elem * elem_size * sizeof(offsets[0])); 378 impl->offsets = impl->offsets_allocated; 379 break; 380 case CEED_OWN_POINTER: 381 impl->offsets_allocated = (CeedInt *)offsets; 382 impl->offsets = impl->offsets_allocated; 383 break; 384 case CEED_USE_POINTER: 385 impl->offsets = offsets; 386 } 387 } 388 389 ierr = CeedElemRestrictionSetData(r, impl); CeedChkBackend(ierr); 390 CeedInt layout[3] = {1, elem_size, elem_size*num_comp}; 391 ierr = CeedElemRestrictionSetELayout(r, layout); CeedChkBackend(ierr); 392 ierr = CeedSetBackendFunction(ceed, "ElemRestriction", r, "Apply", 393 CeedElemRestrictionApply_Ref); CeedChkBackend(ierr); 394 ierr = CeedSetBackendFunction(ceed, "ElemRestriction", r, "ApplyBlock", 395 CeedElemRestrictionApplyBlock_Ref); 396 CeedChkBackend(ierr); 397 ierr = CeedSetBackendFunction(ceed, "ElemRestriction", r, "GetOffsets", 398 CeedElemRestrictionGetOffsets_Ref); 399 CeedChkBackend(ierr); 400 ierr = CeedSetBackendFunction(ceed, "ElemRestriction", r, "Destroy", 401 CeedElemRestrictionDestroy_Ref); CeedChkBackend(ierr); 402 403 // Set apply function based upon num_comp, blk_size, and comp_stride 404 CeedInt idx = -1; 405 if (blk_size < 10) 406 idx = 100*num_comp + 10*blk_size + (comp_stride == 1); 407 switch (idx) { 408 case 110: 409 impl->Apply = CeedElemRestrictionApply_Ref_110; 410 break; 411 case 111: 412 impl->Apply = CeedElemRestrictionApply_Ref_111; 413 break; 414 case 180: 415 impl->Apply = CeedElemRestrictionApply_Ref_180; 416 break; 417 case 181: 418 impl->Apply = CeedElemRestrictionApply_Ref_181; 419 break; 420 case 310: 421 impl->Apply = CeedElemRestrictionApply_Ref_310; 422 break; 423 case 311: 424 impl->Apply = CeedElemRestrictionApply_Ref_311; 425 break; 426 case 380: 427 impl->Apply = CeedElemRestrictionApply_Ref_380; 428 break; 429 case 381: 430 impl->Apply = CeedElemRestrictionApply_Ref_381; 431 break; 432 // LCOV_EXCL_START 433 case 510: 434 impl->Apply = CeedElemRestrictionApply_Ref_510; 435 break; 436 // LCOV_EXCL_STOP 437 case 511: 438 impl->Apply = CeedElemRestrictionApply_Ref_511; 439 break; 440 // LCOV_EXCL_START 441 case 580: 442 impl->Apply = CeedElemRestrictionApply_Ref_580; 443 break; 444 // LCOV_EXCL_STOP 445 case 581: 446 impl->Apply = CeedElemRestrictionApply_Ref_581; 447 break; 448 default: 449 impl->Apply = CeedElemRestrictionApply_Ref_Core; 450 break; 451 } 452 453 return CEED_ERROR_SUCCESS; 454 } 455 456 //------------------------------------------------------------------------------ 457 // ElemRestriction Create Oriented 458 //------------------------------------------------------------------------------ 459 int CeedElemRestrictionCreateOriented_Ref(CeedMemType mem_type, 460 CeedCopyMode copy_mode, 461 const CeedInt *offsets, const bool *orient, 462 CeedElemRestriction r) { 463 int ierr; 464 CeedElemRestriction_Ref *impl; 465 CeedInt num_elem, elem_size; 466 // Set up for normal restriction with explicit offsets. This sets up dispatch to 467 // CeedElemRestrictionApply_Ref_* and manages the impl->offsets array copy/allocation. 468 ierr = CeedElemRestrictionCreate_Ref(mem_type, copy_mode, offsets, r); 469 CeedChkBackend(ierr); 470 471 ierr = CeedElemRestrictionGetData(r, &impl); CeedChkBackend(ierr); 472 ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChkBackend(ierr); 473 ierr = CeedElemRestrictionGetElementSize(r, &elem_size); CeedChkBackend(ierr); 474 switch (copy_mode) { 475 case CEED_COPY_VALUES: 476 ierr = CeedMalloc(num_elem * elem_size, &impl->orient_allocated); 477 CeedChkBackend(ierr); 478 memcpy(impl->orient_allocated, orient, 479 num_elem * elem_size * sizeof(orient[0])); 480 impl->orient = impl->orient_allocated; 481 break; 482 case CEED_OWN_POINTER: 483 impl->orient_allocated = (bool *)orient; 484 impl->orient = impl->orient_allocated; 485 break; 486 case CEED_USE_POINTER: 487 impl->orient = orient; 488 } 489 return CEED_ERROR_SUCCESS; 490 } 491 //------------------------------------------------------------------------------ 492