19ba83ac0SJeremy L Thompson // Copyright (c) 2017-2026, 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 /// ---------------------------------------------------------------------------- 37b0f67a9cSJeremy L Thompson /// CeedVector Internal Functions 38b0f67a9cSJeremy L Thompson /// ---------------------------------------------------------------------------- 39b0f67a9cSJeremy L Thompson /// @addtogroup CeedVectorDeveloper 40b0f67a9cSJeremy L Thompson /// @{ 41b0f67a9cSJeremy L Thompson 42b0f67a9cSJeremy L Thompson /** 43b0f67a9cSJeremy L Thompson @brief View a `CeedVector` passed as a `CeedObject` 44b0f67a9cSJeremy L Thompson 45b0f67a9cSJeremy L Thompson @param[in] vec `CeedVector` to view 46b0f67a9cSJeremy L Thompson @param[in] stream Filestream to write to 47b0f67a9cSJeremy L Thompson 48b0f67a9cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 49b0f67a9cSJeremy L Thompson 50b0f67a9cSJeremy L Thompson @ref Developer 51b0f67a9cSJeremy L Thompson **/ 52b0f67a9cSJeremy L Thompson static int CeedVectorView_Object(CeedObject vec, FILE *stream) { 53b0f67a9cSJeremy L Thompson CeedCall(CeedVectorView((CeedVector)vec, "%12.8f", stream)); 54b0f67a9cSJeremy L Thompson return CEED_ERROR_SUCCESS; 55b0f67a9cSJeremy L Thompson } 56b0f67a9cSJeremy L Thompson 57*6c328a79SJeremy L Thompson /** 58*6c328a79SJeremy L Thompson @brief Destroy a `CeedVector` passed as a `CeedObject` 59*6c328a79SJeremy L Thompson 60*6c328a79SJeremy L Thompson @param[in,out] vec Address of `CeedVector` to destroy 61*6c328a79SJeremy L Thompson 62*6c328a79SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 63*6c328a79SJeremy L Thompson 64*6c328a79SJeremy L Thompson @ref Developer 65*6c328a79SJeremy L Thompson **/ 66*6c328a79SJeremy L Thompson static int CeedVectorDestroy_Object(CeedObject *vec) { 67*6c328a79SJeremy L Thompson CeedCall(CeedVectorDestroy((CeedVector *)vec)); 68*6c328a79SJeremy L Thompson return CEED_ERROR_SUCCESS; 69*6c328a79SJeremy L Thompson } 70*6c328a79SJeremy L Thompson 71b0f67a9cSJeremy L Thompson /// @} 72b0f67a9cSJeremy L Thompson 73b0f67a9cSJeremy L Thompson /// ---------------------------------------------------------------------------- 747a982d89SJeremy L. Thompson /// CeedVector Backend API 757a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 767a982d89SJeremy L. Thompson /// @addtogroup CeedVectorBackend 777a982d89SJeremy L. Thompson /// @{ 787a982d89SJeremy L. Thompson 797a982d89SJeremy L. Thompson /** 80ca94c3ddSJeremy L Thompson @brief Check for valid data in a `CeedVector` 819c774eddSJeremy L Thompson 82ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to check validity 839c774eddSJeremy L Thompson @param[out] has_valid_array Variable to store validity 849c774eddSJeremy L Thompson 859c774eddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 869c774eddSJeremy L Thompson 879c774eddSJeremy L Thompson @ref Backend 889c774eddSJeremy L Thompson **/ 899c774eddSJeremy L Thompson int CeedVectorHasValidArray(CeedVector vec, bool *has_valid_array) { 901203703bSJeremy L Thompson CeedSize length; 911203703bSJeremy L Thompson 926e536b99SJeremy L Thompson CeedCheck(vec->HasValidArray, CeedVectorReturnCeed(vec), CEED_ERROR_UNSUPPORTED, "Backend does not support CeedVectorHasValidArray"); 931203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 941203703bSJeremy L Thompson if (length == 0) { 95b0976d5aSZach Atkins *has_valid_array = true; 96b0976d5aSZach Atkins return CEED_ERROR_SUCCESS; 97b0976d5aSZach Atkins } 982b730f8bSJeremy L Thompson CeedCall(vec->HasValidArray(vec, has_valid_array)); 999c774eddSJeremy L Thompson return CEED_ERROR_SUCCESS; 1009c774eddSJeremy L Thompson } 1019c774eddSJeremy L Thompson 1029c774eddSJeremy L Thompson /** 103ca94c3ddSJeremy L Thompson @brief Check for borrowed array of a specific @ref CeedMemType in a `CeedVector` 1049c774eddSJeremy L Thompson 105ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to check 106ea61e9acSJeremy L Thompson @param[in] mem_type Memory type to check 1079c774eddSJeremy L Thompson @param[out] has_borrowed_array_of_type Variable to store result 1089c774eddSJeremy L Thompson 1099c774eddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1109c774eddSJeremy L Thompson 1119c774eddSJeremy L Thompson @ref Backend 1129c774eddSJeremy L Thompson **/ 1132b730f8bSJeremy L Thompson int CeedVectorHasBorrowedArrayOfType(CeedVector vec, CeedMemType mem_type, bool *has_borrowed_array_of_type) { 1146e536b99SJeremy L Thompson CeedCheck(vec->HasBorrowedArrayOfType, CeedVectorReturnCeed(vec), CEED_ERROR_UNSUPPORTED, 1156e536b99SJeremy L Thompson "Backend does not support CeedVectorHasBorrowedArrayOfType"); 1162b730f8bSJeremy L Thompson CeedCall(vec->HasBorrowedArrayOfType(vec, mem_type, has_borrowed_array_of_type)); 1179c774eddSJeremy L Thompson return CEED_ERROR_SUCCESS; 1189c774eddSJeremy L Thompson } 1199c774eddSJeremy L Thompson 1209c774eddSJeremy L Thompson /** 121ca94c3ddSJeremy L Thompson @brief Get the state of a `CeedVector` 1227a982d89SJeremy L. Thompson 123ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to retrieve state 1247a982d89SJeremy L. Thompson @param[out] state Variable to store state 1257a982d89SJeremy L. Thompson 1267a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1277a982d89SJeremy L. Thompson 1287a982d89SJeremy L. Thompson @ref Backend 1297a982d89SJeremy L. Thompson **/ 1307a982d89SJeremy L. Thompson int CeedVectorGetState(CeedVector vec, uint64_t *state) { 1317a982d89SJeremy L. Thompson *state = vec->state; 132e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1337a982d89SJeremy L. Thompson } 1347a982d89SJeremy L. Thompson 1357a982d89SJeremy L. Thompson /** 136ca94c3ddSJeremy L Thompson @brief Get the backend data of a `CeedVector` 1377a982d89SJeremy L. Thompson 138ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to retrieve state 1397a982d89SJeremy L. Thompson @param[out] data Variable to store data 1407a982d89SJeremy L. Thompson 1417a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1427a982d89SJeremy L. Thompson 1437a982d89SJeremy L. Thompson @ref Backend 1447a982d89SJeremy L. Thompson **/ 145777ff853SJeremy L Thompson int CeedVectorGetData(CeedVector vec, void *data) { 146777ff853SJeremy L Thompson *(void **)data = vec->data; 147e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1487a982d89SJeremy L. Thompson } 1497a982d89SJeremy L. Thompson 1507a982d89SJeremy L. Thompson /** 151ca94c3ddSJeremy L Thompson @brief Set the backend data of a `CeedVector` 1527a982d89SJeremy L. Thompson 153ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` to retrieve state 154ea61e9acSJeremy L Thompson @param[in] data Data to set 1557a982d89SJeremy L. Thompson 1567a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1577a982d89SJeremy L. Thompson 1587a982d89SJeremy L. Thompson @ref Backend 1597a982d89SJeremy L. Thompson **/ 160777ff853SJeremy L Thompson int CeedVectorSetData(CeedVector vec, void *data) { 161777ff853SJeremy L Thompson vec->data = data; 162e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1637a982d89SJeremy L. Thompson } 1647a982d89SJeremy L. Thompson 16534359f16Sjeremylt /** 166ca94c3ddSJeremy L Thompson @brief Increment the reference counter for a `CeedVector` 16734359f16Sjeremylt 168ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` to increment the reference counter 16934359f16Sjeremylt 17034359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 17134359f16Sjeremylt 17234359f16Sjeremylt @ref Backend 17334359f16Sjeremylt **/ 1749560d06aSjeremylt int CeedVectorReference(CeedVector vec) { 175b0f67a9cSJeremy L Thompson CeedCall(CeedObjectReference((CeedObject)vec)); 17634359f16Sjeremylt return CEED_ERROR_SUCCESS; 17734359f16Sjeremylt } 17834359f16Sjeremylt 1797a982d89SJeremy L. Thompson /// @} 1807a982d89SJeremy L. Thompson 1817a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1827a982d89SJeremy L. Thompson /// CeedVector Public API 1837a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1847a982d89SJeremy L. Thompson /// @addtogroup CeedVectorUser 1850436c2adSjeremylt /// @{ 1860436c2adSjeremylt 1870436c2adSjeremylt /** 188ca94c3ddSJeremy L Thompson @brief Create a `CeedVector` of the specified length (does not allocate memory) 1890436c2adSjeremylt 190ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` object used to create the `CeedVector` 191ea61e9acSJeremy L Thompson @param[in] length Length of vector 192ca94c3ddSJeremy L Thompson @param[out] vec Address of the variable where the newly created `CeedVector` will be stored 1930436c2adSjeremylt 1940436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 1950436c2adSjeremylt 1967a982d89SJeremy L. Thompson @ref User 1970436c2adSjeremylt **/ 1981f9221feSJeremy L Thompson int CeedVectorCreate(Ceed ceed, CeedSize length, CeedVector *vec) { 199a5ef892dSJames Wright CeedCheck(length >= 0, ceed, CEED_ERROR_UNSUPPORTED, "CeedVector must have length >= 0, recieved %" CeedSize_FMT, length); 2000436c2adSjeremylt if (!ceed->VectorCreate) { 2010436c2adSjeremylt Ceed delegate; 2026574a04fSJeremy L Thompson 2032b730f8bSJeremy L Thompson CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Vector")); 2041ef3a2a9SJeremy L Thompson CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement VectorCreate"); 2052b730f8bSJeremy L Thompson CeedCall(CeedVectorCreate(delegate, length, vec)); 2069bc66399SJeremy L Thompson CeedCall(CeedDestroy(&delegate)); 207e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2080436c2adSjeremylt } 2090436c2adSjeremylt 2102b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, vec)); 211*6c328a79SJeremy L Thompson CeedCall(CeedObjectCreate(ceed, CeedVectorView_Object, CeedVectorDestroy_Object, &(*vec)->obj)); 2120436c2adSjeremylt (*vec)->length = length; 2130436c2adSjeremylt (*vec)->state = 0; 2142b730f8bSJeremy L Thompson CeedCall(ceed->VectorCreate(length, *vec)); 215e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2160436c2adSjeremylt } 2170436c2adSjeremylt 2180436c2adSjeremylt /** 219ca94c3ddSJeremy L Thompson @brief Copy the pointer to a `CeedVector`. 2204385fb7fSSebastian Grimberg 221ca94c3ddSJeremy L Thompson Both pointers should be destroyed with @ref CeedVectorDestroy(). 222512bb800SJeremy L Thompson 223ca94c3ddSJeremy 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`. 224ca94c3ddSJeremy L Thompson This `CeedVector` will be destroyed if `*vec_copy` is the only reference to this `CeedVector`. 2259560d06aSjeremylt 226ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to copy reference to 227ea61e9acSJeremy L Thompson @param[in,out] vec_copy Variable to store copied reference 2289560d06aSjeremylt 2299560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 2309560d06aSjeremylt 2319560d06aSjeremylt @ref User 2329560d06aSjeremylt **/ 2339560d06aSjeremylt int CeedVectorReferenceCopy(CeedVector vec, CeedVector *vec_copy) { 234393ac2cdSJeremy L Thompson if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) CeedCall(CeedVectorReference(vec)); 2352b730f8bSJeremy L Thompson CeedCall(CeedVectorDestroy(vec_copy)); 2369560d06aSjeremylt *vec_copy = vec; 2379560d06aSjeremylt return CEED_ERROR_SUCCESS; 2389560d06aSjeremylt } 2399560d06aSjeremylt 2409560d06aSjeremylt /** 241ca94c3ddSJeremy L Thompson @brief Copy a `CeedVector` into a different `CeedVector`. 2424385fb7fSSebastian Grimberg 243ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to copy 244e706ae07SJeremy L Thompson @param[in,out] vec_copy `CeedVector` to copy array into 2455fb68f37SKaren (Ren) Stengel 2465fb68f37SKaren (Ren) Stengel @return An error code: 0 - success, otherwise - failure 2475fb68f37SKaren (Ren) Stengel 2485fb68f37SKaren (Ren) Stengel @ref User 2495fb68f37SKaren (Ren) Stengel **/ 2505fb68f37SKaren (Ren) Stengel int CeedVectorCopy(CeedVector vec, CeedVector vec_copy) { 2515fb68f37SKaren (Ren) Stengel CeedMemType mem_type, mem_type_copy; 2525fb68f37SKaren (Ren) Stengel CeedScalar *array; 2535fb68f37SKaren (Ren) Stengel 2549bc66399SJeremy L Thompson // Get the preferred memory types 2559bc66399SJeremy L Thompson { 2569bc66399SJeremy L Thompson Ceed ceed; 2579bc66399SJeremy L Thompson 258d77c2f5dSJeremy L Thompson CeedCall(CeedVectorGetCeed(vec, &ceed)); 259d77c2f5dSJeremy L Thompson CeedCall(CeedGetPreferredMemType(ceed, &mem_type)); 2609bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed)); 2615fb68f37SKaren (Ren) Stengel 262d77c2f5dSJeremy L Thompson CeedCall(CeedVectorGetCeed(vec_copy, &ceed)); 263d77c2f5dSJeremy L Thompson CeedCall(CeedGetPreferredMemType(ceed, &mem_type_copy)); 2649bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed)); 2659bc66399SJeremy L Thompson } 2665fb68f37SKaren (Ren) Stengel 2675fb68f37SKaren (Ren) Stengel // Check that both have same memory type 2685fb68f37SKaren (Ren) Stengel if (mem_type != mem_type_copy) mem_type = CEED_MEM_HOST; 2695fb68f37SKaren (Ren) Stengel 270e706ae07SJeremy L Thompson // Check compatible lengths 271e706ae07SJeremy L Thompson { 272e706ae07SJeremy L Thompson CeedSize length_vec, length_copy; 273e706ae07SJeremy L Thompson 274e706ae07SJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length_vec)); 275e706ae07SJeremy L Thompson CeedCall(CeedVectorGetLength(vec_copy, &length_copy)); 2769bc66399SJeremy L Thompson CeedCheck(length_vec == length_copy, CeedVectorReturnCeed(vec), CEED_ERROR_INCOMPATIBLE, "CeedVectors must have the same length to copy"); 277e706ae07SJeremy L Thompson } 278e706ae07SJeremy L Thompson 2795fb68f37SKaren (Ren) Stengel // Copy the values from vec to vec_copy 2805fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorGetArray(vec, mem_type, &array)); 2815fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorSetArray(vec_copy, mem_type, CEED_COPY_VALUES, array)); 2825fb68f37SKaren (Ren) Stengel 2835fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorRestoreArray(vec, &array)); 2845fb68f37SKaren (Ren) Stengel return CEED_ERROR_SUCCESS; 2855fb68f37SKaren (Ren) Stengel } 2865fb68f37SKaren (Ren) Stengel 2875fb68f37SKaren (Ren) Stengel /** 2880b8f3c4eSJeremy L Thompson @brief Copy a strided portion of `CeedVector` contents into a different `CeedVector` 2890b8f3c4eSJeremy L Thompson 2900b8f3c4eSJeremy L Thompson @param[in] vec `CeedVector` to copy 291832a6d73SJeremy L Thompson @param[in] start First index to copy in the range `[start, stop)` 292832a6d73SJeremy L Thompson @param[in] stop One past the last element to copy in the range, or `-1` for `length` 2930b8f3c4eSJeremy L Thompson @param[in] step Stride between indices to copy 2940b8f3c4eSJeremy L Thompson @param[in,out] vec_copy `CeedVector` to copy values to 2950b8f3c4eSJeremy L Thompson 2960b8f3c4eSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 2970b8f3c4eSJeremy L Thompson 2980b8f3c4eSJeremy L Thompson @ref User 2990b8f3c4eSJeremy L Thompson **/ 300832a6d73SJeremy L Thompson int CeedVectorCopyStrided(CeedVector vec, CeedSize start, CeedSize stop, CeedSize step, CeedVector vec_copy) { 3010b8f3c4eSJeremy L Thompson CeedSize length; 302bb03490dSJeremy L Thompson const CeedScalar *array = NULL; 303bb03490dSJeremy L Thompson CeedScalar *array_copy = NULL; 3040b8f3c4eSJeremy L Thompson 305832a6d73SJeremy L Thompson // Check length 3060b8f3c4eSJeremy L Thompson { 3070b8f3c4eSJeremy L Thompson CeedSize length_vec, length_copy; 3080b8f3c4eSJeremy L Thompson 3090b8f3c4eSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length_vec)); 3100b8f3c4eSJeremy L Thompson CeedCall(CeedVectorGetLength(vec_copy, &length_copy)); 311bb03490dSJeremy L Thompson if (length_vec <= 0 || length_copy <= 0) return CEED_ERROR_SUCCESS; 312a7efc114SJeremy L Thompson length = length_vec < length_copy ? length_vec : length_copy; 3130b8f3c4eSJeremy L Thompson } 314832a6d73SJeremy L Thompson CeedCheck(stop >= -1 && stop <= length, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, 315832a6d73SJeremy L Thompson "Invalid value for stop %" CeedSize_FMT ", must be in the range [-1, length]", stop); 316832a6d73SJeremy L Thompson CeedCheck(start >= 0 && start <= length && (start <= stop || stop == -1), CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, 317832a6d73SJeremy L Thompson "Invalid value for start %" CeedSize_FMT ", must be in the range [0, stop]", start); 318832a6d73SJeremy L Thompson 319832a6d73SJeremy L Thompson // Backend version 320832a6d73SJeremy L Thompson if (vec->CopyStrided && vec_copy->CopyStrided) { 321832a6d73SJeremy L Thompson CeedCall(vec->CopyStrided(vec, start, stop, step, vec_copy)); 322832a6d73SJeremy L Thompson vec_copy->state += 2; 323832a6d73SJeremy L Thompson return CEED_ERROR_SUCCESS; 324832a6d73SJeremy L Thompson } 3250b8f3c4eSJeremy L Thompson 3260b8f3c4eSJeremy L Thompson // Copy 3270b8f3c4eSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(vec, CEED_MEM_HOST, &array)); 3280b8f3c4eSJeremy L Thompson CeedCall(CeedVectorGetArray(vec_copy, CEED_MEM_HOST, &array_copy)); 329832a6d73SJeremy L Thompson if (stop == -1) stop = length; 330832a6d73SJeremy L Thompson for (CeedSize i = start; i < stop; i += step) array_copy[i] = array[i]; 3310b8f3c4eSJeremy L Thompson 3320b8f3c4eSJeremy L Thompson // Cleanup 3330b8f3c4eSJeremy L Thompson CeedCall(CeedVectorRestoreArrayRead(vec, &array)); 3340b8f3c4eSJeremy L Thompson CeedCall(CeedVectorRestoreArray(vec_copy, &array_copy)); 3350b8f3c4eSJeremy L Thompson return CEED_ERROR_SUCCESS; 3360b8f3c4eSJeremy L Thompson } 3370b8f3c4eSJeremy L Thompson 3380b8f3c4eSJeremy L Thompson /** 339ca94c3ddSJeremy L Thompson @brief Set the array used by a `CeedVector`, freeing any previously allocated array if applicable. 3404385fb7fSSebastian Grimberg 341ca94c3ddSJeremy L Thompson The backend may copy values to a different @ref CeedMemType, such as during @ref CeedOperatorApply(). 3426a6c615bSJeremy L Thompson See also @ref CeedVectorSyncArray() and @ref CeedVectorTakeArray(). 3430436c2adSjeremylt 344ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` 345ea61e9acSJeremy L Thompson @param[in] mem_type Memory type of the array being passed 346ea61e9acSJeremy L Thompson @param[in] copy_mode Copy mode for the array 347ca94c3ddSJeremy L Thompson @param[in] array Array to be used, or `NULL` with @ref CEED_COPY_VALUES to have the library allocate 3480436c2adSjeremylt 3490436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 3500436c2adSjeremylt 3517a982d89SJeremy L. Thompson @ref User 3520436c2adSjeremylt **/ 3532b730f8bSJeremy L Thompson int CeedVectorSetArray(CeedVector vec, CeedMemType mem_type, CeedCopyMode copy_mode, CeedScalar *array) { 3541203703bSJeremy L Thompson CeedSize length; 3550436c2adSjeremylt 3569bc66399SJeremy L Thompson CeedCheck(vec->SetArray, CeedVectorReturnCeed(vec), CEED_ERROR_UNSUPPORTED, "Backend does not support VectorSetArray"); 3579bc66399SJeremy L Thompson CeedCheck(vec->state % 2 == 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, 3589bc66399SJeremy L Thompson "Cannot grant CeedVector array access, the access lock is already in use"); 3599bc66399SJeremy L Thompson CeedCheck(vec->num_readers == 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, a process has read access"); 3601203703bSJeremy L Thompson 3611203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 3621203703bSJeremy L Thompson if (length > 0) CeedCall(vec->SetArray(vec, mem_type, copy_mode, array)); 3630436c2adSjeremylt vec->state += 2; 364e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3650436c2adSjeremylt } 3660436c2adSjeremylt 3670436c2adSjeremylt /** 368ca94c3ddSJeremy L Thompson @brief Set the `CeedVector` to a constant value 3690436c2adSjeremylt 370ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` 3710436c2adSjeremylt @param[in] value Value to be used 3720436c2adSjeremylt 3730436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 3740436c2adSjeremylt 3757a982d89SJeremy L. Thompson @ref User 3760436c2adSjeremylt **/ 3770436c2adSjeremylt int CeedVectorSetValue(CeedVector vec, CeedScalar value) { 3789bc66399SJeremy L Thompson CeedCheck(vec->state % 2 == 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, 3799bc66399SJeremy L Thompson "Cannot grant CeedVector array access, the access lock is already in use"); 3809bc66399SJeremy L Thompson CeedCheck(vec->num_readers == 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, a process has read access"); 3810436c2adSjeremylt 3820436c2adSjeremylt if (vec->SetValue) { 3832b730f8bSJeremy L Thompson CeedCall(vec->SetValue(vec, value)); 3842d4e0605SJeremy L Thompson vec->state += 2; 3850436c2adSjeremylt } else { 3861203703bSJeremy L Thompson CeedSize length; 3870436c2adSjeremylt CeedScalar *array; 3881203703bSJeremy L Thompson 3892b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayWrite(vec, CEED_MEM_HOST, &array)); 3901203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 3911203703bSJeremy L Thompson for (CeedSize i = 0; i < length; i++) array[i] = value; 3922b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArray(vec, &array)); 3930436c2adSjeremylt } 394e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3950436c2adSjeremylt } 3960436c2adSjeremylt 3970436c2adSjeremylt /** 3980b8f3c4eSJeremy L Thompson @brief Set a portion of a `CeedVector` to a constant value. 3990b8f3c4eSJeremy L Thompson 4000b8f3c4eSJeremy L Thompson Note: The `CeedVector` must already have valid data set via @ref CeedVectorSetArray() or similar. 4010b8f3c4eSJeremy L Thompson 4020b8f3c4eSJeremy L Thompson @param[in,out] vec `CeedVector` 403ff90b007SJeremy L Thompson @param[in] start First index to set in range `[start, stop)` 40412634730SJeremy L Thompson @param[in] stop One past the last element to set in the range, or `-1` for `length` 4050b8f3c4eSJeremy L Thompson @param[in] step Stride between indices to set 4060b8f3c4eSJeremy L Thompson @param[in] value Value to be used 4070b8f3c4eSJeremy L Thompson 4080b8f3c4eSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 4090b8f3c4eSJeremy L Thompson 4100b8f3c4eSJeremy L Thompson @ref User 4110b8f3c4eSJeremy L Thompson **/ 412ff90b007SJeremy L Thompson int CeedVectorSetValueStrided(CeedVector vec, CeedSize start, CeedSize stop, CeedSize step, CeedScalar value) { 413b1a610efSJeremy L Thompson CeedSize length; 414b1a610efSJeremy L Thompson 4159bc66399SJeremy L Thompson CeedCheck(vec->state % 2 == 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, 4169bc66399SJeremy L Thompson "Cannot grant CeedVector array access, the access lock is already in use"); 4179bc66399SJeremy L Thompson CeedCheck(vec->num_readers == 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, a process has read access"); 418b1a610efSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 4197a747cf1SJeremy L Thompson CeedCheck(stop >= -1 && stop <= length, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, 4207a747cf1SJeremy L Thompson "Invalid value for stop %" CeedSize_FMT ", must be in the range [-1, length]", stop); 4210b8f3c4eSJeremy L Thompson 4220b8f3c4eSJeremy L Thompson if (vec->SetValueStrided) { 423ff90b007SJeremy L Thompson CeedCall(vec->SetValueStrided(vec, start, stop, step, value)); 4242d4e0605SJeremy L Thompson vec->state += 2; 4250b8f3c4eSJeremy L Thompson } else { 4260b8f3c4eSJeremy L Thompson CeedScalar *array; 4270b8f3c4eSJeremy L Thompson 428bb03490dSJeremy L Thompson if (length <= 0) return CEED_ERROR_SUCCESS; 429ff90b007SJeremy L Thompson if (stop == -1) stop = length; 430bb03490dSJeremy L Thompson CeedCall(CeedVectorGetArray(vec, CEED_MEM_HOST, &array)); 431ff90b007SJeremy L Thompson for (CeedSize i = start; i < stop; i += step) array[i] = value; 4320b8f3c4eSJeremy L Thompson CeedCall(CeedVectorRestoreArray(vec, &array)); 4330b8f3c4eSJeremy L Thompson } 4340b8f3c4eSJeremy L Thompson return CEED_ERROR_SUCCESS; 4350b8f3c4eSJeremy L Thompson } 4360b8f3c4eSJeremy L Thompson 4370b8f3c4eSJeremy L Thompson /** 438ca94c3ddSJeremy L Thompson @brief Sync the `CeedVector` to a specified `mem_type`. 4394385fb7fSSebastian Grimberg 440ea61e9acSJeremy L Thompson This function is used to force synchronization of arrays set with @ref CeedVectorSetArray(). 441ca94c3ddSJeremy L Thompson If the requested `mem_type` is already synchronized, this function results in a no-op. 4420436c2adSjeremylt 443ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` 444ca94c3ddSJeremy L Thompson @param[in] mem_type @ref CeedMemType to be synced 4450436c2adSjeremylt 4460436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 4470436c2adSjeremylt 4487a982d89SJeremy L. Thompson @ref User 4490436c2adSjeremylt **/ 450d1d35e2fSjeremylt int CeedVectorSyncArray(CeedVector vec, CeedMemType mem_type) { 4511203703bSJeremy L Thompson CeedSize length; 4521203703bSJeremy L Thompson 4536e536b99SJeremy L Thompson CeedCheck(vec->state % 2 == 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, "Cannot sync CeedVector, the access lock is already in use"); 4540436c2adSjeremylt 455b0976d5aSZach Atkins // Don't sync empty array 4561203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 4571203703bSJeremy L Thompson if (length == 0) return CEED_ERROR_SUCCESS; 458b0976d5aSZach Atkins 4590436c2adSjeremylt if (vec->SyncArray) { 4602b730f8bSJeremy L Thompson CeedCall(vec->SyncArray(vec, mem_type)); 4610436c2adSjeremylt } else { 4620436c2adSjeremylt const CeedScalar *array; 4631203703bSJeremy L Thompson 4642b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(vec, mem_type, &array)); 4652b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArrayRead(vec, &array)); 4660436c2adSjeremylt } 467e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4680436c2adSjeremylt } 4690436c2adSjeremylt 4700436c2adSjeremylt /** 471ca94c3ddSJeremy 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`. 4724385fb7fSSebastian Grimberg 4739c774eddSJeremy L Thompson The caller is responsible for managing and freeing the array. 474ea61e9acSJeremy L Thompson This function will error if @ref CeedVectorSetArray() was not previously called with @ref CEED_USE_POINTER for the corresponding mem_type. 4756a6c615bSJeremy L Thompson 476ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` 477ea61e9acSJeremy L Thompson @param[in] mem_type Memory type on which to take the array. 478ea61e9acSJeremy L Thompson If the backend uses a different memory type, this will perform a copy. 479ca94c3ddSJeremy L Thompson @param[out] array Array on memory type `mem_type`, or `NULL` if array pointer is not required 4806a6c615bSJeremy L Thompson 4816a6c615bSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 4826a6c615bSJeremy L Thompson 4836a6c615bSJeremy L Thompson @ref User 4846a6c615bSJeremy L Thompson **/ 4852b730f8bSJeremy L Thompson int CeedVectorTakeArray(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 4861203703bSJeremy L Thompson CeedSize length; 4871c66c397SJeremy L Thompson CeedScalar *temp_array = NULL; 4881c66c397SJeremy L Thompson 4899bc66399SJeremy L Thompson CeedCheck(vec->state % 2 == 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, "Cannot take CeedVector array, the access lock is already in use"); 4909bc66399SJeremy L Thompson CeedCheck(vec->num_readers == 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, "Cannot take CeedVector array, a process has read access"); 4916a6c615bSJeremy L Thompson 4921203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 4931203703bSJeremy L Thompson if (length > 0) { 4941203703bSJeremy L Thompson bool has_borrowed_array_of_type = true, has_valid_array = true; 4951203703bSJeremy L Thompson 4962b730f8bSJeremy L Thompson CeedCall(CeedVectorHasBorrowedArrayOfType(vec, mem_type, &has_borrowed_array_of_type)); 4979bc66399SJeremy L Thompson CeedCheck(has_borrowed_array_of_type, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, 4989bc66399SJeremy L Thompson "CeedVector has no borrowed %s array, must set array with CeedVectorSetArray", CeedMemTypes[mem_type]); 4999c774eddSJeremy L Thompson 5002b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(vec, &has_valid_array)); 5019bc66399SJeremy L Thompson CeedCheck(has_valid_array, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, 5022b730f8bSJeremy L Thompson "CeedVector has no valid data to take, must set data with CeedVectorSetValue or CeedVectorSetArray"); 5039c774eddSJeremy L Thompson 5042b730f8bSJeremy L Thompson CeedCall(vec->TakeArray(vec, mem_type, &temp_array)); 50550c643e1SJed Brown } 506d1d35e2fSjeremylt if (array) (*array) = temp_array; 507e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5086a6c615bSJeremy L Thompson } 5096a6c615bSJeremy L Thompson 5106a6c615bSJeremy L Thompson /** 511ca94c3ddSJeremy L Thompson @brief Get read/write access to a `CeedVector` via the specified memory type. 5124385fb7fSSebastian Grimberg 513b3cf021fSjeremylt Restore access with @ref CeedVectorRestoreArray(). 5140436c2adSjeremylt 515ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` to access 516ea61e9acSJeremy L Thompson @param[in] mem_type Memory type on which to access the array. 517ea61e9acSJeremy L Thompson If the backend uses a different memory type, this will perform a copy. 518ca94c3ddSJeremy L Thompson @param[out] array Array on memory type `mem_type` 5190436c2adSjeremylt 520ca94c3ddSJeremy L Thompson @note The @ref CeedVectorGetArray() and @ref CeedVectorRestoreArray() functions provide access to array pointers in the desired memory space. 521ca94c3ddSJeremy L Thompson Pairing get/restore allows the `CeedVector` to track access, thus knowing if norms or other operations may need to be recomputed. 5220436c2adSjeremylt 5230436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 5240436c2adSjeremylt 5257a982d89SJeremy L. Thompson @ref User 5260436c2adSjeremylt **/ 5272b730f8bSJeremy L Thompson int CeedVectorGetArray(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 5281203703bSJeremy L Thompson CeedSize length; 5290436c2adSjeremylt 5309bc66399SJeremy L Thompson CeedCheck(vec->GetArray, CeedVectorReturnCeed(vec), CEED_ERROR_UNSUPPORTED, "Backend does not support GetArray"); 5319bc66399SJeremy L Thompson CeedCheck(vec->state % 2 == 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, 5329bc66399SJeremy L Thompson "Cannot grant CeedVector array access, the access lock is already in use"); 5339bc66399SJeremy L Thompson CeedCheck(vec->num_readers == 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, a process has read access"); 5341203703bSJeremy L Thompson 5351203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 5361203703bSJeremy L Thompson if (length > 0) { 5379c774eddSJeremy L Thompson bool has_valid_array = true; 538b0976d5aSZach Atkins 5392b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(vec, &has_valid_array)); 5409bc66399SJeremy L Thompson CeedCheck(has_valid_array, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, 5412b730f8bSJeremy L Thompson "CeedVector has no valid data to read, must set data with CeedVectorSetValue or CeedVectorSetArray"); 5429c774eddSJeremy L Thompson 5432b730f8bSJeremy L Thompson CeedCall(vec->GetArray(vec, mem_type, array)); 544b0976d5aSZach Atkins } else { 545b0976d5aSZach Atkins *array = NULL; 546b0976d5aSZach Atkins } 54728bfd0b7SJeremy L Thompson vec->state++; 548e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5490436c2adSjeremylt } 5500436c2adSjeremylt 5510436c2adSjeremylt /** 552ca94c3ddSJeremy L Thompson @brief Get read-only access to a `CeedVector` via the specified memory type. 5534385fb7fSSebastian Grimberg 554b3cf021fSjeremylt Restore access with @ref CeedVectorRestoreArrayRead(). 5550436c2adSjeremylt 556ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to access 557ca94c3ddSJeremy L Thompson @param[in] mem_type Memory type on which to access the array. 558ca94c3ddSJeremy L Thompson If the backend uses a different memory type, this will perform a copy (possibly cached). 559ca94c3ddSJeremy L Thompson @param[out] array Array on memory type `mem_type` 5600436c2adSjeremylt 5610436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 5620436c2adSjeremylt 5637a982d89SJeremy L. Thompson @ref User 5640436c2adSjeremylt **/ 5652b730f8bSJeremy L Thompson int CeedVectorGetArrayRead(CeedVector vec, CeedMemType mem_type, const CeedScalar **array) { 5661203703bSJeremy L Thompson CeedSize length; 5670436c2adSjeremylt 5689bc66399SJeremy L Thompson CeedCheck(vec->GetArrayRead, CeedVectorReturnCeed(vec), CEED_ERROR_UNSUPPORTED, "Backend does not support GetArrayRead"); 5699bc66399SJeremy L Thompson CeedCheck(vec->state % 2 == 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, 5709bc66399SJeremy L Thompson "Cannot grant CeedVector read-only array access, the access lock is already in use"); 5711203703bSJeremy L Thompson 5721203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 5731203703bSJeremy L Thompson if (length > 0) { 5749c774eddSJeremy L Thompson bool has_valid_array = true; 575b0976d5aSZach Atkins 5762b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(vec, &has_valid_array)); 5779bc66399SJeremy L Thompson CeedCheck(has_valid_array, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, 5782b730f8bSJeremy L Thompson "CeedVector has no valid data to read, must set data with CeedVectorSetValue or CeedVectorSetArray"); 5799c774eddSJeremy L Thompson 5802b730f8bSJeremy L Thompson CeedCall(vec->GetArrayRead(vec, mem_type, array)); 58150c643e1SJed Brown } else { 58250c643e1SJed Brown *array = NULL; 58350c643e1SJed Brown } 584d1d35e2fSjeremylt vec->num_readers++; 585e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5860436c2adSjeremylt } 5870436c2adSjeremylt 5880436c2adSjeremylt /** 589ca94c3ddSJeremy L Thompson @brief Get write access to a `CeedVector` via the specified memory type. 5904385fb7fSSebastian Grimberg 591ea61e9acSJeremy L Thompson Restore access with @ref CeedVectorRestoreArray(). 592ea61e9acSJeremy L Thompson All old values should be assumed to be invalid. 5939c774eddSJeremy L Thompson 594ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` to access 595ea61e9acSJeremy L Thompson @param[in] mem_type Memory type on which to access the array. 596ca94c3ddSJeremy L Thompson @param[out] array Array on memory type `mem_type` 5979c774eddSJeremy L Thompson 5989c774eddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 5999c774eddSJeremy L Thompson 6009c774eddSJeremy L Thompson @ref User 6019c774eddSJeremy L Thompson **/ 6022b730f8bSJeremy L Thompson int CeedVectorGetArrayWrite(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 6031203703bSJeremy L Thompson CeedSize length; 6049c774eddSJeremy L Thompson 6059bc66399SJeremy L Thompson CeedCheck(vec->GetArrayWrite, CeedVectorReturnCeed(vec), CEED_ERROR_UNSUPPORTED, "Backend does not support CeedVectorGetArrayWrite"); 6069bc66399SJeremy L Thompson CeedCheck(vec->state % 2 == 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, 6079bc66399SJeremy L Thompson "Cannot grant CeedVector array access, the access lock is already in use"); 6089bc66399SJeremy L Thompson CeedCheck(vec->num_readers == 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, a process has read access"); 6091203703bSJeremy L Thompson 6101203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 6111203703bSJeremy L Thompson if (length > 0) { 6122b730f8bSJeremy L Thompson CeedCall(vec->GetArrayWrite(vec, mem_type, array)); 613b0976d5aSZach Atkins } else { 614b0976d5aSZach Atkins *array = NULL; 615b0976d5aSZach Atkins } 61628bfd0b7SJeremy L Thompson vec->state++; 6179c774eddSJeremy L Thompson return CEED_ERROR_SUCCESS; 6189c774eddSJeremy L Thompson } 6199c774eddSJeremy L Thompson 6209c774eddSJeremy L Thompson /** 621ea61e9acSJeremy L Thompson @brief Restore an array obtained using @ref CeedVectorGetArray() or @ref CeedVectorGetArrayWrite() 6220436c2adSjeremylt 623ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` to restore 624ea61e9acSJeremy L Thompson @param[in,out] array Array of vector data 6250436c2adSjeremylt 6260436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 6270436c2adSjeremylt 6287a982d89SJeremy L. Thompson @ref User 6290436c2adSjeremylt **/ 6300436c2adSjeremylt int CeedVectorRestoreArray(CeedVector vec, CeedScalar **array) { 6311203703bSJeremy L Thompson CeedSize length; 6321203703bSJeremy L Thompson 6336e536b99SJeremy L Thompson CeedCheck(vec->state % 2 == 1, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, "Cannot restore CeedVector array access, access was not granted"); 6341203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 6351203703bSJeremy L Thompson if (length > 0 && vec->RestoreArray) CeedCall(vec->RestoreArray(vec)); 6360436c2adSjeremylt *array = NULL; 63728bfd0b7SJeremy L Thompson vec->state++; 638e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6390436c2adSjeremylt } 6400436c2adSjeremylt 6410436c2adSjeremylt /** 642b3cf021fSjeremylt @brief Restore an array obtained using @ref CeedVectorGetArrayRead() 6430436c2adSjeremylt 644ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to restore 645ea61e9acSJeremy L Thompson @param[in,out] array Array of vector data 6460436c2adSjeremylt 6470436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 6480436c2adSjeremylt 6497a982d89SJeremy L. Thompson @ref User 6500436c2adSjeremylt **/ 6510436c2adSjeremylt int CeedVectorRestoreArrayRead(CeedVector vec, const CeedScalar **array) { 6521203703bSJeremy L Thompson CeedSize length; 6531203703bSJeremy L Thompson 6546e536b99SJeremy L Thompson CeedCheck(vec->num_readers > 0, CeedVectorReturnCeed(vec), CEED_ERROR_ACCESS, 6556e536b99SJeremy L Thompson "Cannot restore CeedVector array read access, access was not granted"); 65675a19770SJeremy L Thompson vec->num_readers--; 6571203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 6581203703bSJeremy L Thompson if (length > 0 && vec->num_readers == 0 && vec->RestoreArrayRead) CeedCall(vec->RestoreArrayRead(vec)); 6590436c2adSjeremylt *array = NULL; 660e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6610436c2adSjeremylt } 6620436c2adSjeremylt 6630436c2adSjeremylt /** 664ca94c3ddSJeremy L Thompson @brief Get the norm of a `CeedVector`. 665171f8ca9Sjeremylt 666ca94c3ddSJeremy L Thompson Note: This operation is local to the `CeedVector`. 667ca94c3ddSJeremy 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. 668547d9b97Sjeremylt 669ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to retrieve maximum value 670ea61e9acSJeremy L Thompson @param[in] norm_type Norm type @ref CEED_NORM_1, @ref CEED_NORM_2, or @ref CEED_NORM_MAX 671547d9b97Sjeremylt @param[out] norm Variable to store norm value 672547d9b97Sjeremylt 673547d9b97Sjeremylt @return An error code: 0 - success, otherwise - failure 674547d9b97Sjeremylt 6757a982d89SJeremy L. Thompson @ref User 676547d9b97Sjeremylt **/ 677d1d35e2fSjeremylt int CeedVectorNorm(CeedVector vec, CeedNormType norm_type, CeedScalar *norm) { 6789c774eddSJeremy L Thompson bool has_valid_array = true; 6791203703bSJeremy L Thompson CeedSize length; 6801203703bSJeremy L Thompson 6812b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(vec, &has_valid_array)); 6826e536b99SJeremy L Thompson CeedCheck(has_valid_array, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, 6832b730f8bSJeremy L Thompson "CeedVector has no valid data to compute norm, must set data with CeedVectorSetValue or CeedVectorSetArray"); 6849c774eddSJeremy L Thompson 6851203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 6861203703bSJeremy L Thompson if (length == 0) { 687b0976d5aSZach Atkins *norm = 0; 688b0976d5aSZach Atkins return CEED_ERROR_SUCCESS; 689b0976d5aSZach Atkins } 690b0976d5aSZach Atkins 691547d9b97Sjeremylt // Backend impl for GPU, if added 692547d9b97Sjeremylt if (vec->Norm) { 6932b730f8bSJeremy L Thompson CeedCall(vec->Norm(vec, norm_type, norm)); 694e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 695547d9b97Sjeremylt } 696547d9b97Sjeremylt 697547d9b97Sjeremylt const CeedScalar *array; 6982b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(vec, CEED_MEM_HOST, &array)); 699b0976d5aSZach Atkins assert(array); 700547d9b97Sjeremylt 701547d9b97Sjeremylt *norm = 0.; 702d1d35e2fSjeremylt switch (norm_type) { 703547d9b97Sjeremylt case CEED_NORM_1: 7041203703bSJeremy L Thompson for (CeedSize i = 0; i < length; i++) { 705547d9b97Sjeremylt *norm += fabs(array[i]); 706547d9b97Sjeremylt } 707547d9b97Sjeremylt break; 708547d9b97Sjeremylt case CEED_NORM_2: 7091203703bSJeremy L Thompson for (CeedSize i = 0; i < length; i++) { 710547d9b97Sjeremylt *norm += fabs(array[i]) * fabs(array[i]); 711547d9b97Sjeremylt } 712547d9b97Sjeremylt break; 713547d9b97Sjeremylt case CEED_NORM_MAX: 7141203703bSJeremy L Thompson for (CeedSize i = 0; i < length; i++) { 715d1d35e2fSjeremylt const CeedScalar abs_v_i = fabs(array[i]); 716d1d35e2fSjeremylt *norm = *norm > abs_v_i ? *norm : abs_v_i; 717547d9b97Sjeremylt } 718547d9b97Sjeremylt } 7192b730f8bSJeremy L Thompson if (norm_type == CEED_NORM_2) *norm = sqrt(*norm); 720547d9b97Sjeremylt 7212b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArrayRead(vec, &array)); 722e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 723547d9b97Sjeremylt } 724547d9b97Sjeremylt 725547d9b97Sjeremylt /** 726ca94c3ddSJeremy L Thompson @brief Compute `x = alpha x` 727e0dd3b27Sjeremylt 728ca94c3ddSJeremy L Thompson @param[in,out] x `CeedVector` for scaling 72996b902e2Sjeremylt @param[in] alpha scaling factor 730e0dd3b27Sjeremylt 731e0dd3b27Sjeremylt @return An error code: 0 - success, otherwise - failure 732e0dd3b27Sjeremylt 733e0dd3b27Sjeremylt @ref User 734e0dd3b27Sjeremylt **/ 735e0dd3b27Sjeremylt int CeedVectorScale(CeedVector x, CeedScalar alpha) { 7369c774eddSJeremy L Thompson bool has_valid_array = true; 7371203703bSJeremy L Thompson CeedSize length; 7381203703bSJeremy L Thompson CeedScalar *x_array = NULL; 7391c66c397SJeremy L Thompson 7402b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(x, &has_valid_array)); 7416e536b99SJeremy L Thompson CeedCheck(has_valid_array, CeedVectorReturnCeed(x), CEED_ERROR_BACKEND, 7422b730f8bSJeremy L Thompson "CeedVector has no valid data to scale, must set data with CeedVectorSetValue or CeedVectorSetArray"); 7439c774eddSJeremy L Thompson 744b0976d5aSZach Atkins // Return early for empty vector 7451203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(x, &length)); 7461203703bSJeremy L Thompson if (length == 0) return CEED_ERROR_SUCCESS; 747b0976d5aSZach Atkins 748e0dd3b27Sjeremylt // Backend implementation 7492b730f8bSJeremy L Thompson if (x->Scale) return x->Scale(x, alpha); 750e0dd3b27Sjeremylt 751e0dd3b27Sjeremylt // Default implementation 752567d69a2SJeremy L Thompson CeedCall(CeedVectorGetArray(x, CEED_MEM_HOST, &x_array)); 753b0976d5aSZach Atkins assert(x_array); 7541203703bSJeremy L Thompson for (CeedSize i = 0; i < length; i++) x_array[i] *= alpha; 7552b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArray(x, &x_array)); 756e0dd3b27Sjeremylt return CEED_ERROR_SUCCESS; 757e0dd3b27Sjeremylt } 758e0dd3b27Sjeremylt 759e0dd3b27Sjeremylt /** 760ca94c3ddSJeremy L Thompson @brief Compute `y = alpha x + y` 7610f7fd0f8Sjeremylt 762ca94c3ddSJeremy L Thompson @param[in,out] y target `CeedVector` for sum 76396b902e2Sjeremylt @param[in] alpha scaling factor 764ca94c3ddSJeremy L Thompson @param[in] x second `CeedVector`, must be different than ``y` 7650f7fd0f8Sjeremylt 7660f7fd0f8Sjeremylt @return An error code: 0 - success, otherwise - failure 7670f7fd0f8Sjeremylt 7680f7fd0f8Sjeremylt @ref User 7690f7fd0f8Sjeremylt **/ 7700f7fd0f8Sjeremylt int CeedVectorAXPY(CeedVector y, CeedScalar alpha, CeedVector x) { 7711203703bSJeremy L Thompson bool has_valid_array_x = true, has_valid_array_y = true; 7721203703bSJeremy L Thompson CeedSize length_x, length_y; 77373380422SJeremy L Thompson CeedScalar *y_array = NULL; 77473380422SJeremy L Thompson CeedScalar const *x_array = NULL; 7750f7fd0f8Sjeremylt 7761203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(y, &length_y)); 7771203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(x, &length_x)); 7789bc66399SJeremy L Thompson CeedCheck(length_x == length_y, CeedVectorReturnCeed(y), CEED_ERROR_UNSUPPORTED, 7793f08121cSJeremy L Thompson "Cannot add vector of different lengths." 7803f08121cSJeremy L Thompson " x length: %" CeedSize_FMT " y length: %" CeedSize_FMT, 7813f08121cSJeremy L Thompson length_x, length_y); 7829bc66399SJeremy L Thompson CeedCheck(x != y, CeedVectorReturnCeed(y), CEED_ERROR_UNSUPPORTED, "Cannot use same vector for x and y in CeedVectorAXPY"); 7830f7fd0f8Sjeremylt 7842b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(x, &has_valid_array_x)); 7859bc66399SJeremy L Thompson CeedCheck(has_valid_array_x, CeedVectorReturnCeed(y), CEED_ERROR_BACKEND, 7866574a04fSJeremy L Thompson "CeedVector x has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 7872b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(y, &has_valid_array_y)); 7889bc66399SJeremy L Thompson CeedCheck(has_valid_array_y, CeedVectorReturnCeed(y), CEED_ERROR_BACKEND, 7896574a04fSJeremy L Thompson "CeedVector y has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 7909c774eddSJeremy L Thompson 7919bc66399SJeremy L Thompson { 7929bc66399SJeremy L Thompson Ceed ceed_x, ceed_y, ceed_parent_x, ceed_parent_y; 7939bc66399SJeremy L Thompson 7949bc66399SJeremy L Thompson CeedCall(CeedVectorGetCeed(y, &ceed_y)); 7959bc66399SJeremy L Thompson CeedCall(CeedVectorGetCeed(x, &ceed_x)); 7969bc66399SJeremy L Thompson CeedCall(CeedGetParent(ceed_x, &ceed_parent_x)); 7979bc66399SJeremy L Thompson CeedCall(CeedGetParent(ceed_y, &ceed_parent_y)); 7989bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_x)); 7999bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_y)); 8009bc66399SJeremy L Thompson CeedCheck(ceed_parent_x == ceed_parent_y, CeedVectorReturnCeed(y), CEED_ERROR_INCOMPATIBLE, 8019bc66399SJeremy L Thompson "Vectors x and y must be created by the same Ceed context"); 8029bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent_x)); 8039bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent_y)); 8049bc66399SJeremy L Thompson } 8052d04630dSjeremylt 806b0976d5aSZach Atkins // Return early for empty vectors 8071203703bSJeremy L Thompson if (length_y == 0) return CEED_ERROR_SUCCESS; 808b0976d5aSZach Atkins 8090f7fd0f8Sjeremylt // Backend implementation 810eaf62fffSJeremy L Thompson if (y->AXPY) { 8112b730f8bSJeremy L Thompson CeedCall(y->AXPY(y, alpha, x)); 812eaf62fffSJeremy L Thompson return CEED_ERROR_SUCCESS; 813eaf62fffSJeremy L Thompson } 8140f7fd0f8Sjeremylt 8150f7fd0f8Sjeremylt // Default implementation 816567d69a2SJeremy L Thompson CeedCall(CeedVectorGetArray(y, CEED_MEM_HOST, &y_array)); 8172b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(x, CEED_MEM_HOST, &x_array)); 8180f7fd0f8Sjeremylt 8192b730f8bSJeremy L Thompson assert(x_array); 8202b730f8bSJeremy L Thompson assert(y_array); 82173380422SJeremy L Thompson 8221203703bSJeremy L Thompson for (CeedSize i = 0; i < length_y; i++) y_array[i] += alpha * x_array[i]; 8230f7fd0f8Sjeremylt 8242b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArray(y, &y_array)); 8252b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArrayRead(x, &x_array)); 8260f7fd0f8Sjeremylt return CEED_ERROR_SUCCESS; 8270f7fd0f8Sjeremylt } 8280f7fd0f8Sjeremylt 8290f7fd0f8Sjeremylt /** 830ca94c3ddSJeremy L Thompson @brief Compute `y = alpha x + beta y` 8315fb68f37SKaren (Ren) Stengel 832ca94c3ddSJeremy L Thompson @param[in,out] y target `CeedVector` for sum 8335fb68f37SKaren (Ren) Stengel @param[in] alpha first scaling factor 8345fb68f37SKaren (Ren) Stengel @param[in] beta second scaling factor 835ca94c3ddSJeremy L Thompson @param[in] x second `CeedVector`, must be different than `y` 8365fb68f37SKaren (Ren) Stengel 8375fb68f37SKaren (Ren) Stengel @return An error code: 0 - success, otherwise - failure 8385fb68f37SKaren (Ren) Stengel 8395fb68f37SKaren (Ren) Stengel @ref User 8405fb68f37SKaren (Ren) Stengel **/ 8415fb68f37SKaren (Ren) Stengel int CeedVectorAXPBY(CeedVector y, CeedScalar alpha, CeedScalar beta, CeedVector x) { 8421203703bSJeremy L Thompson bool has_valid_array_x = true, has_valid_array_y = true; 8431203703bSJeremy L Thompson CeedSize length_x, length_y; 8445fb68f37SKaren (Ren) Stengel CeedScalar *y_array = NULL; 8455fb68f37SKaren (Ren) Stengel CeedScalar const *x_array = NULL; 8461203703bSJeremy L Thompson 8471203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(y, &length_y)); 8481203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(x, &length_x)); 8499bc66399SJeremy L Thompson CeedCheck(length_x == length_y, CeedVectorReturnCeed(y), CEED_ERROR_UNSUPPORTED, 8503f08121cSJeremy L Thompson "Cannot add vector of different lengths." 8513f08121cSJeremy L Thompson " x length: %" CeedSize_FMT " y length: %" CeedSize_FMT, 8523f08121cSJeremy L Thompson length_x, length_y); 8539bc66399SJeremy L Thompson CeedCheck(x != y, CeedVectorReturnCeed(y), CEED_ERROR_UNSUPPORTED, "Cannot use same vector for x and y in CeedVectorAXPBY"); 8545fb68f37SKaren (Ren) Stengel 8555fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorHasValidArray(x, &has_valid_array_x)); 8569bc66399SJeremy L Thompson CeedCheck(has_valid_array_x, CeedVectorReturnCeed(y), CEED_ERROR_BACKEND, 8576574a04fSJeremy L Thompson "CeedVector x has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 8585fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorHasValidArray(y, &has_valid_array_y)); 8599bc66399SJeremy L Thompson CeedCheck(has_valid_array_y, CeedVectorReturnCeed(y), CEED_ERROR_BACKEND, 8606574a04fSJeremy L Thompson "CeedVector y has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 8615fb68f37SKaren (Ren) Stengel 8629bc66399SJeremy L Thompson { 8639bc66399SJeremy L Thompson Ceed ceed_x, ceed_y, ceed_parent_x, ceed_parent_y; 8649bc66399SJeremy L Thompson 8659bc66399SJeremy L Thompson CeedCall(CeedVectorGetCeed(y, &ceed_y)); 8669bc66399SJeremy L Thompson CeedCall(CeedVectorGetCeed(x, &ceed_x)); 8679bc66399SJeremy L Thompson CeedCall(CeedGetParent(ceed_x, &ceed_parent_x)); 8689bc66399SJeremy L Thompson CeedCall(CeedGetParent(ceed_y, &ceed_parent_y)); 8699bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_x)); 8709bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_y)); 8719bc66399SJeremy L Thompson CeedCheck(ceed_parent_x == ceed_parent_y, CeedVectorReturnCeed(y), CEED_ERROR_INCOMPATIBLE, 8729bc66399SJeremy L Thompson "Vectors x and y must be created by the same Ceed context"); 8739bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent_x)); 8749bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent_y)); 8759bc66399SJeremy L Thompson } 8765fb68f37SKaren (Ren) Stengel 877b0976d5aSZach Atkins // Return early for empty vectors 8781203703bSJeremy L Thompson if (length_y == 0) return CEED_ERROR_SUCCESS; 879b0976d5aSZach Atkins 8805fb68f37SKaren (Ren) Stengel // Backend implementation 8815fb68f37SKaren (Ren) Stengel if (y->AXPBY) { 8825fb68f37SKaren (Ren) Stengel CeedCall(y->AXPBY(y, alpha, beta, x)); 8835fb68f37SKaren (Ren) Stengel return CEED_ERROR_SUCCESS; 8845fb68f37SKaren (Ren) Stengel } 8855fb68f37SKaren (Ren) Stengel 8865fb68f37SKaren (Ren) Stengel // Default implementation 8875fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorGetArray(y, CEED_MEM_HOST, &y_array)); 8885fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorGetArrayRead(x, CEED_MEM_HOST, &x_array)); 8895fb68f37SKaren (Ren) Stengel 8905fb68f37SKaren (Ren) Stengel assert(x_array); 8915fb68f37SKaren (Ren) Stengel assert(y_array); 8925fb68f37SKaren (Ren) Stengel 8931203703bSJeremy L Thompson for (CeedSize i = 0; i < length_y; i++) y_array[i] = alpha * x_array[i] + beta * y_array[i]; 8945fb68f37SKaren (Ren) Stengel 8955fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorRestoreArray(y, &y_array)); 8965fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorRestoreArrayRead(x, &x_array)); 8975fb68f37SKaren (Ren) Stengel return CEED_ERROR_SUCCESS; 8985fb68f37SKaren (Ren) Stengel } 8995fb68f37SKaren (Ren) Stengel 9005fb68f37SKaren (Ren) Stengel /** 901ca94c3ddSJeremy L Thompson @brief Compute the pointwise multiplication \f$w = x .* y\f$. 9024385fb7fSSebastian Grimberg 903ca94c3ddSJeremy L Thompson Any subset of `x`, `y`, and `w` may be the same `CeedVector`. 9040f7fd0f8Sjeremylt 905ca94c3ddSJeremy L Thompson @param[out] w target `CeedVector` for the product 906ca94c3ddSJeremy L Thompson @param[in] x first `CeedVector` for product 907ca94c3ddSJeremy L Thompson @param[in] y second `CeedVector` for the product 9080f7fd0f8Sjeremylt 9090f7fd0f8Sjeremylt @return An error code: 0 - success, otherwise - failure 9100f7fd0f8Sjeremylt 9110f7fd0f8Sjeremylt @ref User 9120f7fd0f8Sjeremylt **/ 9130f7fd0f8Sjeremylt int CeedVectorPointwiseMult(CeedVector w, CeedVector x, CeedVector y) { 9141203703bSJeremy L Thompson bool has_valid_array_x = true, has_valid_array_y = true; 91573380422SJeremy L Thompson CeedScalar *w_array = NULL; 91673380422SJeremy L Thompson CeedScalar const *x_array = NULL, *y_array = NULL; 9171203703bSJeremy L Thompson CeedSize length_w, length_x, length_y; 9180f7fd0f8Sjeremylt 9191203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(w, &length_w)); 9201203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(x, &length_x)); 9211203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(y, &length_y)); 9229bc66399SJeremy L Thompson CeedCheck(length_x >= length_w && length_y >= length_w, CeedVectorReturnCeed(w), CEED_ERROR_UNSUPPORTED, 923ccad5cb9SJeremy L Thompson "Cannot pointwise multiply vectors of incompatible lengths." 924ccad5cb9SJeremy L Thompson " w length: %" CeedSize_FMT " x length: %" CeedSize_FMT " y length: %" CeedSize_FMT, 925ccad5cb9SJeremy L Thompson length_w, length_x, length_y); 9260f7fd0f8Sjeremylt 9279bc66399SJeremy L Thompson { 9289bc66399SJeremy L Thompson Ceed ceed_w, ceed_x, ceed_y, ceed_parent_w, ceed_parent_x, ceed_parent_y; 9299bc66399SJeremy L Thompson 9309bc66399SJeremy L Thompson CeedCall(CeedVectorGetCeed(w, &ceed_w)); 9319bc66399SJeremy L Thompson CeedCall(CeedVectorGetCeed(x, &ceed_x)); 9329bc66399SJeremy L Thompson CeedCall(CeedVectorGetCeed(y, &ceed_y)); 9339bc66399SJeremy L Thompson CeedCall(CeedGetParent(ceed_w, &ceed_parent_w)); 9349bc66399SJeremy L Thompson CeedCall(CeedGetParent(ceed_x, &ceed_parent_x)); 9359bc66399SJeremy L Thompson CeedCall(CeedGetParent(ceed_y, &ceed_parent_y)); 9369bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_w)); 9379bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_x)); 9389bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_y)); 9399bc66399SJeremy L Thompson CeedCheck(ceed_parent_w == ceed_parent_x && ceed_parent_w == ceed_parent_y, CeedVectorReturnCeed(w), CEED_ERROR_INCOMPATIBLE, 9406574a04fSJeremy L Thompson "Vectors w, x, and y must be created by the same Ceed context"); 9419bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent_w)); 9429bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent_x)); 9439bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent_y)); 9449bc66399SJeremy L Thompson } 9452d04630dSjeremylt 9462b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(x, &has_valid_array_x)); 9479bc66399SJeremy L Thompson CeedCheck(has_valid_array_x, CeedVectorReturnCeed(w), CEED_ERROR_BACKEND, 9486574a04fSJeremy L Thompson "CeedVector x has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 9492b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(y, &has_valid_array_y)); 9509bc66399SJeremy L Thompson CeedCheck(has_valid_array_y, CeedVectorReturnCeed(w), CEED_ERROR_BACKEND, 9516574a04fSJeremy L Thompson "CeedVector y has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 9529c774eddSJeremy L Thompson 953b0976d5aSZach Atkins // Return early for empty vectors 9541203703bSJeremy L Thompson if (length_w == 0) return CEED_ERROR_SUCCESS; 955b0976d5aSZach Atkins 9560f7fd0f8Sjeremylt // Backend implementation 957eaf62fffSJeremy L Thompson if (w->PointwiseMult) { 9582b730f8bSJeremy L Thompson CeedCall(w->PointwiseMult(w, x, y)); 959eaf62fffSJeremy L Thompson return CEED_ERROR_SUCCESS; 960eaf62fffSJeremy L Thompson } 9610f7fd0f8Sjeremylt 9620f7fd0f8Sjeremylt // Default implementation 963b0976d5aSZach Atkins if (x == w || y == w) { 964b0976d5aSZach Atkins CeedCall(CeedVectorGetArray(w, CEED_MEM_HOST, &w_array)); 965b0976d5aSZach Atkins } else { 966b0976d5aSZach Atkins CeedCall(CeedVectorGetArrayWrite(w, CEED_MEM_HOST, &w_array)); 967b0976d5aSZach Atkins } 9680f7fd0f8Sjeremylt if (x != w) { 9692b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(x, CEED_MEM_HOST, &x_array)); 9700f7fd0f8Sjeremylt } else { 9710f7fd0f8Sjeremylt x_array = w_array; 9720f7fd0f8Sjeremylt } 9730f7fd0f8Sjeremylt if (y != w && y != x) { 9742b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(y, CEED_MEM_HOST, &y_array)); 975c6d796c6SJeremy L Thompson } else if (y == x) { 9760f7fd0f8Sjeremylt y_array = x_array; 977b0976d5aSZach Atkins } else if (y == w) { 978c6d796c6SJeremy L Thompson y_array = w_array; 9790f7fd0f8Sjeremylt } 9800f7fd0f8Sjeremylt 9812b730f8bSJeremy L Thompson assert(w_array); 9822b730f8bSJeremy L Thompson assert(x_array); 9832b730f8bSJeremy L Thompson assert(y_array); 98473380422SJeremy L Thompson 9851203703bSJeremy L Thompson for (CeedSize i = 0; i < length_w; i++) w_array[i] = x_array[i] * y_array[i]; 9860f7fd0f8Sjeremylt 9872b730f8bSJeremy L Thompson if (y != w && y != x) CeedCall(CeedVectorRestoreArrayRead(y, &y_array)); 9882b730f8bSJeremy L Thompson if (x != w) CeedCall(CeedVectorRestoreArrayRead(x, &x_array)); 9892b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArray(w, &w_array)); 9900f7fd0f8Sjeremylt return CEED_ERROR_SUCCESS; 9910f7fd0f8Sjeremylt } 9920f7fd0f8Sjeremylt 9930f7fd0f8Sjeremylt /** 994ca94c3ddSJeremy L Thompson @brief Take the reciprocal of a `CeedVector`. 995d99fa3c5SJeremy L Thompson 996ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` to take reciprocal 997d99fa3c5SJeremy L Thompson 998d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 999d99fa3c5SJeremy L Thompson 1000d99fa3c5SJeremy L Thompson @ref User 1001d99fa3c5SJeremy L Thompson **/ 1002d99fa3c5SJeremy L Thompson int CeedVectorReciprocal(CeedVector vec) { 10039c774eddSJeremy L Thompson bool has_valid_array = true; 10041203703bSJeremy L Thompson CeedSize length; 10051203703bSJeremy L Thompson CeedScalar *array; 10062b730f8bSJeremy L Thompson 10071c66c397SJeremy L Thompson CeedCall(CeedVectorHasValidArray(vec, &has_valid_array)); 10089bc66399SJeremy L Thompson CeedCheck(has_valid_array, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, 10092b730f8bSJeremy L Thompson "CeedVector has no valid data to compute reciprocal, must set data with CeedVectorSetValue or CeedVectorSetArray"); 10109c774eddSJeremy L Thompson 1011d99fa3c5SJeremy L Thompson // Check if vector data set 10129bc66399SJeremy L Thompson CeedCheck(vec->state > 0, CeedVectorReturnCeed(vec), CEED_ERROR_INCOMPLETE, "CeedVector must have data set to take reciprocal"); 1013d99fa3c5SJeremy L Thompson 1014b0976d5aSZach Atkins // Return early for empty vector 10151203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 10161203703bSJeremy L Thompson if (length == 0) return CEED_ERROR_SUCCESS; 1017b0976d5aSZach Atkins 1018d99fa3c5SJeremy L Thompson // Backend impl for GPU, if added 1019d99fa3c5SJeremy L Thompson if (vec->Reciprocal) { 10202b730f8bSJeremy L Thompson CeedCall(vec->Reciprocal(vec)); 1021e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1022d99fa3c5SJeremy L Thompson } 1023d99fa3c5SJeremy L Thompson 1024567d69a2SJeremy L Thompson CeedCall(CeedVectorGetArray(vec, CEED_MEM_HOST, &array)); 10251203703bSJeremy L Thompson for (CeedSize i = 0; i < length; i++) { 10262b730f8bSJeremy L Thompson if (fabs(array[i]) > CEED_EPSILON) array[i] = 1. / array[i]; 10272b730f8bSJeremy L Thompson } 1028d99fa3c5SJeremy L Thompson 10292b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArray(vec, &array)); 1030e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1031d99fa3c5SJeremy L Thompson } 1032d99fa3c5SJeremy L Thompson 1033d99fa3c5SJeremy L Thompson /** 10344c789ea2SJeremy L Thompson @brief Set the number of tabs to indent for @ref CeedVectorView() output 10354c789ea2SJeremy L Thompson 10364c789ea2SJeremy L Thompson @param[in] vec `CeedVector` to set the number of view tabs 10374c789ea2SJeremy L Thompson @param[in] num_tabs Number of view tabs to set 10384c789ea2SJeremy L Thompson 10394c789ea2SJeremy L Thompson @return Error code: 0 - success, otherwise - failure 10404c789ea2SJeremy L Thompson 10414c789ea2SJeremy L Thompson @ref User 10424c789ea2SJeremy L Thompson **/ 10434c789ea2SJeremy L Thompson int CeedVectorSetNumViewTabs(CeedVector vec, CeedInt num_tabs) { 1044a299a25bSJeremy L Thompson CeedCall(CeedObjectSetNumViewTabs((CeedObject)vec, num_tabs)); 10454c789ea2SJeremy L Thompson return CEED_ERROR_SUCCESS; 10464c789ea2SJeremy L Thompson } 10474c789ea2SJeremy L Thompson 10484c789ea2SJeremy L Thompson /** 1049690992b2SZach Atkins @brief Get the number of tabs to indent for @ref CeedVectorView() output 1050690992b2SZach Atkins 1051690992b2SZach Atkins @param[in] vec `CeedVector` to get the number of view tabs 1052690992b2SZach Atkins @param[out] num_tabs Number of view tabs 1053690992b2SZach Atkins 1054690992b2SZach Atkins @return Error code: 0 - success, otherwise - failure 1055690992b2SZach Atkins 1056690992b2SZach Atkins @ref User 1057690992b2SZach Atkins **/ 1058690992b2SZach Atkins int CeedVectorGetNumViewTabs(CeedVector vec, CeedInt *num_tabs) { 1059a299a25bSJeremy L Thompson CeedCall(CeedObjectGetNumViewTabs((CeedObject)vec, num_tabs)); 1060690992b2SZach Atkins return CEED_ERROR_SUCCESS; 1061690992b2SZach Atkins } 1062690992b2SZach Atkins 1063690992b2SZach Atkins /** 1064ca94c3ddSJeremy L Thompson @brief View a `CeedVector` 10650436c2adSjeremylt 1066acb2c48cSJeremy L Thompson Note: It is safe to use any unsigned values for `start` or `stop` and any nonzero integer for `step`. 1067ca94c3ddSJeremy L Thompson Any portion of the provided range that is outside the range of valid indices for the `CeedVector` will be ignored. 1068acb2c48cSJeremy L Thompson 1069ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to view 1070f52f9f6cSJeremy L Thompson @param[in] start Index of first `CeedVector` entry to view in the range `[start, stop)` 1071f52f9f6cSJeremy L Thompson @param[in] stop One past the last element to view in the range, or `-1` for `length` 1072ca94c3ddSJeremy L Thompson @param[in] step Step between `CeedVector` entries to view 1073acb2c48cSJeremy L Thompson @param[in] fp_fmt Printing format 1074acb2c48cSJeremy L Thompson @param[in] stream Filestream to write to 1075acb2c48cSJeremy L Thompson 1076acb2c48cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1077acb2c48cSJeremy L Thompson 1078acb2c48cSJeremy L Thompson @ref User 1079acb2c48cSJeremy L Thompson **/ 1080acb2c48cSJeremy L Thompson int CeedVectorViewRange(CeedVector vec, CeedSize start, CeedSize stop, CeedInt step, const char *fp_fmt, FILE *stream) { 1081acb2c48cSJeremy L Thompson char fmt[1024]; 10824c789ea2SJeremy L Thompson char *tabs = NULL; 10831203703bSJeremy L Thompson CeedSize length; 10841203703bSJeremy L Thompson const CeedScalar *x; 1085acb2c48cSJeremy L Thompson 10866e536b99SJeremy L Thompson CeedCheck(step != 0, CeedVectorReturnCeed(vec), CEED_ERROR_MINOR, "View range 'step' must be nonzero"); 1087acb2c48cSJeremy L Thompson 10884c789ea2SJeremy L Thompson { 10894c789ea2SJeremy L Thompson CeedInt num_tabs = 0; 10904c789ea2SJeremy L Thompson 10914c789ea2SJeremy L Thompson CeedCall(CeedVectorGetNumViewTabs(vec, &num_tabs)); 10924c789ea2SJeremy L Thompson CeedCall(CeedCalloc(CEED_TAB_WIDTH * num_tabs + 1, &tabs)); 10934c789ea2SJeremy L Thompson for (CeedInt i = 0; i < CEED_TAB_WIDTH * num_tabs; i++) tabs[i] = ' '; 10944c789ea2SJeremy L Thompson } 10954c789ea2SJeremy L Thompson 10961203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 10974c789ea2SJeremy L Thompson fprintf(stream, "%sCeedVector length %" CeedSize_FMT "\n", tabs, length); 10981203703bSJeremy L Thompson if (start != 0 || stop != length || step != 1) { 10994c789ea2SJeremy L Thompson fprintf(stream, "%s start: %" CeedSize_FMT "\n%s stop: %" CeedSize_FMT "\n%s step: %" CeedInt_FMT "\n", tabs, start, tabs, stop, tabs, step); 1100acb2c48cSJeremy L Thompson } 11011203703bSJeremy L Thompson if (start > length) start = length; 1102f52f9f6cSJeremy L Thompson if (stop == -1 || stop > length) stop = length; 1103acb2c48cSJeremy L Thompson 11044c789ea2SJeremy L Thompson snprintf(fmt, sizeof fmt, "%s %s\n", tabs, fp_fmt ? fp_fmt : "%g"); 1105acb2c48cSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(vec, CEED_MEM_HOST, &x)); 1106b94338b9SJed Brown for (CeedSize i = start; step > 0 ? (i < stop) : (i > stop); i += step) fprintf(stream, fmt, x[i]); 1107acb2c48cSJeremy L Thompson CeedCall(CeedVectorRestoreArrayRead(vec, &x)); 11084c789ea2SJeremy L Thompson if (stop != length) fprintf(stream, "%s ...\n", tabs); 11094c789ea2SJeremy L Thompson CeedCall(CeedFree(&tabs)); 1110acb2c48cSJeremy L Thompson return CEED_ERROR_SUCCESS; 1111acb2c48cSJeremy L Thompson } 1112acb2c48cSJeremy L Thompson 1113acb2c48cSJeremy L Thompson /** 1114ca94c3ddSJeremy L Thompson @brief View a `CeedVector` 1115acb2c48cSJeremy L Thompson 1116ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to view 1117d1d35e2fSjeremylt @param[in] fp_fmt Printing format 11180a0da059Sjeremylt @param[in] stream Filestream to write to 11190a0da059Sjeremylt 11200436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 11210436c2adSjeremylt 11227a982d89SJeremy L. Thompson @ref User 11230436c2adSjeremylt **/ 1124d1d35e2fSjeremylt int CeedVectorView(CeedVector vec, const char *fp_fmt, FILE *stream) { 11251203703bSJeremy L Thompson CeedSize length; 11261203703bSJeremy L Thompson 11271203703bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &length)); 11281203703bSJeremy L Thompson CeedCall(CeedVectorViewRange(vec, 0, length, 1, fp_fmt, stream)); 1129e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 11300436c2adSjeremylt } 11310436c2adSjeremylt 11320436c2adSjeremylt /** 1133ca94c3ddSJeremy L Thompson @brief Get the `Ceed` associated with a `CeedVector` 1134b7c9bbdaSJeremy L Thompson 1135ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to retrieve state 1136ca94c3ddSJeremy L Thompson @param[out] ceed Variable to store `Ceed` 1137b7c9bbdaSJeremy L Thompson 1138b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1139b7c9bbdaSJeremy L Thompson 1140b7c9bbdaSJeremy L Thompson @ref Advanced 1141b7c9bbdaSJeremy L Thompson **/ 1142b7c9bbdaSJeremy L Thompson int CeedVectorGetCeed(CeedVector vec, Ceed *ceed) { 1143b0f67a9cSJeremy L Thompson CeedCall(CeedObjectGetCeed((CeedObject)vec, ceed)); 1144b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 1145b7c9bbdaSJeremy L Thompson } 1146b7c9bbdaSJeremy L Thompson 1147b7c9bbdaSJeremy L Thompson /** 11486e536b99SJeremy L Thompson @brief Return the `Ceed` associated with a `CeedVector` 11496e536b99SJeremy L Thompson 11506e536b99SJeremy L Thompson @param[in] vec `CeedVector` to retrieve state 11516e536b99SJeremy L Thompson 11526e536b99SJeremy L Thompson @return `Ceed` associated with the `vec` 11536e536b99SJeremy L Thompson 11546e536b99SJeremy L Thompson @ref Advanced 11556e536b99SJeremy L Thompson **/ 1156b0f67a9cSJeremy L Thompson Ceed CeedVectorReturnCeed(CeedVector vec) { return CeedObjectReturnCeed((CeedObject)vec); } 11576e536b99SJeremy L Thompson 11586e536b99SJeremy L Thompson /** 1159ca94c3ddSJeremy L Thompson @brief Get the length of a `CeedVector` 11600436c2adSjeremylt 1161ca94c3ddSJeremy L Thompson @param[in] vec `CeedVector` to retrieve length 11627a982d89SJeremy L. Thompson @param[out] length Variable to store length 11630436c2adSjeremylt 11640436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 11650436c2adSjeremylt 11667a982d89SJeremy L. Thompson @ref User 11670436c2adSjeremylt **/ 11681f9221feSJeremy L Thompson int CeedVectorGetLength(CeedVector vec, CeedSize *length) { 11697a982d89SJeremy L. Thompson *length = vec->length; 1170e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 11710436c2adSjeremylt } 11720436c2adSjeremylt 11730436c2adSjeremylt /** 1174ca94c3ddSJeremy L Thompson @brief Destroy a `CeedVector` 11750436c2adSjeremylt 1176ca94c3ddSJeremy L Thompson @param[in,out] vec `CeedVector` to destroy 11770436c2adSjeremylt 11780436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 11790436c2adSjeremylt 11807a982d89SJeremy L. Thompson @ref User 11810436c2adSjeremylt **/ 11820436c2adSjeremylt int CeedVectorDestroy(CeedVector *vec) { 1183b0f67a9cSJeremy L Thompson if (!*vec || *vec == CEED_VECTOR_ACTIVE || *vec == CEED_VECTOR_NONE || CeedObjectDereference((CeedObject)*vec) > 0) { 1184ad6481ceSJeremy L Thompson *vec = NULL; 1185ad6481ceSJeremy L Thompson return CEED_ERROR_SUCCESS; 1186ad6481ceSJeremy L Thompson } 1187b0f67a9cSJeremy L Thompson CeedCheck((*vec)->state % 2 == 0, CeedVectorReturnCeed(*vec), CEED_ERROR_ACCESS, "Cannot destroy CeedVector, the writable access lock is in use"); 1188b0f67a9cSJeremy L Thompson CeedCheck((*vec)->num_readers == 0, CeedVectorReturnCeed(*vec), CEED_ERROR_ACCESS, "Cannot destroy CeedVector, a process has read access"); 11890436c2adSjeremylt 11902b730f8bSJeremy L Thompson if ((*vec)->Destroy) CeedCall((*vec)->Destroy(*vec)); 1191*6c328a79SJeremy L Thompson CeedCall(CeedObjectDestroy_Private(&(*vec)->obj)); 11922b730f8bSJeremy L Thompson CeedCall(CeedFree(vec)); 1193e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 11940436c2adSjeremylt } 11950436c2adSjeremylt 11960436c2adSjeremylt /// @} 1197