15aed82e4SJeremy L Thompson // Copyright (c) 2017-2024, Lawrence Livermore National Security, LLC and other CEED contributors. 23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 30436c2adSjeremylt // 43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 50436c2adSjeremylt // 63d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 70436c2adSjeremylt 82b730f8bSJeremy L Thompson #include <ceed-impl.h> 949aac155SJeremy L Thompson #include <ceed.h> 102b730f8bSJeremy L Thompson #include <ceed/backend.h> 11c85e8640SSebastian Grimberg #include <assert.h> 12547d9b97Sjeremylt #include <math.h> 1349aac155SJeremy L Thompson #include <stdbool.h> 143d576824SJeremy L Thompson #include <stdint.h> 153d576824SJeremy L Thompson #include <stdio.h> 160436c2adSjeremylt 177a982d89SJeremy L. Thompson /// @file 187a982d89SJeremy L. Thompson /// Implementation of public CeedVector interfaces 197a982d89SJeremy L. Thompson 200436c2adSjeremylt /// @cond DOXYGEN_SKIP 210436c2adSjeremylt static struct CeedVector_private ceed_vector_active; 220436c2adSjeremylt static struct CeedVector_private ceed_vector_none; 230436c2adSjeremylt /// @endcond 240436c2adSjeremylt 257a982d89SJeremy L. Thompson /// @addtogroup CeedVectorUser 267a982d89SJeremy L. Thompson /// @{ 277a982d89SJeremy L. Thompson 28ca94c3ddSJeremy L Thompson /// Indicate that vector will be provided as an explicit argument to @ref CeedOperatorApply(). 297a982d89SJeremy L. Thompson const CeedVector CEED_VECTOR_ACTIVE = &ceed_vector_active; 307a982d89SJeremy L. Thompson 3196b902e2Sjeremylt /// Indicate that no vector is applicable (i.e., for @ref CEED_EVAL_WEIGHT). 327a982d89SJeremy L. Thompson const CeedVector CEED_VECTOR_NONE = &ceed_vector_none; 337a982d89SJeremy L. Thompson 347a982d89SJeremy L. Thompson /// @} 357a982d89SJeremy L. Thompson 367a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 377a982d89SJeremy L. Thompson /// CeedVector Backend API 387a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 397a982d89SJeremy L. Thompson /// @addtogroup CeedVectorBackend 407a982d89SJeremy L. Thompson /// @{ 417a982d89SJeremy L. Thompson 427a982d89SJeremy L. Thompson /** 43ca94c3ddSJeremy L Thompson @brief Check for valid data in a `CeedVector` 449c774eddSJeremy L Thompson 45ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to check validity 469c774eddSJeremy L Thompson @param[out] has_valid_array Variable to store validity 479c774eddSJeremy L Thompson 489c774eddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 499c774eddSJeremy L Thompson 509c774eddSJeremy L Thompson @ref Backend 519c774eddSJeremy L Thompson **/ 529c774eddSJeremy L Thompson int CeedVectorHasValidArray(CeedVector vec, bool *has_valid_array) { 531203703bSJeremy L Thompson CeedSize length; 541203703bSJeremy L Thompson 556e536b99SJeremy L Thompson CeedCheck(vec->HasValidArray, CeedVectorReturnCeed(vec), CEED_ERROR_UNSUPPORTED, "Backend does not support CeedVectorHasValidArray"); 561203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 571203703bSJeremy L Thompson if (length == 0) { 58b0976d5aSZach Atkins *has_valid_array = true; 59b0976d5aSZach Atkins return CEED_ERROR_SUCCESS; 60b0976d5aSZach Atkins } 612b730f8bSJeremy L Thompson CeedCall(vec->HasValidArray(vec, has_valid_array)); 629c774eddSJeremy L Thompson return CEED_ERROR_SUCCESS; 639c774eddSJeremy L Thompson } 649c774eddSJeremy L Thompson 659c774eddSJeremy L Thompson /** 66ca94c3ddSJeremy L Thompson @brief Check for borrowed array of a specific @ref CeedMemType in a `CeedVector` 679c774eddSJeremy L Thompson 68ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to check 69ea61e9acSJeremy L Thompson @param[in] mem_type Memory type to check 709c774eddSJeremy L Thompson @param[out] has_borrowed_array_of_type Variable to store result 719c774eddSJeremy L Thompson 729c774eddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 739c774eddSJeremy L Thompson 749c774eddSJeremy L Thompson @ref Backend 759c774eddSJeremy L Thompson **/ 762b730f8bSJeremy L Thompson int CeedVectorHasBorrowedArrayOfType(CeedVector vec, CeedMemType mem_type, bool *has_borrowed_array_of_type) { 776e536b99SJeremy L Thompson CeedCheck(vec->HasBorrowedArrayOfType, CeedVectorReturnCeed(vec), CEED_ERROR_UNSUPPORTED, 786e536b99SJeremy L Thompson "Backend does not support CeedVectorHasBorrowedArrayOfType"); 792b730f8bSJeremy L Thompson CeedCall(vec->HasBorrowedArrayOfType(vec, mem_type, has_borrowed_array_of_type)); 809c774eddSJeremy L Thompson return CEED_ERROR_SUCCESS; 819c774eddSJeremy L Thompson } 829c774eddSJeremy L Thompson 839c774eddSJeremy L Thompson /** 84ca94c3ddSJeremy L Thompson @brief Get the state of a `CeedVector` 857a982d89SJeremy L. Thompson 86ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to retrieve state 877a982d89SJeremy L. Thompson @param[out] state Variable to store state 887a982d89SJeremy L. Thompson 897a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 907a982d89SJeremy L. Thompson 917a982d89SJeremy L. Thompson @ref Backend 927a982d89SJeremy L. Thompson **/ 937a982d89SJeremy L. Thompson int CeedVectorGetState(CeedVector vec, uint64_t *state) { 947a982d89SJeremy L. Thompson *state = vec->state; 95e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 967a982d89SJeremy L. Thompson } 977a982d89SJeremy L. Thompson 987a982d89SJeremy L. Thompson /** 99ca94c3ddSJeremy L Thompson @brief Get the backend data of a `CeedVector` 1007a982d89SJeremy L. Thompson 101ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to retrieve state 1027a982d89SJeremy L. Thompson @param[out] data Variable to store data 1037a982d89SJeremy L. Thompson 1047a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1057a982d89SJeremy L. Thompson 1067a982d89SJeremy L. Thompson @ref Backend 1077a982d89SJeremy L. Thompson **/ 108777ff853SJeremy L Thompson int CeedVectorGetData(CeedVector vec, void *data) { 109777ff853SJeremy L Thompson *(void **)data = vec->data; 110e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1117a982d89SJeremy L. Thompson } 1127a982d89SJeremy L. Thompson 1137a982d89SJeremy L. Thompson /** 114ca94c3ddSJeremy L Thompson @brief Set the backend data of a `CeedVector` 1157a982d89SJeremy L. Thompson 116ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` to retrieve state 117ea61e9acSJeremy L Thompson @param[in] data Data to set 1187a982d89SJeremy L. Thompson 1197a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1207a982d89SJeremy L. Thompson 1217a982d89SJeremy L. Thompson @ref Backend 1227a982d89SJeremy L. Thompson **/ 123777ff853SJeremy L Thompson int CeedVectorSetData(CeedVector vec, void *data) { 124777ff853SJeremy L Thompson vec->data = data; 125e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1267a982d89SJeremy L. Thompson } 1277a982d89SJeremy L. Thompson 12834359f16Sjeremylt /** 129ca94c3ddSJeremy L Thompson @brief Increment the reference counter for a `CeedVector` 13034359f16Sjeremylt 131ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` to increment the reference counter 13234359f16Sjeremylt 13334359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 13434359f16Sjeremylt 13534359f16Sjeremylt @ref Backend 13634359f16Sjeremylt **/ 1379560d06aSjeremylt int CeedVectorReference(CeedVector vec) { 13834359f16Sjeremylt vec->ref_count++; 13934359f16Sjeremylt return CEED_ERROR_SUCCESS; 14034359f16Sjeremylt } 14134359f16Sjeremylt 1427a982d89SJeremy L. Thompson /// @} 1437a982d89SJeremy L. Thompson 1447a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1457a982d89SJeremy L. Thompson /// CeedVector Public API 1467a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1477a982d89SJeremy L. Thompson /// @addtogroup CeedVectorUser 1480436c2adSjeremylt /// @{ 1490436c2adSjeremylt 1500436c2adSjeremylt /** 151ca94c3ddSJeremy L Thompson @brief Create a `CeedVector` of the specified length (does not allocate memory) 1520436c2adSjeremylt 153ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` object used to create the `CeedVector` 154ea61e9acSJeremy L Thompson @param[in] length Length of vector 155ca94c3ddSJeremy L Thompson @param[out] vec Address of the variable where the newly created `CeedVector` will be stored 1560436c2adSjeremylt 1570436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 1580436c2adSjeremylt 1597a982d89SJeremy L. Thompson @ref User 1600436c2adSjeremylt **/ 1611f9221feSJeremy L Thompson int CeedVectorCreate(Ceed ceed, CeedSize length, CeedVector *vec) { 1620436c2adSjeremylt if (!ceed->VectorCreate) { 1630436c2adSjeremylt Ceed delegate; 1646574a04fSJeremy L Thompson 1652b730f8bSJeremy L Thompson CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Vector")); 166*1ef3a2a9SJeremy L Thompson CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement VectorCreate"); 1672b730f8bSJeremy L Thompson CeedCall(CeedVectorCreate(delegate, length, vec)); 168e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1690436c2adSjeremylt } 1700436c2adSjeremylt 1712b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, vec)); 172db002c03SJeremy L Thompson CeedCall(CeedReferenceCopy(ceed, &(*vec)->ceed)); 173d1d35e2fSjeremylt (*vec)->ref_count = 1; 1740436c2adSjeremylt (*vec)->length = length; 1750436c2adSjeremylt (*vec)->state = 0; 1762b730f8bSJeremy L Thompson CeedCall(ceed->VectorCreate(length, *vec)); 177e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1780436c2adSjeremylt } 1790436c2adSjeremylt 1800436c2adSjeremylt /** 181ca94c3ddSJeremy L Thompson @brief Copy the pointer to a `CeedVector`. 1824385fb7fSSebastian Grimberg 183ca94c3ddSJeremy L Thompson Both pointers should be destroyed with @ref CeedVectorDestroy(). 184512bb800SJeremy L Thompson 185ca94c3ddSJeremy L Thompson Note: If the value of `*vec_copy` passed to this function is non-`NULL`, then it is assumed that `*vec_copy` is a pointer to a `CeedVector`. 186ca94c3ddSJeremy L Thompson This `CeedVector` will be destroyed if `*vec_copy` is the only reference to this `CeedVector`. 1879560d06aSjeremylt 188ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to copy reference to 189ea61e9acSJeremy L Thompson @param[in,out] vec_copy Variable to store copied reference 1909560d06aSjeremylt 1919560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 1929560d06aSjeremylt 1939560d06aSjeremylt @ref User 1949560d06aSjeremylt **/ 1959560d06aSjeremylt int CeedVectorReferenceCopy(CeedVector vec, CeedVector *vec_copy) { 196393ac2cdSJeremy L Thompson if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) CeedCall(CeedVectorReference(vec)); 1972b730f8bSJeremy L Thompson CeedCall(CeedVectorDestroy(vec_copy)); 1989560d06aSjeremylt *vec_copy = vec; 1999560d06aSjeremylt return CEED_ERROR_SUCCESS; 2009560d06aSjeremylt } 2019560d06aSjeremylt 2029560d06aSjeremylt /** 203ca94c3ddSJeremy L Thompson @brief Copy a `CeedVector` into a different `CeedVector`. 2044385fb7fSSebastian Grimberg 205ca94c3ddSJeremy L Thompson Both pointers should be destroyed with @ref CeedVectorDestroy(). 2064385fb7fSSebastian Grimberg 207ca94c3ddSJeremy L Thompson Note: If `*vec_copy` is non-`NULL`, then it is assumed that `*vec_copy` is a pointer to a `CeedVector`. 208ca94c3ddSJeremy L Thompson This `CeedVector` will be destroyed if `*vec_copy` is the only reference to this `CeedVector`. 2095fb68f37SKaren (Ren) Stengel 210ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to copy 211ca94c3ddSJeremy L Thompson @param[in,out] vec_copy Variable to store copied `CeedVector` to 2125fb68f37SKaren (Ren) Stengel 2135fb68f37SKaren (Ren) Stengel @return An error code: 0 - success, otherwise - failure 2145fb68f37SKaren (Ren) Stengel 2155fb68f37SKaren (Ren) Stengel @ref User 2165fb68f37SKaren (Ren) Stengel **/ 2175fb68f37SKaren (Ren) Stengel int CeedVectorCopy(CeedVector vec, CeedVector vec_copy) { 2185fb68f37SKaren (Ren) Stengel Ceed ceed; 2195fb68f37SKaren (Ren) Stengel CeedMemType mem_type, mem_type_copy; 2205fb68f37SKaren (Ren) Stengel CeedScalar *array; 2215fb68f37SKaren (Ren) Stengel 2225fb68f37SKaren (Ren) Stengel // Get the preferred memory type 223d77c2f5dSJeremy L Thompson CeedCall(CeedVectorGetCeed(vec, &ceed)); 224d77c2f5dSJeremy L Thompson CeedCall(CeedGetPreferredMemType(ceed, &mem_type)); 2255fb68f37SKaren (Ren) Stengel 2265fb68f37SKaren (Ren) Stengel // Get the preferred memory type 227d77c2f5dSJeremy L Thompson CeedCall(CeedVectorGetCeed(vec_copy, &ceed)); 228d77c2f5dSJeremy L Thompson CeedCall(CeedGetPreferredMemType(ceed, &mem_type_copy)); 2295fb68f37SKaren (Ren) Stengel 2305fb68f37SKaren (Ren) Stengel // Check that both have same memory type 2315fb68f37SKaren (Ren) Stengel if (mem_type != mem_type_copy) mem_type = CEED_MEM_HOST; 2325fb68f37SKaren (Ren) Stengel 2335fb68f37SKaren (Ren) Stengel // Copy the values from vec to vec_copy 2345fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorGetArray(vec, mem_type, &array)); 2355fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorSetArray(vec_copy, mem_type, CEED_COPY_VALUES, array)); 2365fb68f37SKaren (Ren) Stengel 2375fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorRestoreArray(vec, &array)); 2385fb68f37SKaren (Ren) Stengel return CEED_ERROR_SUCCESS; 2395fb68f37SKaren (Ren) Stengel } 2405fb68f37SKaren (Ren) Stengel 2415fb68f37SKaren (Ren) Stengel /** 242ca94c3ddSJeremy L Thompson @brief Set the array used by a `CeedVector`, freeing any previously allocated array if applicable. 2434385fb7fSSebastian Grimberg 244ca94c3ddSJeremy L Thompson The backend may copy values to a different @ref CeedMemType, such as during @ref CeedOperatorApply(). 2456a6c615bSJeremy L Thompson See also @ref CeedVectorSyncArray() and @ref CeedVectorTakeArray(). 2460436c2adSjeremylt 247ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` 248ea61e9acSJeremy L Thompson @param[in] mem_type Memory type of the array being passed 249ea61e9acSJeremy L Thompson @param[in] copy_mode Copy mode for the array 250ca94c3ddSJeremy L Thompson @param[in] array Array to be used, or `NULL` with @ref CEED_COPY_VALUES to have the library allocate 2510436c2adSjeremylt 2520436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 2530436c2adSjeremylt 2547a982d89SJeremy L. Thompson @ref User 2550436c2adSjeremylt **/ 2562b730f8bSJeremy L Thompson int CeedVectorSetArray(CeedVector vec, CeedMemType mem_type, CeedCopyMode copy_mode, CeedScalar *array) { 2571203703bSJeremy L Thompson CeedSize length; 2581203703bSJeremy L Thompson Ceed ceed; 2590436c2adSjeremylt 2601203703bSJeremy L Thompson CeedCall(CeedVectorGetCeed(vec, &ceed)); 2611203703bSJeremy L Thompson 2621203703bSJeremy L Thompson CeedCheck(vec->SetArray, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support VectorSetArray"); 2631203703bSJeremy L Thompson CeedCheck(vec->state % 2 == 0, ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, the access lock is already in use"); 2641203703bSJeremy L Thompson CeedCheck(vec->num_readers == 0, ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, a process has read access"); 2651203703bSJeremy L Thompson 2661203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 2671203703bSJeremy L Thompson if (length > 0) CeedCall(vec->SetArray(vec, mem_type, copy_mode, array)); 2680436c2adSjeremylt vec->state += 2; 269e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2700436c2adSjeremylt } 2710436c2adSjeremylt 2720436c2adSjeremylt /** 273ca94c3ddSJeremy L Thompson @brief Set the `CeedVector` to a constant value 2740436c2adSjeremylt 275ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` 2760436c2adSjeremylt @param[in] value Value to be used 2770436c2adSjeremylt 2780436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 2790436c2adSjeremylt 2807a982d89SJeremy L. Thompson @ref User 2810436c2adSjeremylt **/ 2820436c2adSjeremylt int CeedVectorSetValue(CeedVector vec, CeedScalar value) { 2831203703bSJeremy L Thompson Ceed ceed; 2841203703bSJeremy L Thompson 2851203703bSJeremy L Thompson CeedCall(CeedVectorGetCeed(vec, &ceed)); 2861203703bSJeremy L Thompson CeedCheck(vec->state % 2 == 0, ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, the access lock is already in use"); 2871203703bSJeremy L Thompson CeedCheck(vec->num_readers == 0, ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, a process has read access"); 2880436c2adSjeremylt 2890436c2adSjeremylt if (vec->SetValue) { 2902b730f8bSJeremy L Thompson CeedCall(vec->SetValue(vec, value)); 2910436c2adSjeremylt } else { 2921203703bSJeremy L Thompson CeedSize length; 2930436c2adSjeremylt CeedScalar *array; 2941203703bSJeremy L Thompson 2952b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayWrite(vec, CEED_MEM_HOST, &array)); 2961203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 2971203703bSJeremy L Thompson for (CeedSize i = 0; i < length; i++) array[i] = value; 2982b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArray(vec, &array)); 2990436c2adSjeremylt } 3000436c2adSjeremylt vec->state += 2; 301e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3020436c2adSjeremylt } 3030436c2adSjeremylt 3040436c2adSjeremylt /** 305ca94c3ddSJeremy L Thompson @brief Sync the `CeedVector` to a specified `mem_type`. 3064385fb7fSSebastian Grimberg 307ea61e9acSJeremy L Thompson This function is used to force synchronization of arrays set with @ref CeedVectorSetArray(). 308ca94c3ddSJeremy L Thompson If the requested `mem_type` is already synchronized, this function results in a no-op. 3090436c2adSjeremylt 310ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` 311ca94c3ddSJeremy L Thompson @param[in] mem_type @ref CeedMemType to be synced 3120436c2adSjeremylt 3130436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 3140436c2adSjeremylt 3157a982d89SJeremy L. Thompson @ref User 3160436c2adSjeremylt **/ 317d1d35e2fSjeremylt int CeedVectorSyncArray(CeedVector vec, CeedMemType mem_type) { 3181203703bSJeremy L Thompson CeedSize length; 3191203703bSJeremy L Thompson 3206e536b99SJeremy L Thompson CeedCheck(vec->state % 2 == 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, "Cannot sync CeedVector, the access lock is already in use"); 3210436c2adSjeremylt 322b0976d5aSZach Atkins // Don't sync empty array 3231203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 3241203703bSJeremy L Thompson if (length == 0) return CEED_ERROR_SUCCESS; 325b0976d5aSZach Atkins 3260436c2adSjeremylt if (vec->SyncArray) { 3272b730f8bSJeremy L Thompson CeedCall(vec->SyncArray(vec, mem_type)); 3280436c2adSjeremylt } else { 3290436c2adSjeremylt const CeedScalar *array; 3301203703bSJeremy L Thompson 3312b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(vec, mem_type, &array)); 3322b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArrayRead(vec, &array)); 3330436c2adSjeremylt } 334e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3350436c2adSjeremylt } 3360436c2adSjeremylt 3370436c2adSjeremylt /** 338ca94c3ddSJeremy L Thompson @brief Take ownership of the `CeedVector` array set by @ref CeedVectorSetArray() with @ref CEED_USE_POINTER and remove the array from the `CeedVector`. 3394385fb7fSSebastian Grimberg 3409c774eddSJeremy L Thompson The caller is responsible for managing and freeing the array. 341ea61e9acSJeremy L Thompson This function will error if @ref CeedVectorSetArray() was not previously called with @ref CEED_USE_POINTER for the corresponding mem_type. 3426a6c615bSJeremy L Thompson 343ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` 344ea61e9acSJeremy L Thompson @param[in] mem_type Memory type on which to take the array. 345ea61e9acSJeremy L Thompson If the backend uses a different memory type, this will perform a copy. 346ca94c3ddSJeremy L Thompson @param[out] array Array on memory type `mem_type`, or `NULL` if array pointer is not required 3476a6c615bSJeremy L Thompson 3486a6c615bSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 3496a6c615bSJeremy L Thompson 3506a6c615bSJeremy L Thompson @ref User 3516a6c615bSJeremy L Thompson **/ 3522b730f8bSJeremy L Thompson int CeedVectorTakeArray(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 3531203703bSJeremy L Thompson CeedSize length; 3541c66c397SJeremy L Thompson CeedScalar *temp_array = NULL; 3551203703bSJeremy L Thompson Ceed ceed; 3561c66c397SJeremy L Thompson 3571203703bSJeremy L Thompson CeedCall(CeedVectorGetCeed(vec, &ceed)); 3581203703bSJeremy L Thompson CeedCheck(vec->state % 2 == 0, ceed, CEED_ERROR_ACCESS, "Cannot take CeedVector array, the access lock is already in use"); 3591203703bSJeremy L Thompson CeedCheck(vec->num_readers == 0, ceed, CEED_ERROR_ACCESS, "Cannot take CeedVector array, a process has read access"); 3606a6c615bSJeremy L Thompson 3611203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 3621203703bSJeremy L Thompson if (length > 0) { 3631203703bSJeremy L Thompson bool has_borrowed_array_of_type = true, has_valid_array = true; 3641203703bSJeremy L Thompson 3652b730f8bSJeremy L Thompson CeedCall(CeedVectorHasBorrowedArrayOfType(vec, mem_type, &has_borrowed_array_of_type)); 3661203703bSJeremy L Thompson CeedCheck(has_borrowed_array_of_type, ceed, CEED_ERROR_BACKEND, "CeedVector has no borrowed %s array, must set array with CeedVectorSetArray", 3671203703bSJeremy L Thompson CeedMemTypes[mem_type]); 3689c774eddSJeremy L Thompson 3692b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(vec, &has_valid_array)); 3701203703bSJeremy L Thompson CeedCheck(has_valid_array, ceed, CEED_ERROR_BACKEND, 3712b730f8bSJeremy L Thompson "CeedVector has no valid data to take, must set data with CeedVectorSetValue or CeedVectorSetArray"); 3729c774eddSJeremy L Thompson 3732b730f8bSJeremy L Thompson CeedCall(vec->TakeArray(vec, mem_type, &temp_array)); 37450c643e1SJed Brown } 375d1d35e2fSjeremylt if (array) (*array) = temp_array; 376e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3776a6c615bSJeremy L Thompson } 3786a6c615bSJeremy L Thompson 3796a6c615bSJeremy L Thompson /** 380ca94c3ddSJeremy L Thompson @brief Get read/write access to a `CeedVector` via the specified memory type. 3814385fb7fSSebastian Grimberg 382b3cf021fSjeremylt Restore access with @ref CeedVectorRestoreArray(). 3830436c2adSjeremylt 384ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` to access 385ea61e9acSJeremy L Thompson @param[in] mem_type Memory type on which to access the array. 386ea61e9acSJeremy L Thompson If the backend uses a different memory type, this will perform a copy. 387ca94c3ddSJeremy L Thompson @param[out] array Array on memory type `mem_type` 3880436c2adSjeremylt 389ca94c3ddSJeremy L Thompson @note The @ref CeedVectorGetArray() and @ref CeedVectorRestoreArray() functions provide access to array pointers in the desired memory space. 390ca94c3ddSJeremy L Thompson Pairing get/restore allows the `CeedVector` to track access, thus knowing if norms or other operations may need to be recomputed. 3910436c2adSjeremylt 3920436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 3930436c2adSjeremylt 3947a982d89SJeremy L. Thompson @ref User 3950436c2adSjeremylt **/ 3962b730f8bSJeremy L Thompson int CeedVectorGetArray(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 3971203703bSJeremy L Thompson CeedSize length; 3981203703bSJeremy L Thompson Ceed ceed; 3990436c2adSjeremylt 4001203703bSJeremy L Thompson CeedCall(CeedVectorGetCeed(vec, &ceed)); 4011203703bSJeremy L Thompson CeedCheck(vec->GetArray, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetArray"); 4021203703bSJeremy L Thompson CeedCheck(vec->state % 2 == 0, ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, the access lock is already in use"); 4031203703bSJeremy L Thompson CeedCheck(vec->num_readers == 0, ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, a process has read access"); 4041203703bSJeremy L Thompson 4051203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 4061203703bSJeremy L Thompson if (length > 0) { 4079c774eddSJeremy L Thompson bool has_valid_array = true; 408b0976d5aSZach Atkins 4092b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(vec, &has_valid_array)); 4101203703bSJeremy L Thompson CeedCheck(has_valid_array, ceed, CEED_ERROR_BACKEND, 4112b730f8bSJeremy L Thompson "CeedVector has no valid data to read, must set data with CeedVectorSetValue or CeedVectorSetArray"); 4129c774eddSJeremy L Thompson 4132b730f8bSJeremy L Thompson CeedCall(vec->GetArray(vec, mem_type, array)); 414b0976d5aSZach Atkins } else { 415b0976d5aSZach Atkins *array = NULL; 416b0976d5aSZach Atkins } 41728bfd0b7SJeremy L Thompson vec->state++; 418e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4190436c2adSjeremylt } 4200436c2adSjeremylt 4210436c2adSjeremylt /** 422ca94c3ddSJeremy L Thompson @brief Get read-only access to a `CeedVector` via the specified memory type. 4234385fb7fSSebastian Grimberg 424b3cf021fSjeremylt Restore access with @ref CeedVectorRestoreArrayRead(). 4250436c2adSjeremylt 426ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to access 427ca94c3ddSJeremy L Thompson @param[in] mem_type Memory type on which to access the array. 428ca94c3ddSJeremy L Thompson If the backend uses a different memory type, this will perform a copy (possibly cached). 429ca94c3ddSJeremy L Thompson @param[out] array Array on memory type `mem_type` 4300436c2adSjeremylt 4310436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 4320436c2adSjeremylt 4337a982d89SJeremy L. Thompson @ref User 4340436c2adSjeremylt **/ 4352b730f8bSJeremy L Thompson int CeedVectorGetArrayRead(CeedVector vec, CeedMemType mem_type, const CeedScalar **array) { 4361203703bSJeremy L Thompson CeedSize length; 4371203703bSJeremy L Thompson Ceed ceed; 4380436c2adSjeremylt 4391203703bSJeremy L Thompson CeedCall(CeedVectorGetCeed(vec, &ceed)); 4401203703bSJeremy L Thompson CeedCheck(vec->GetArrayRead, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetArrayRead"); 4411203703bSJeremy L Thompson CeedCheck(vec->state % 2 == 0, ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector read-only array access, the access lock is already in use"); 4421203703bSJeremy L Thompson 4431203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 4441203703bSJeremy L Thompson if (length > 0) { 4459c774eddSJeremy L Thompson bool has_valid_array = true; 446b0976d5aSZach Atkins 4472b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(vec, &has_valid_array)); 4481203703bSJeremy L Thompson CeedCheck(has_valid_array, ceed, CEED_ERROR_BACKEND, 4492b730f8bSJeremy L Thompson "CeedVector has no valid data to read, must set data with CeedVectorSetValue or CeedVectorSetArray"); 4509c774eddSJeremy L Thompson 4512b730f8bSJeremy L Thompson CeedCall(vec->GetArrayRead(vec, mem_type, array)); 45250c643e1SJed Brown } else { 45350c643e1SJed Brown *array = NULL; 45450c643e1SJed Brown } 455d1d35e2fSjeremylt vec->num_readers++; 456e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4570436c2adSjeremylt } 4580436c2adSjeremylt 4590436c2adSjeremylt /** 460ca94c3ddSJeremy L Thompson @brief Get write access to a `CeedVector` via the specified memory type. 4614385fb7fSSebastian Grimberg 462ea61e9acSJeremy L Thompson Restore access with @ref CeedVectorRestoreArray(). 463ea61e9acSJeremy L Thompson All old values should be assumed to be invalid. 4649c774eddSJeremy L Thompson 465ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` to access 466ea61e9acSJeremy L Thompson @param[in] mem_type Memory type on which to access the array. 467ca94c3ddSJeremy L Thompson @param[out] array Array on memory type `mem_type` 4689c774eddSJeremy L Thompson 4699c774eddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 4709c774eddSJeremy L Thompson 4719c774eddSJeremy L Thompson @ref User 4729c774eddSJeremy L Thompson **/ 4732b730f8bSJeremy L Thompson int CeedVectorGetArrayWrite(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 4741203703bSJeremy L Thompson CeedSize length; 4751203703bSJeremy L Thompson Ceed ceed; 4769c774eddSJeremy L Thompson 4771203703bSJeremy L Thompson CeedCall(CeedVectorGetCeed(vec, &ceed)); 4781203703bSJeremy L Thompson CeedCheck(vec->GetArrayWrite, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedVectorGetArrayWrite"); 4791203703bSJeremy L Thompson CeedCheck(vec->state % 2 == 0, ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, the access lock is already in use"); 4801203703bSJeremy L Thompson CeedCheck(vec->num_readers == 0, ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, a process has read access"); 4811203703bSJeremy L Thompson 4821203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 4831203703bSJeremy L Thompson if (length > 0) { 4842b730f8bSJeremy L Thompson CeedCall(vec->GetArrayWrite(vec, mem_type, array)); 485b0976d5aSZach Atkins } else { 486b0976d5aSZach Atkins *array = NULL; 487b0976d5aSZach Atkins } 48828bfd0b7SJeremy L Thompson vec->state++; 4899c774eddSJeremy L Thompson return CEED_ERROR_SUCCESS; 4909c774eddSJeremy L Thompson } 4919c774eddSJeremy L Thompson 4929c774eddSJeremy L Thompson /** 493ea61e9acSJeremy L Thompson @brief Restore an array obtained using @ref CeedVectorGetArray() or @ref CeedVectorGetArrayWrite() 4940436c2adSjeremylt 495ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` to restore 496ea61e9acSJeremy L Thompson @param[in,out] array Array of vector data 4970436c2adSjeremylt 4980436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 4990436c2adSjeremylt 5007a982d89SJeremy L. Thompson @ref User 5010436c2adSjeremylt **/ 5020436c2adSjeremylt int CeedVectorRestoreArray(CeedVector vec, CeedScalar **array) { 5031203703bSJeremy L Thompson CeedSize length; 5041203703bSJeremy L Thompson 5056e536b99SJeremy L Thompson CeedCheck(vec->state % 2 == 1, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, "Cannot restore CeedVector array access, access was not granted"); 5061203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 5071203703bSJeremy L Thompson if (length > 0 && vec->RestoreArray) CeedCall(vec->RestoreArray(vec)); 5080436c2adSjeremylt *array = NULL; 50928bfd0b7SJeremy L Thompson vec->state++; 510e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5110436c2adSjeremylt } 5120436c2adSjeremylt 5130436c2adSjeremylt /** 514b3cf021fSjeremylt @brief Restore an array obtained using @ref CeedVectorGetArrayRead() 5150436c2adSjeremylt 516ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to restore 517ea61e9acSJeremy L Thompson @param[in,out] array Array of vector data 5180436c2adSjeremylt 5190436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 5200436c2adSjeremylt 5217a982d89SJeremy L. Thompson @ref User 5220436c2adSjeremylt **/ 5230436c2adSjeremylt int CeedVectorRestoreArrayRead(CeedVector vec, const CeedScalar **array) { 5241203703bSJeremy L Thompson CeedSize length; 5251203703bSJeremy L Thompson 5266e536b99SJeremy L Thompson CeedCheck(vec->num_readers > 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, 5276e536b99SJeremy L Thompson "Cannot restore CeedVector array read access, access was not granted"); 52875a19770SJeremy L Thompson vec->num_readers--; 5291203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 5301203703bSJeremy L Thompson if (length > 0 && vec->num_readers == 0 && vec->RestoreArrayRead) CeedCall(vec->RestoreArrayRead(vec)); 5310436c2adSjeremylt *array = NULL; 532e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5330436c2adSjeremylt } 5340436c2adSjeremylt 5350436c2adSjeremylt /** 536ca94c3ddSJeremy L Thompson @brief Get the norm of a `CeedVector`. 537171f8ca9Sjeremylt 538ca94c3ddSJeremy L Thompson Note: This operation is local to the `CeedVector`. 539ca94c3ddSJeremy L Thompson This function will likely not provide the desired results for the norm of the libCEED portion of a parallel vector or a `CeedVector` with duplicated or hanging nodes. 540547d9b97Sjeremylt 541ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to retrieve maximum value 542ea61e9acSJeremy L Thompson @param[in] norm_type Norm type @ref CEED_NORM_1, @ref CEED_NORM_2, or @ref CEED_NORM_MAX 543547d9b97Sjeremylt @param[out] norm Variable to store norm value 544547d9b97Sjeremylt 545547d9b97Sjeremylt @return An error code: 0 - success, otherwise - failure 546547d9b97Sjeremylt 5477a982d89SJeremy L. Thompson @ref User 548547d9b97Sjeremylt **/ 549d1d35e2fSjeremylt int CeedVectorNorm(CeedVector vec, CeedNormType norm_type, CeedScalar *norm) { 5509c774eddSJeremy L Thompson bool has_valid_array = true; 5511203703bSJeremy L Thompson CeedSize length; 5521203703bSJeremy L Thompson 5532b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(vec, &has_valid_array)); 5546e536b99SJeremy L Thompson CeedCheck(has_valid_array, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, 5552b730f8bSJeremy L Thompson "CeedVector has no valid data to compute norm, must set data with CeedVectorSetValue or CeedVectorSetArray"); 5569c774eddSJeremy L Thompson 5571203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 5581203703bSJeremy L Thompson if (length == 0) { 559b0976d5aSZach Atkins *norm = 0; 560b0976d5aSZach Atkins return CEED_ERROR_SUCCESS; 561b0976d5aSZach Atkins } 562b0976d5aSZach Atkins 563547d9b97Sjeremylt // Backend impl for GPU, if added 564547d9b97Sjeremylt if (vec->Norm) { 5652b730f8bSJeremy L Thompson CeedCall(vec->Norm(vec, norm_type, norm)); 566e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 567547d9b97Sjeremylt } 568547d9b97Sjeremylt 569547d9b97Sjeremylt const CeedScalar *array; 5702b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(vec, CEED_MEM_HOST, &array)); 571b0976d5aSZach Atkins assert(array); 572547d9b97Sjeremylt 573547d9b97Sjeremylt *norm = 0.; 574d1d35e2fSjeremylt switch (norm_type) { 575547d9b97Sjeremylt case CEED_NORM_1: 5761203703bSJeremy L Thompson for (CeedSize i = 0; i < length; i++) { 577547d9b97Sjeremylt *norm += fabs(array[i]); 578547d9b97Sjeremylt } 579547d9b97Sjeremylt break; 580547d9b97Sjeremylt case CEED_NORM_2: 5811203703bSJeremy L Thompson for (CeedSize i = 0; i < length; i++) { 582547d9b97Sjeremylt *norm += fabs(array[i]) * fabs(array[i]); 583547d9b97Sjeremylt } 584547d9b97Sjeremylt break; 585547d9b97Sjeremylt case CEED_NORM_MAX: 5861203703bSJeremy L Thompson for (CeedSize i = 0; i < length; i++) { 587d1d35e2fSjeremylt const CeedScalar abs_v_i = fabs(array[i]); 588d1d35e2fSjeremylt *norm = *norm > abs_v_i ? *norm : abs_v_i; 589547d9b97Sjeremylt } 590547d9b97Sjeremylt } 5912b730f8bSJeremy L Thompson if (norm_type == CEED_NORM_2) *norm = sqrt(*norm); 592547d9b97Sjeremylt 5932b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArrayRead(vec, &array)); 594e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 595547d9b97Sjeremylt } 596547d9b97Sjeremylt 597547d9b97Sjeremylt /** 598ca94c3ddSJeremy L Thompson @brief Compute `x = alpha x` 599e0dd3b27Sjeremylt 600ca94c3ddSJeremy L Thompson @param[in,out] x `CeedVector` for scaling 60196b902e2Sjeremylt @param[in] alpha scaling factor 602e0dd3b27Sjeremylt 603e0dd3b27Sjeremylt @return An error code: 0 - success, otherwise - failure 604e0dd3b27Sjeremylt 605e0dd3b27Sjeremylt @ref User 606e0dd3b27Sjeremylt **/ 607e0dd3b27Sjeremylt int CeedVectorScale(CeedVector x, CeedScalar alpha) { 6089c774eddSJeremy L Thompson bool has_valid_array = true; 6091203703bSJeremy L Thompson CeedSize length; 6101203703bSJeremy L Thompson CeedScalar *x_array = NULL; 6111c66c397SJeremy L Thompson 6122b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(x, &has_valid_array)); 6136e536b99SJeremy L Thompson CeedCheck(has_valid_array, CeedVectorReturnCeed(x), CEED_ERROR_BACKEND, 6142b730f8bSJeremy L Thompson "CeedVector has no valid data to scale, must set data with CeedVectorSetValue or CeedVectorSetArray"); 6159c774eddSJeremy L Thompson 616b0976d5aSZach Atkins // Return early for empty vector 6171203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(x, &length)); 6181203703bSJeremy L Thompson if (length == 0) return CEED_ERROR_SUCCESS; 619b0976d5aSZach Atkins 620e0dd3b27Sjeremylt // Backend implementation 6212b730f8bSJeremy L Thompson if (x->Scale) return x->Scale(x, alpha); 622e0dd3b27Sjeremylt 623e0dd3b27Sjeremylt // Default implementation 624567d69a2SJeremy L Thompson CeedCall(CeedVectorGetArray(x, CEED_MEM_HOST, &x_array)); 625b0976d5aSZach Atkins assert(x_array); 6261203703bSJeremy L Thompson for (CeedSize i = 0; i < length; i++) x_array[i] *= alpha; 6272b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArray(x, &x_array)); 628e0dd3b27Sjeremylt return CEED_ERROR_SUCCESS; 629e0dd3b27Sjeremylt } 630e0dd3b27Sjeremylt 631e0dd3b27Sjeremylt /** 632ca94c3ddSJeremy L Thompson @brief Compute `y = alpha x + y` 6330f7fd0f8Sjeremylt 634ca94c3ddSJeremy L Thompson @param[in,out] y target `CeedVector` for sum 63596b902e2Sjeremylt @param[in] alpha scaling factor 636ca94c3ddSJeremy L Thompson @param[in] x second `CeedVector`, must be different than ``y` 6370f7fd0f8Sjeremylt 6380f7fd0f8Sjeremylt @return An error code: 0 - success, otherwise - failure 6390f7fd0f8Sjeremylt 6400f7fd0f8Sjeremylt @ref User 6410f7fd0f8Sjeremylt **/ 6420f7fd0f8Sjeremylt int CeedVectorAXPY(CeedVector y, CeedScalar alpha, CeedVector x) { 6431203703bSJeremy L Thompson bool has_valid_array_x = true, has_valid_array_y = true; 6441203703bSJeremy L Thompson CeedSize length_x, length_y; 64573380422SJeremy L Thompson CeedScalar *y_array = NULL; 64673380422SJeremy L Thompson CeedScalar const *x_array = NULL; 6471203703bSJeremy L Thompson Ceed ceed, ceed_parent_x, ceed_parent_y; 6480f7fd0f8Sjeremylt 6491203703bSJeremy L Thompson CeedCall(CeedVectorGetCeed(y, &ceed)); 6501203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(y, &length_y)); 6511203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(x, &length_x)); 6521203703bSJeremy L Thompson CeedCheck(length_x == length_y, ceed, CEED_ERROR_UNSUPPORTED, "Cannot add vector of different lengths"); 6531203703bSJeremy L Thompson CeedCheck(x != y, ceed, CEED_ERROR_UNSUPPORTED, "Cannot use same vector for x and y in CeedVectorAXPY"); 6540f7fd0f8Sjeremylt 6552b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(x, &has_valid_array_x)); 6561203703bSJeremy L Thompson CeedCheck(has_valid_array_x, ceed, CEED_ERROR_BACKEND, 6576574a04fSJeremy L Thompson "CeedVector x has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 6582b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(y, &has_valid_array_y)); 6591203703bSJeremy L Thompson CeedCheck(has_valid_array_y, ceed, CEED_ERROR_BACKEND, 6606574a04fSJeremy L Thompson "CeedVector y has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 6619c774eddSJeremy L Thompson 6622b730f8bSJeremy L Thompson CeedCall(CeedGetParent(x->ceed, &ceed_parent_x)); 6632b730f8bSJeremy L Thompson CeedCall(CeedGetParent(y->ceed, &ceed_parent_y)); 6641203703bSJeremy L Thompson CeedCheck(ceed_parent_x == ceed_parent_y, ceed, CEED_ERROR_INCOMPATIBLE, "Vectors x and y must be created by the same Ceed context"); 6652d04630dSjeremylt 666b0976d5aSZach Atkins // Return early for empty vectors 6671203703bSJeremy L Thompson if (length_y == 0) return CEED_ERROR_SUCCESS; 668b0976d5aSZach Atkins 6690f7fd0f8Sjeremylt // Backend implementation 670eaf62fffSJeremy L Thompson if (y->AXPY) { 6712b730f8bSJeremy L Thompson CeedCall(y->AXPY(y, alpha, x)); 672eaf62fffSJeremy L Thompson return CEED_ERROR_SUCCESS; 673eaf62fffSJeremy L Thompson } 6740f7fd0f8Sjeremylt 6750f7fd0f8Sjeremylt // Default implementation 676567d69a2SJeremy L Thompson CeedCall(CeedVectorGetArray(y, CEED_MEM_HOST, &y_array)); 6772b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(x, CEED_MEM_HOST, &x_array)); 6780f7fd0f8Sjeremylt 6792b730f8bSJeremy L Thompson assert(x_array); 6802b730f8bSJeremy L Thompson assert(y_array); 68173380422SJeremy L Thompson 6821203703bSJeremy L Thompson for (CeedSize i = 0; i < length_y; i++) y_array[i] += alpha * x_array[i]; 6830f7fd0f8Sjeremylt 6842b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArray(y, &y_array)); 6852b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArrayRead(x, &x_array)); 6860f7fd0f8Sjeremylt return CEED_ERROR_SUCCESS; 6870f7fd0f8Sjeremylt } 6880f7fd0f8Sjeremylt 6890f7fd0f8Sjeremylt /** 690ca94c3ddSJeremy L Thompson @brief Compute `y = alpha x + beta y` 6915fb68f37SKaren (Ren) Stengel 692ca94c3ddSJeremy L Thompson @param[in,out] y target `CeedVector` for sum 6935fb68f37SKaren (Ren) Stengel @param[in] alpha first scaling factor 6945fb68f37SKaren (Ren) Stengel @param[in] beta second scaling factor 695ca94c3ddSJeremy L Thompson @param[in] x second `CeedVector`, must be different than `y` 6965fb68f37SKaren (Ren) Stengel 6975fb68f37SKaren (Ren) Stengel @return An error code: 0 - success, otherwise - failure 6985fb68f37SKaren (Ren) Stengel 6995fb68f37SKaren (Ren) Stengel @ref User 7005fb68f37SKaren (Ren) Stengel **/ 7015fb68f37SKaren (Ren) Stengel int CeedVectorAXPBY(CeedVector y, CeedScalar alpha, CeedScalar beta, CeedVector x) { 7021203703bSJeremy L Thompson bool has_valid_array_x = true, has_valid_array_y = true; 7031203703bSJeremy L Thompson CeedSize length_x, length_y; 7045fb68f37SKaren (Ren) Stengel CeedScalar *y_array = NULL; 7055fb68f37SKaren (Ren) Stengel CeedScalar const *x_array = NULL; 7061203703bSJeremy L Thompson Ceed ceed, ceed_parent_x, ceed_parent_y; 7075fb68f37SKaren (Ren) Stengel 7081203703bSJeremy L Thompson CeedCall(CeedVectorGetCeed(y, &ceed)); 7091203703bSJeremy L Thompson 7101203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(y, &length_y)); 7111203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(x, &length_x)); 7121203703bSJeremy L Thompson CeedCheck(length_x == length_y, ceed, CEED_ERROR_UNSUPPORTED, "Cannot add vector of different lengths"); 7131203703bSJeremy L Thompson CeedCheck(x != y, ceed, CEED_ERROR_UNSUPPORTED, "Cannot use same vector for x and y in CeedVectorAXPBY"); 7145fb68f37SKaren (Ren) Stengel 7155fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorHasValidArray(x, &has_valid_array_x)); 7161203703bSJeremy L Thompson CeedCheck(has_valid_array_x, ceed, CEED_ERROR_BACKEND, 7176574a04fSJeremy L Thompson "CeedVector x has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 7185fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorHasValidArray(y, &has_valid_array_y)); 7191203703bSJeremy L Thompson CeedCheck(has_valid_array_y, ceed, CEED_ERROR_BACKEND, 7206574a04fSJeremy L Thompson "CeedVector y has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 7215fb68f37SKaren (Ren) Stengel 7225fb68f37SKaren (Ren) Stengel CeedCall(CeedGetParent(x->ceed, &ceed_parent_x)); 7235fb68f37SKaren (Ren) Stengel CeedCall(CeedGetParent(y->ceed, &ceed_parent_y)); 7241203703bSJeremy L Thompson CeedCheck(ceed_parent_x == ceed_parent_y, ceed, CEED_ERROR_INCOMPATIBLE, "Vectors x and y must be created by the same Ceed context"); 7255fb68f37SKaren (Ren) Stengel 726b0976d5aSZach Atkins // Return early for empty vectors 7271203703bSJeremy L Thompson if (length_y == 0) return CEED_ERROR_SUCCESS; 728b0976d5aSZach Atkins 7295fb68f37SKaren (Ren) Stengel // Backend implementation 7305fb68f37SKaren (Ren) Stengel if (y->AXPBY) { 7315fb68f37SKaren (Ren) Stengel CeedCall(y->AXPBY(y, alpha, beta, x)); 7325fb68f37SKaren (Ren) Stengel return CEED_ERROR_SUCCESS; 7335fb68f37SKaren (Ren) Stengel } 7345fb68f37SKaren (Ren) Stengel 7355fb68f37SKaren (Ren) Stengel // Default implementation 7365fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorGetArray(y, CEED_MEM_HOST, &y_array)); 7375fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorGetArrayRead(x, CEED_MEM_HOST, &x_array)); 7385fb68f37SKaren (Ren) Stengel 7395fb68f37SKaren (Ren) Stengel assert(x_array); 7405fb68f37SKaren (Ren) Stengel assert(y_array); 7415fb68f37SKaren (Ren) Stengel 7421203703bSJeremy L Thompson for (CeedSize i = 0; i < length_y; i++) y_array[i] = alpha * x_array[i] + beta * y_array[i]; 7435fb68f37SKaren (Ren) Stengel 7445fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorRestoreArray(y, &y_array)); 7455fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorRestoreArrayRead(x, &x_array)); 7465fb68f37SKaren (Ren) Stengel return CEED_ERROR_SUCCESS; 7475fb68f37SKaren (Ren) Stengel } 7485fb68f37SKaren (Ren) Stengel 7495fb68f37SKaren (Ren) Stengel /** 750ca94c3ddSJeremy L Thompson @brief Compute the pointwise multiplication \f$w = x .* y\f$. 7514385fb7fSSebastian Grimberg 752ca94c3ddSJeremy L Thompson Any subset of `x`, `y`, and `w` may be the same `CeedVector`. 7530f7fd0f8Sjeremylt 754ca94c3ddSJeremy L Thompson @param[out] w target `CeedVector` for the product 755ca94c3ddSJeremy L Thompson @param[in] x first `CeedVector` for product 756ca94c3ddSJeremy L Thompson @param[in] y second `CeedVector` for the product 7570f7fd0f8Sjeremylt 7580f7fd0f8Sjeremylt @return An error code: 0 - success, otherwise - failure 7590f7fd0f8Sjeremylt 7600f7fd0f8Sjeremylt @ref User 7610f7fd0f8Sjeremylt **/ 7620f7fd0f8Sjeremylt int CeedVectorPointwiseMult(CeedVector w, CeedVector x, CeedVector y) { 7631203703bSJeremy L Thompson bool has_valid_array_x = true, has_valid_array_y = true; 76473380422SJeremy L Thompson CeedScalar *w_array = NULL; 76573380422SJeremy L Thompson CeedScalar const *x_array = NULL, *y_array = NULL; 7661203703bSJeremy L Thompson CeedSize length_w, length_x, length_y; 7671203703bSJeremy L Thompson Ceed ceed, ceed_parent_w, ceed_parent_x, ceed_parent_y; 7680f7fd0f8Sjeremylt 7691203703bSJeremy L Thompson CeedCall(CeedVectorGetCeed(w, &ceed)); 7701203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(w, &length_w)); 7711203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(x, &length_x)); 7721203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(y, &length_y)); 7731203703bSJeremy L Thompson CeedCheck(length_w == length_x && length_w == length_y, ceed, CEED_ERROR_UNSUPPORTED, "Cannot multiply vectors of different lengths"); 7740f7fd0f8Sjeremylt 7752b730f8bSJeremy L Thompson CeedCall(CeedGetParent(w->ceed, &ceed_parent_w)); 7762b730f8bSJeremy L Thompson CeedCall(CeedGetParent(x->ceed, &ceed_parent_x)); 7772b730f8bSJeremy L Thompson CeedCall(CeedGetParent(y->ceed, &ceed_parent_y)); 7781203703bSJeremy L Thompson CeedCheck(ceed_parent_w == ceed_parent_x && ceed_parent_w == ceed_parent_y, ceed, CEED_ERROR_INCOMPATIBLE, 7796574a04fSJeremy L Thompson "Vectors w, x, and y must be created by the same Ceed context"); 7802d04630dSjeremylt 7812b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(x, &has_valid_array_x)); 7821203703bSJeremy L Thompson CeedCheck(has_valid_array_x, ceed, CEED_ERROR_BACKEND, 7836574a04fSJeremy L Thompson "CeedVector x has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 7842b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(y, &has_valid_array_y)); 7851203703bSJeremy L Thompson CeedCheck(has_valid_array_y, ceed, CEED_ERROR_BACKEND, 7866574a04fSJeremy L Thompson "CeedVector y has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 7879c774eddSJeremy L Thompson 788b0976d5aSZach Atkins // Return early for empty vectors 7891203703bSJeremy L Thompson if (length_w == 0) return CEED_ERROR_SUCCESS; 790b0976d5aSZach Atkins 7910f7fd0f8Sjeremylt // Backend implementation 792eaf62fffSJeremy L Thompson if (w->PointwiseMult) { 7932b730f8bSJeremy L Thompson CeedCall(w->PointwiseMult(w, x, y)); 794eaf62fffSJeremy L Thompson return CEED_ERROR_SUCCESS; 795eaf62fffSJeremy L Thompson } 7960f7fd0f8Sjeremylt 7970f7fd0f8Sjeremylt // Default implementation 798b0976d5aSZach Atkins if (x == w || y == w) { 799b0976d5aSZach Atkins CeedCall(CeedVectorGetArray(w, CEED_MEM_HOST, &w_array)); 800b0976d5aSZach Atkins } else { 801b0976d5aSZach Atkins CeedCall(CeedVectorGetArrayWrite(w, CEED_MEM_HOST, &w_array)); 802b0976d5aSZach Atkins } 8030f7fd0f8Sjeremylt if (x != w) { 8042b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(x, CEED_MEM_HOST, &x_array)); 8050f7fd0f8Sjeremylt } else { 8060f7fd0f8Sjeremylt x_array = w_array; 8070f7fd0f8Sjeremylt } 8080f7fd0f8Sjeremylt if (y != w && y != x) { 8092b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(y, CEED_MEM_HOST, &y_array)); 810c6d796c6SJeremy L Thompson } else if (y == x) { 8110f7fd0f8Sjeremylt y_array = x_array; 812b0976d5aSZach Atkins } else if (y == w) { 813c6d796c6SJeremy L Thompson y_array = w_array; 8140f7fd0f8Sjeremylt } 8150f7fd0f8Sjeremylt 8162b730f8bSJeremy L Thompson assert(w_array); 8172b730f8bSJeremy L Thompson assert(x_array); 8182b730f8bSJeremy L Thompson assert(y_array); 81973380422SJeremy L Thompson 8201203703bSJeremy L Thompson for (CeedSize i = 0; i < length_w; i++) w_array[i] = x_array[i] * y_array[i]; 8210f7fd0f8Sjeremylt 8222b730f8bSJeremy L Thompson if (y != w && y != x) CeedCall(CeedVectorRestoreArrayRead(y, &y_array)); 8232b730f8bSJeremy L Thompson if (x != w) CeedCall(CeedVectorRestoreArrayRead(x, &x_array)); 8242b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArray(w, &w_array)); 8250f7fd0f8Sjeremylt return CEED_ERROR_SUCCESS; 8260f7fd0f8Sjeremylt } 8270f7fd0f8Sjeremylt 8280f7fd0f8Sjeremylt /** 829ca94c3ddSJeremy L Thompson @brief Take the reciprocal of a `CeedVector`. 830d99fa3c5SJeremy L Thompson 831ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` to take reciprocal 832d99fa3c5SJeremy L Thompson 833d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 834d99fa3c5SJeremy L Thompson 835d99fa3c5SJeremy L Thompson @ref User 836d99fa3c5SJeremy L Thompson **/ 837d99fa3c5SJeremy L Thompson int CeedVectorReciprocal(CeedVector vec) { 8389c774eddSJeremy L Thompson bool has_valid_array = true; 8391203703bSJeremy L Thompson CeedSize length; 8401203703bSJeremy L Thompson CeedScalar *array; 8411203703bSJeremy L Thompson Ceed ceed; 8422b730f8bSJeremy L Thompson 8431203703bSJeremy L Thompson CeedCall(CeedVectorGetCeed(vec, &ceed)); 8441c66c397SJeremy L Thompson CeedCall(CeedVectorHasValidArray(vec, &has_valid_array)); 8451203703bSJeremy L Thompson CeedCheck(has_valid_array, ceed, CEED_ERROR_BACKEND, 8462b730f8bSJeremy L Thompson "CeedVector has no valid data to compute reciprocal, must set data with CeedVectorSetValue or CeedVectorSetArray"); 8479c774eddSJeremy L Thompson 848d99fa3c5SJeremy L Thompson // Check if vector data set 8491203703bSJeremy L Thompson CeedCheck(vec->state > 0, ceed, CEED_ERROR_INCOMPLETE, "CeedVector must have data set to take reciprocal"); 850d99fa3c5SJeremy L Thompson 851b0976d5aSZach Atkins // Return early for empty vector 8521203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 8531203703bSJeremy L Thompson if (length == 0) return CEED_ERROR_SUCCESS; 854b0976d5aSZach Atkins 855d99fa3c5SJeremy L Thompson // Backend impl for GPU, if added 856d99fa3c5SJeremy L Thompson if (vec->Reciprocal) { 8572b730f8bSJeremy L Thompson CeedCall(vec->Reciprocal(vec)); 858e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 859d99fa3c5SJeremy L Thompson } 860d99fa3c5SJeremy L Thompson 861567d69a2SJeremy L Thompson CeedCall(CeedVectorGetArray(vec, CEED_MEM_HOST, &array)); 8621203703bSJeremy L Thompson for (CeedSize i = 0; i < length; i++) { 8632b730f8bSJeremy L Thompson if (fabs(array[i]) > CEED_EPSILON) array[i] = 1. / array[i]; 8642b730f8bSJeremy L Thompson } 865d99fa3c5SJeremy L Thompson 8662b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArray(vec, &array)); 867e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 868d99fa3c5SJeremy L Thompson } 869d99fa3c5SJeremy L Thompson 870d99fa3c5SJeremy L Thompson /** 871ca94c3ddSJeremy L Thompson @brief View a `CeedVector` 8720436c2adSjeremylt 873acb2c48cSJeremy L Thompson Note: It is safe to use any unsigned values for `start` or `stop` and any nonzero integer for `step`. 874ca94c3ddSJeremy L Thompson Any portion of the provided range that is outside the range of valid indices for the `CeedVector` will be ignored. 875acb2c48cSJeremy L Thompson 876ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to view 877ca94c3ddSJeremy L Thompson @param[in] start Index of first `CeedVector` entry to view 878ca94c3ddSJeremy L Thompson @param[in] stop Index of last `CeedVector` entry to view 879ca94c3ddSJeremy L Thompson @param[in] step Step between `CeedVector` entries to view 880acb2c48cSJeremy L Thompson @param[in] fp_fmt Printing format 881acb2c48cSJeremy L Thompson @param[in] stream Filestream to write to 882acb2c48cSJeremy L Thompson 883acb2c48cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 884acb2c48cSJeremy L Thompson 885acb2c48cSJeremy L Thompson @ref User 886acb2c48cSJeremy L Thompson **/ 887acb2c48cSJeremy L Thompson int CeedVectorViewRange(CeedVector vec, CeedSize start, CeedSize stop, CeedInt step, const char *fp_fmt, FILE *stream) { 888acb2c48cSJeremy L Thompson char fmt[1024]; 8891203703bSJeremy L Thompson CeedSize length; 8901203703bSJeremy L Thompson const CeedScalar *x; 891acb2c48cSJeremy L Thompson 8926e536b99SJeremy L Thompson CeedCheck(step != 0, CeedVectorReturnCeed(vec), CEED_ERROR_MINOR, "View range 'step' must be nonzero"); 893acb2c48cSJeremy L Thompson 8941203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 8951203703bSJeremy L Thompson fprintf(stream, "CeedVector length %" CeedSize_FMT "\n", length); 8961203703bSJeremy L Thompson if (start != 0 || stop != length || step != 1) { 8971203703bSJeremy L Thompson fprintf(stream, " start: %" CeedSize_FMT "\n stop: %" CeedSize_FMT "\n step: %" CeedInt_FMT "\n", start, stop, step); 898acb2c48cSJeremy L Thompson } 8991203703bSJeremy L Thompson if (start > length) start = length; 9001203703bSJeremy L Thompson if (stop > length) stop = length; 901acb2c48cSJeremy L Thompson 902acb2c48cSJeremy L Thompson snprintf(fmt, sizeof fmt, " %s\n", fp_fmt ? fp_fmt : "%g"); 903acb2c48cSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(vec, CEED_MEM_HOST, &x)); 904b94338b9SJed Brown for (CeedSize i = start; step > 0 ? (i < stop) : (i > stop); i += step) fprintf(stream, fmt, x[i]); 905acb2c48cSJeremy L Thompson CeedCall(CeedVectorRestoreArrayRead(vec, &x)); 9061203703bSJeremy L Thompson if (stop != length) fprintf(stream, " ...\n"); 907acb2c48cSJeremy L Thompson return CEED_ERROR_SUCCESS; 908acb2c48cSJeremy L Thompson } 909acb2c48cSJeremy L Thompson 910acb2c48cSJeremy L Thompson /** 911ca94c3ddSJeremy L Thompson @brief View a `CeedVector` 912acb2c48cSJeremy L Thompson 913ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to view 914d1d35e2fSjeremylt @param[in] fp_fmt Printing format 9150a0da059Sjeremylt @param[in] stream Filestream to write to 9160a0da059Sjeremylt 9170436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 9180436c2adSjeremylt 9197a982d89SJeremy L. Thompson @ref User 9200436c2adSjeremylt **/ 921d1d35e2fSjeremylt int CeedVectorView(CeedVector vec, const char *fp_fmt, FILE *stream) { 9221203703bSJeremy L Thompson CeedSize length; 9231203703bSJeremy L Thompson 9241203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 9251203703bSJeremy L Thompson CeedCall(CeedVectorViewRange(vec, 0, length, 1, fp_fmt, stream)); 926e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9270436c2adSjeremylt } 9280436c2adSjeremylt 9290436c2adSjeremylt /** 930ca94c3ddSJeremy L Thompson @brief Get the `Ceed` associated with a `CeedVector` 931b7c9bbdaSJeremy L Thompson 932ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to retrieve state 933ca94c3ddSJeremy L Thompson @param[out] ceed Variable to store `Ceed` 934b7c9bbdaSJeremy L Thompson 935b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 936b7c9bbdaSJeremy L Thompson 937b7c9bbdaSJeremy L Thompson @ref Advanced 938b7c9bbdaSJeremy L Thompson **/ 939b7c9bbdaSJeremy L Thompson int CeedVectorGetCeed(CeedVector vec, Ceed *ceed) { 9406e536b99SJeremy L Thompson *ceed = CeedVectorReturnCeed(vec); 941b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 942b7c9bbdaSJeremy L Thompson } 943b7c9bbdaSJeremy L Thompson 944b7c9bbdaSJeremy L Thompson /** 9456e536b99SJeremy L Thompson @brief Return the `Ceed` associated with a `CeedVector` 9466e536b99SJeremy L Thompson 9476e536b99SJeremy L Thompson @param[in] vec `CeedVector` to retrieve state 9486e536b99SJeremy L Thompson 9496e536b99SJeremy L Thompson @return `Ceed` associated with the `vec` 9506e536b99SJeremy L Thompson 9516e536b99SJeremy L Thompson @ref Advanced 9526e536b99SJeremy L Thompson **/ 9536e536b99SJeremy L Thompson Ceed CeedVectorReturnCeed(CeedVector vec) { return vec->ceed; } 9546e536b99SJeremy L Thompson 9556e536b99SJeremy L Thompson /** 956ca94c3ddSJeremy L Thompson @brief Get the length of a `CeedVector` 9570436c2adSjeremylt 958ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to retrieve length 9597a982d89SJeremy L. Thompson @param[out] length Variable to store length 9600436c2adSjeremylt 9610436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 9620436c2adSjeremylt 9637a982d89SJeremy L. Thompson @ref User 9640436c2adSjeremylt **/ 9651f9221feSJeremy L Thompson int CeedVectorGetLength(CeedVector vec, CeedSize *length) { 9667a982d89SJeremy L. Thompson *length = vec->length; 967e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9680436c2adSjeremylt } 9690436c2adSjeremylt 9700436c2adSjeremylt /** 971ca94c3ddSJeremy L Thompson @brief Destroy a `CeedVector` 9720436c2adSjeremylt 973ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` to destroy 9740436c2adSjeremylt 9750436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 9760436c2adSjeremylt 9777a982d89SJeremy L. Thompson @ref User 9780436c2adSjeremylt **/ 9790436c2adSjeremylt int CeedVectorDestroy(CeedVector *vec) { 9807425e127SJeremy L Thompson if (!*vec || *vec == CEED_VECTOR_ACTIVE || *vec == CEED_VECTOR_NONE || --(*vec)->ref_count > 0) { 981ad6481ceSJeremy L Thompson *vec = NULL; 982ad6481ceSJeremy L Thompson return CEED_ERROR_SUCCESS; 983ad6481ceSJeremy L Thompson } 9846574a04fSJeremy L Thompson CeedCheck((*vec)->state % 2 == 0, (*vec)->ceed, CEED_ERROR_ACCESS, "Cannot destroy CeedVector, the writable access lock is in use"); 9856574a04fSJeremy L Thompson CeedCheck((*vec)->num_readers == 0, (*vec)->ceed, CEED_ERROR_ACCESS, "Cannot destroy CeedVector, a process has read access"); 9860436c2adSjeremylt 9872b730f8bSJeremy L Thompson if ((*vec)->Destroy) CeedCall((*vec)->Destroy(*vec)); 9882b730f8bSJeremy L Thompson 9892b730f8bSJeremy L Thompson CeedCall(CeedDestroy(&(*vec)->ceed)); 9902b730f8bSJeremy L Thompson CeedCall(CeedFree(vec)); 991e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9920436c2adSjeremylt } 9930436c2adSjeremylt 9940436c2adSjeremylt /// @} 995