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