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