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