1 // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2 // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3 // 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-impl.h> 18 #include <ceed-backend.h> 19 #include <math.h> 20 21 /// @cond DOXYGEN_SKIP 22 static struct CeedVector_private ceed_vector_active; 23 static struct CeedVector_private ceed_vector_none; 24 /// @endcond 25 26 /// @file 27 /// Implementation of public CeedVector interfaces 28 /// 29 /// @addtogroup CeedVector 30 /// @{ 31 32 /** 33 @brief Create a CeedVector of the specified length (does not allocate memory) 34 35 @param ceed Ceed object where the CeedVector will be created 36 @param length Length of vector 37 @param[out] vec Address of the variable where the newly created 38 CeedVector will be stored 39 40 @return An error code: 0 - success, otherwise - failure 41 42 @ref Basic 43 **/ 44 int CeedVectorCreate(Ceed ceed, CeedInt length, CeedVector *vec) { 45 int ierr; 46 47 if (!ceed->VectorCreate) { 48 Ceed delegate; 49 ierr = CeedGetObjectDelegate(ceed, &delegate, "Vector"); CeedChk(ierr); 50 51 if (!delegate) 52 // LCOV_EXCL_START 53 return CeedError(ceed, 1, "Backend does not support VectorCreate"); 54 // LCOV_EXCL_STOP 55 56 ierr = CeedVectorCreate(delegate, length, vec); CeedChk(ierr); 57 return 0; 58 } 59 60 ierr = CeedCalloc(1,vec); CeedChk(ierr); 61 (*vec)->ceed = ceed; 62 ceed->refcount++; 63 (*vec)->refcount = 1; 64 (*vec)->length = length; 65 (*vec)->state = 0; 66 ierr = ceed->VectorCreate(length, *vec); CeedChk(ierr); 67 return 0; 68 } 69 70 /** 71 @brief Set the array used by a CeedVector, freeing any previously allocated 72 array if applicable 73 74 @param vec CeedVector 75 @param mtype Memory type of the array being passed 76 @param cmode Copy mode for the array 77 @param array Array to be used, or NULL with CEED_COPY_VALUES to have the 78 library allocate 79 80 @return An error code: 0 - success, otherwise - failure 81 82 @ref Basic 83 **/ 84 int CeedVectorSetArray(CeedVector vec, CeedMemType mtype, CeedCopyMode cmode, 85 CeedScalar *array) { 86 int ierr; 87 88 if (!vec->SetArray) 89 // LCOV_EXCL_START 90 return CeedError(vec->ceed, 1, "Backend does not support VectorSetArray"); 91 // LCOV_EXCL_STOP 92 93 if (vec->state % 2 == 1) 94 return CeedError(vec->ceed, 1, "Cannot grant CeedVector array access, the " 95 "access lock is already in use"); 96 97 if (vec->numreaders > 0) 98 return CeedError(vec->ceed, 1, "Cannot grant CeedVector array access, a " 99 "process has read access"); 100 101 ierr = vec->SetArray(vec, mtype, cmode, array); CeedChk(ierr); 102 vec->state += 2; 103 104 return 0; 105 } 106 107 /** 108 @brief Set the CeedVector to a constant value 109 110 @param vec CeedVector 111 @param[in] value Value to be used 112 113 @return An error code: 0 - success, otherwise - failure 114 115 @ref Basic 116 **/ 117 int CeedVectorSetValue(CeedVector vec, CeedScalar value) { 118 int ierr; 119 120 if (vec->state % 2 == 1) 121 return CeedError(vec->ceed, 1, "Cannot grant CeedVector array access, the " 122 "access lock is already in use"); 123 124 if (vec->SetValue) { 125 ierr = vec->SetValue(vec, value); CeedChk(ierr); 126 } else { 127 CeedScalar *array; 128 ierr = CeedVectorGetArray(vec, CEED_MEM_HOST, &array); CeedChk(ierr); 129 for (int i=0; i<vec->length; i++) array[i] = value; 130 ierr = CeedVectorRestoreArray(vec, &array); CeedChk(ierr); 131 } 132 133 vec->state += 2; 134 135 return 0; 136 } 137 138 /** 139 @brief Sync the CeedVector to a specified memtype 140 141 @param vec CeedVector 142 @param mtype Memtype to be synced 143 144 @return An error code: 0 - success, otherwise - failure 145 146 @ref Basic 147 **/ 148 int CeedVectorSyncArray(CeedVector vec, CeedMemType mtype) { 149 int ierr; 150 151 if (vec->state % 2 == 1) 152 return CeedError(vec->ceed, 1, "Cannot sync CeedVector, the access lock is " 153 "already in use"); 154 155 if (vec->SyncArray) { 156 ierr = vec->SyncArray(vec, mtype); CeedChk(ierr); 157 } else { 158 const CeedScalar *array; 159 ierr = CeedVectorGetArrayRead(vec, mtype, &array); CeedChk(ierr); 160 ierr = CeedVectorRestoreArrayRead(vec, &array); CeedChk(ierr); 161 } 162 163 return 0; 164 } 165 166 /** 167 @brief Get read/write access to a CeedVector via the specified memory type 168 169 @param vec CeedVector to access 170 @param mtype Memory type on which to access the array. If the backend 171 uses a different memory type, this will perform a copy and 172 CeedVectorRestoreArray() will copy back. 173 @param[out] array Array on memory type mtype 174 175 @note The CeedVectorGetArray* and CeedVectorRestoreArray* functions provide 176 access to array pointers in the desired memory space. Pairing get/restore 177 allows the Vector to track access, thus knowing if norms or other 178 operations may need to be recomputed. 179 180 @return An error code: 0 - success, otherwise - failure 181 182 @ref Basic 183 **/ 184 int CeedVectorGetArray(CeedVector vec, CeedMemType mtype, CeedScalar **array) { 185 int ierr; 186 187 if (!vec->GetArray) 188 // LCOV_EXCL_START 189 return CeedError(vec->ceed, 1, "Backend does not support GetArray"); 190 // LCOV_EXCL_STOP 191 192 if (vec->state % 2 == 1) 193 return CeedError(vec->ceed, 1, "Cannot grant CeedVector array access, the " 194 "access lock is already in use"); 195 196 if (vec->numreaders > 0) 197 return CeedError(vec->ceed, 1, "Cannot grant CeedVector array access, a " 198 "process has read access"); 199 200 ierr = vec->GetArray(vec, mtype, array); CeedChk(ierr); 201 vec->state += 1; 202 203 return 0; 204 } 205 206 /** 207 @brief Get read-only access to a CeedVector via the specified memory type 208 209 @param vec CeedVector to access 210 @param mtype Memory type on which to access the array. If the backend 211 uses a different memory type, this will perform a copy 212 (possibly cached). 213 @param[out] array Array on memory type mtype 214 215 @return An error code: 0 - success, otherwise - failure 216 217 @ref Basic 218 **/ 219 int CeedVectorGetArrayRead(CeedVector vec, CeedMemType mtype, 220 const CeedScalar **array) { 221 int ierr; 222 223 if (!vec->GetArrayRead) 224 // LCOV_EXCL_START 225 return CeedError(vec->ceed, 1, "Backend does not support GetArrayRead"); 226 // LCOV_EXCL_STOP 227 228 if (vec->state % 2 == 1) 229 return CeedError(vec->ceed, 1, "Cannot grant CeedVector read-only array " 230 "access, the access lock is already in use"); 231 232 ierr = vec->GetArrayRead(vec, mtype, array); CeedChk(ierr); 233 vec->numreaders++; 234 235 return 0; 236 } 237 238 /** 239 @brief Restore an array obtained using CeedVectorGetArray() 240 241 @param vec CeedVector to restore 242 @param array Array of vector data 243 244 @return An error code: 0 - success, otherwise - failure 245 246 @ref Basic 247 **/ 248 int CeedVectorRestoreArray(CeedVector vec, CeedScalar **array) { 249 int ierr; 250 251 if (!vec->RestoreArray) 252 // LCOV_EXCL_START 253 return CeedError(vec->ceed, 1, "Backend does not support RestoreArray"); 254 // LCOV_EXCL_STOP 255 256 if (vec->state % 2 != 1) 257 return CeedError(vec->ceed, 1, "Cannot restore CeedVector array access, " 258 "access was not granted"); 259 260 ierr = vec->RestoreArray(vec); CeedChk(ierr); 261 *array = NULL; 262 vec->state += 1; 263 264 return 0; 265 } 266 267 /** 268 @brief Restore an array obtained using CeedVectorGetArrayRead() 269 270 @param vec CeedVector to restore 271 @param array Array of vector data 272 273 @return An error code: 0 - success, otherwise - failure 274 275 @ref Basic 276 **/ 277 int CeedVectorRestoreArrayRead(CeedVector vec, const CeedScalar **array) { 278 int ierr; 279 280 if (!vec->RestoreArrayRead) 281 // LCOV_EXCL_START 282 return CeedError(vec->ceed, 1, "Backend does not support RestoreArrayRead"); 283 // LCOV_EXCL_STOP 284 285 ierr = vec->RestoreArrayRead(vec); CeedChk(ierr); 286 *array = NULL; 287 vec->numreaders--; 288 289 return 0; 290 } 291 292 /** 293 @brief View a CeedVector 294 295 @return An error code: 0 - success, otherwise - failure 296 297 @ref Utility 298 **/ 299 int CeedVectorView(CeedVector vec, const char *fpfmt, FILE *stream) { 300 const CeedScalar *x; 301 302 int ierr = CeedVectorGetArrayRead(vec, CEED_MEM_HOST, &x); CeedChk(ierr); 303 304 char fmt[1024]; 305 fprintf(stream, "CeedVector length %ld\n", (long)vec->length); 306 snprintf(fmt, sizeof fmt, " %s\n", fpfmt ? fpfmt : "%g"); 307 for (CeedInt i=0; i<vec->length; i++) 308 fprintf(stream, fmt, x[i]); 309 310 ierr = CeedVectorRestoreArrayRead(vec, &x); CeedChk(ierr); 311 312 return 0; 313 } 314 315 /** 316 @brief Get the Ceed associated with a CeedVector 317 318 @param vec CeedVector to retrieve state 319 @param[out] ceed Variable to store ceed 320 321 @return An error code: 0 - success, otherwise - failure 322 323 @ref Advanced 324 **/ 325 int CeedVectorGetCeed(CeedVector vec, Ceed *ceed) { 326 *ceed = vec->ceed; 327 return 0; 328 } 329 330 /** 331 @brief Get the length of a CeedVector 332 333 @param vec CeedVector to retrieve length 334 @param[out] length Variable to store length 335 336 @return An error code: 0 - success, otherwise - failure 337 338 @ref Advanced 339 **/ 340 int CeedVectorGetLength(CeedVector vec, CeedInt *length) { 341 *length = vec->length; 342 return 0; 343 } 344 345 /** 346 @brief Get the norm of a CeedVector. 347 348 Note: This operation is local to the CeedVector. This function will likely 349 not provide the desired results for the norm of the libCEED portion 350 of a parallel vector or a CeedVector with duplicated or hanging nodes. 351 352 @param vec CeedVector to retrieve maximum value 353 @param type Norm type CEED_NORM_1, CEED_NORM_2, or CEED_NORM_MAX 354 @param[out] norm Variable to store norm value 355 356 @return An error code: 0 - success, otherwise - failure 357 358 @ref Advanced 359 **/ 360 int CeedVectorNorm(CeedVector vec, CeedNormType type, CeedScalar *norm) { 361 int ierr; 362 363 // Backend impl for GPU, if added 364 if (vec->Norm) { 365 ierr = vec->Norm(vec, type, norm); CeedChk(ierr); 366 return 0; 367 } 368 369 const CeedScalar *array; 370 ierr = CeedVectorGetArrayRead(vec, CEED_MEM_HOST, &array); CeedChk(ierr); 371 372 *norm = 0.; 373 switch (type) { 374 case CEED_NORM_1: 375 for (int i=0; i<vec->length; i++) { 376 *norm += fabs(array[i]); 377 } 378 break; 379 case CEED_NORM_2: 380 for (int i=0; i<vec->length; i++) { 381 *norm += fabs(array[i])*fabs(array[i]); 382 } 383 break; 384 case CEED_NORM_MAX: 385 for (int i=0; i<vec->length; i++) { 386 const CeedScalar absi = fabs(array[i]); 387 *norm = *norm > absi ? *norm : absi; 388 } 389 } 390 if (type == CEED_NORM_2) 391 *norm = sqrt(*norm); 392 393 ierr = CeedVectorRestoreArrayRead(vec, &array); CeedChk(ierr); 394 395 return 0; 396 } 397 398 /** 399 @brief Get the state of a CeedVector 400 401 @param vec CeedVector to retrieve state 402 @param[out] state Variable to store state 403 404 @return An error code: 0 - success, otherwise - failure 405 406 @ref Advanced 407 **/ 408 int CeedVectorGetState(CeedVector vec, uint64_t *state) { 409 *state = vec->state; 410 return 0; 411 } 412 413 /** 414 @brief Get the backend data of a CeedVector 415 416 @param vec CeedVector to retrieve state 417 @param[out] data Variable to store data 418 419 @return An error code: 0 - success, otherwise - failure 420 421 @ref Advanced 422 **/ 423 int CeedVectorGetData(CeedVector vec, void **data) { 424 *data = vec->data; 425 return 0; 426 } 427 428 /** 429 @brief Set the backend data of a CeedVector 430 431 @param[out] vec CeedVector to retrieve state 432 @param data Data to set 433 434 @return An error code: 0 - success, otherwise - failure 435 436 @ref Advanced 437 **/ 438 int CeedVectorSetData(CeedVector vec, void **data) { 439 vec->data = *data; 440 return 0; 441 } 442 443 /** 444 @brief Add a refrence to a CeedVector 445 446 @param[out] vec CeedVector to increment refrence counter 447 448 @return An error code: 0 - success, otherwise - failure 449 450 @ref Advanced 451 **/ 452 int CeedVectorAddReference(CeedVector vec) { 453 vec->refcount++; 454 return 0; 455 } 456 457 /** 458 @brief Destroy a CeedVector 459 460 @param vec CeedVector to destroy 461 462 @return An error code: 0 - success, otherwise - failure 463 464 @ref Basic 465 **/ 466 int CeedVectorDestroy(CeedVector *vec) { 467 int ierr; 468 469 if (!*vec || --(*vec)->refcount > 0) 470 return 0; 471 472 if ((*vec) && ((*vec)->state % 2) == 1) 473 return CeedError((*vec)->ceed, 1, "Cannot destroy CeedVector, the access " 474 "lock is in use"); 475 476 if ((*vec)->Destroy) { 477 ierr = (*vec)->Destroy(*vec); CeedChk(ierr); 478 } 479 480 ierr = CeedDestroy(&(*vec)->ceed); CeedChk(ierr); 481 ierr = CeedFree(vec); CeedChk(ierr); 482 483 return 0; 484 } 485 486 /// @cond DOXYGEN_SKIP 487 // Indicate that vector will be provided as an explicit argument to 488 // CeedOperatorApply(). 489 const CeedVector CEED_VECTOR_ACTIVE = &ceed_vector_active; 490 491 // Indicate that no vector is applicable (i.e., for CEED_EVAL_WEIGHTS). 492 const CeedVector CEED_VECTOR_NONE = &ceed_vector_none; 493 /// @endcond 494 /// @} 495