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 @param vec CeedVector to retrieve maximum value 349 @param type Norm type CEED_NORM_1, CEED_NORM_2, or CEED_NORM_MAX 350 @param[out] norm Variable to store norm value 351 352 @return An error code: 0 - success, otherwise - failure 353 354 @ref Advanced 355 **/ 356 int CeedVectorNorm(CeedVector vec, CeedNormType type, CeedScalar *norm) { 357 int ierr; 358 359 // Backend impl for GPU, if added 360 if (vec->Norm) { 361 ierr = vec->Norm(vec, type, norm); CeedChk(ierr); 362 return 0; 363 } 364 365 const CeedScalar *array; 366 ierr = CeedVectorGetArrayRead(vec, CEED_MEM_HOST, &array); CeedChk(ierr); 367 368 *norm = 0.; 369 switch (type) { 370 case CEED_NORM_1: 371 for (int i=0; i<vec->length; i++) { 372 *norm += fabs(array[i]); 373 } 374 break; 375 case CEED_NORM_2: 376 for (int i=0; i<vec->length; i++) { 377 *norm += fabs(array[i])*fabs(array[i]); 378 } 379 break; 380 case CEED_NORM_MAX: 381 for (int i=0; i<vec->length; i++) { 382 const CeedScalar absi = fabs(array[i]); 383 *norm = *norm > absi ? *norm : absi; 384 } 385 } 386 if (type == CEED_NORM_2) 387 *norm = sqrt(*norm); 388 389 ierr = CeedVectorRestoreArrayRead(vec, &array); CeedChk(ierr); 390 391 return 0; 392 } 393 394 /** 395 @brief Get the state of a CeedVector 396 397 @param vec CeedVector to retrieve state 398 @param[out] state Variable to store state 399 400 @return An error code: 0 - success, otherwise - failure 401 402 @ref Advanced 403 **/ 404 int CeedVectorGetState(CeedVector vec, uint64_t *state) { 405 *state = vec->state; 406 return 0; 407 } 408 409 /** 410 @brief Get the backend data of a CeedVector 411 412 @param vec CeedVector to retrieve state 413 @param[out] data Variable to store data 414 415 @return An error code: 0 - success, otherwise - failure 416 417 @ref Advanced 418 **/ 419 int CeedVectorGetData(CeedVector vec, void **data) { 420 *data = vec->data; 421 return 0; 422 } 423 424 /** 425 @brief Set the backend data of a CeedVector 426 427 @param[out] vec CeedVector to retrieve state 428 @param data Data to set 429 430 @return An error code: 0 - success, otherwise - failure 431 432 @ref Advanced 433 **/ 434 int CeedVectorSetData(CeedVector vec, void **data) { 435 vec->data = *data; 436 return 0; 437 } 438 439 /** 440 @brief Add a refrence to a CeedVector 441 442 @param[out] vec CeedVector to increment refrence counter 443 444 @return An error code: 0 - success, otherwise - failure 445 446 @ref Advanced 447 **/ 448 int CeedVectorAddReference(CeedVector vec) { 449 vec->refcount++; 450 return 0; 451 } 452 453 /** 454 @brief Destroy a CeedVector 455 456 @param vec CeedVector to destroy 457 458 @return An error code: 0 - success, otherwise - failure 459 460 @ref Basic 461 **/ 462 int CeedVectorDestroy(CeedVector *vec) { 463 int ierr; 464 465 if (!*vec || --(*vec)->refcount > 0) 466 return 0; 467 468 if ((*vec) && ((*vec)->state % 2) == 1) 469 return CeedError((*vec)->ceed, 1, "Cannot destroy CeedVector, the access " 470 "lock is in use"); 471 472 if ((*vec)->Destroy) { 473 ierr = (*vec)->Destroy(*vec); CeedChk(ierr); 474 } 475 476 ierr = CeedDestroy(&(*vec)->ceed); CeedChk(ierr); 477 ierr = CeedFree(vec); CeedChk(ierr); 478 479 return 0; 480 } 481 482 /// @cond DOXYGEN_SKIP 483 // Indicate that vector will be provided as an explicit argument to 484 // CeedOperatorApply(). 485 CeedVector CEED_VECTOR_ACTIVE = &ceed_vector_active; 486 487 // Indicate that no vector is applicable (i.e., for CEED_EVAL_WEIGHTS). 488 CeedVector CEED_VECTOR_NONE = &ceed_vector_none; 489 /// @endcond 490 /// @} 491