13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, 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 873380422SJeremy L Thompson #include <assert.h> 92b730f8bSJeremy L Thompson #include <ceed-impl.h> 1049aac155SJeremy L Thompson #include <ceed.h> 112b730f8bSJeremy L Thompson #include <ceed/backend.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 28ea61e9acSJeremy L Thompson /// Indicate that vector will be provided as an explicit argument to 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 /** 439c774eddSJeremy L Thompson @brief Check for valid data in a CeedVector 449c774eddSJeremy L Thompson 45ea61e9acSJeremy 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) { 53*6574a04fSJeremy L Thompson CeedCheck(vec->HasValidArray, vec->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support HasValidArray"); 542b730f8bSJeremy L Thompson CeedCall(vec->HasValidArray(vec, has_valid_array)); 559c774eddSJeremy L Thompson return CEED_ERROR_SUCCESS; 569c774eddSJeremy L Thompson } 579c774eddSJeremy L Thompson 589c774eddSJeremy L Thompson /** 599c774eddSJeremy L Thompson @brief Check for borrowed array of a specific CeedMemType in a CeedVector 609c774eddSJeremy L Thompson 61ea61e9acSJeremy L Thompson @param[in] vec CeedVector to check 62ea61e9acSJeremy L Thompson @param[in] mem_type Memory type to check 639c774eddSJeremy L Thompson @param[out] has_borrowed_array_of_type Variable to store result 649c774eddSJeremy L Thompson 659c774eddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 669c774eddSJeremy L Thompson 679c774eddSJeremy L Thompson @ref Backend 689c774eddSJeremy L Thompson **/ 692b730f8bSJeremy L Thompson int CeedVectorHasBorrowedArrayOfType(CeedVector vec, CeedMemType mem_type, bool *has_borrowed_array_of_type) { 70*6574a04fSJeremy L Thompson CeedCheck(vec->HasBorrowedArrayOfType, vec->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support HasBorrowedArrayOfType"); 712b730f8bSJeremy L Thompson CeedCall(vec->HasBorrowedArrayOfType(vec, mem_type, has_borrowed_array_of_type)); 729c774eddSJeremy L Thompson return CEED_ERROR_SUCCESS; 739c774eddSJeremy L Thompson } 749c774eddSJeremy L Thompson 759c774eddSJeremy L Thompson /** 767a982d89SJeremy L. Thompson @brief Get the state of a CeedVector 777a982d89SJeremy L. Thompson 78ea61e9acSJeremy L Thompson @param[in] vec CeedVector to retrieve state 797a982d89SJeremy L. Thompson @param[out] state Variable to store state 807a982d89SJeremy L. Thompson 817a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 827a982d89SJeremy L. Thompson 837a982d89SJeremy L. Thompson @ref Backend 847a982d89SJeremy L. Thompson **/ 857a982d89SJeremy L. Thompson int CeedVectorGetState(CeedVector vec, uint64_t *state) { 867a982d89SJeremy L. Thompson *state = vec->state; 87e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 887a982d89SJeremy L. Thompson } 897a982d89SJeremy L. Thompson 907a982d89SJeremy L. Thompson /** 9127312b0fSJed Brown @brief Add a reference to a CeedVector 927a982d89SJeremy L. Thompson 93ea61e9acSJeremy L Thompson @param[in,out] vec CeedVector to increment reference counter 947a982d89SJeremy L. Thompson 957a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 967a982d89SJeremy L. Thompson 977a982d89SJeremy L. Thompson @ref Backend 987a982d89SJeremy L. Thompson **/ 997a982d89SJeremy L. Thompson int CeedVectorAddReference(CeedVector vec) { 100d1d35e2fSjeremylt vec->ref_count++; 101e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1027a982d89SJeremy L. Thompson } 1037a982d89SJeremy L. Thompson 1047a982d89SJeremy L. Thompson /** 1057a982d89SJeremy L. Thompson @brief Get the backend data of a CeedVector 1067a982d89SJeremy L. Thompson 107ea61e9acSJeremy L Thompson @param[in] vec CeedVector to retrieve state 1087a982d89SJeremy L. Thompson @param[out] data Variable to store data 1097a982d89SJeremy L. Thompson 1107a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1117a982d89SJeremy L. Thompson 1127a982d89SJeremy L. Thompson @ref Backend 1137a982d89SJeremy L. Thompson **/ 114777ff853SJeremy L Thompson int CeedVectorGetData(CeedVector vec, void *data) { 115777ff853SJeremy L Thompson *(void **)data = vec->data; 116e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1177a982d89SJeremy L. Thompson } 1187a982d89SJeremy L. Thompson 1197a982d89SJeremy L. Thompson /** 1207a982d89SJeremy L. Thompson @brief Set the backend data of a CeedVector 1217a982d89SJeremy L. Thompson 122ea61e9acSJeremy L Thompson @param[in,out] vec CeedVector to retrieve state 123ea61e9acSJeremy L Thompson @param[in] data Data to set 1247a982d89SJeremy L. Thompson 1257a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1267a982d89SJeremy L. Thompson 1277a982d89SJeremy L. Thompson @ref Backend 1287a982d89SJeremy L. Thompson **/ 129777ff853SJeremy L Thompson int CeedVectorSetData(CeedVector vec, void *data) { 130777ff853SJeremy L Thompson vec->data = data; 131e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1327a982d89SJeremy L. Thompson } 1337a982d89SJeremy L. Thompson 13434359f16Sjeremylt /** 13534359f16Sjeremylt @brief Increment the reference counter for a CeedVector 13634359f16Sjeremylt 137ea61e9acSJeremy L Thompson @param[in,out] vec CeedVector to increment the reference counter 13834359f16Sjeremylt 13934359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 14034359f16Sjeremylt 14134359f16Sjeremylt @ref Backend 14234359f16Sjeremylt **/ 1439560d06aSjeremylt int CeedVectorReference(CeedVector vec) { 14434359f16Sjeremylt vec->ref_count++; 14534359f16Sjeremylt return CEED_ERROR_SUCCESS; 14634359f16Sjeremylt } 14734359f16Sjeremylt 1487a982d89SJeremy L. Thompson /// @} 1497a982d89SJeremy L. Thompson 1507a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1517a982d89SJeremy L. Thompson /// CeedVector Public API 1527a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1537a982d89SJeremy L. Thompson /// @addtogroup CeedVectorUser 1540436c2adSjeremylt /// @{ 1550436c2adSjeremylt 1560436c2adSjeremylt /** 1570436c2adSjeremylt @brief Create a CeedVector of the specified length (does not allocate memory) 1580436c2adSjeremylt 159ea61e9acSJeremy L Thompson @param[in] ceed Ceed object where the CeedVector will be created 160ea61e9acSJeremy L Thompson @param[in] length Length of vector 161ea61e9acSJeremy L Thompson @param[out] vec Address of the variable where the newly created CeedVector will be stored 1620436c2adSjeremylt 1630436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 1640436c2adSjeremylt 1657a982d89SJeremy L. Thompson @ref User 1660436c2adSjeremylt **/ 1671f9221feSJeremy L Thompson int CeedVectorCreate(Ceed ceed, CeedSize length, CeedVector *vec) { 1680436c2adSjeremylt if (!ceed->VectorCreate) { 1690436c2adSjeremylt Ceed delegate; 170*6574a04fSJeremy L Thompson 1712b730f8bSJeremy L Thompson CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Vector")); 172*6574a04fSJeremy L Thompson CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support VectorCreate"); 1732b730f8bSJeremy L Thompson CeedCall(CeedVectorCreate(delegate, length, vec)); 174e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1750436c2adSjeremylt } 1760436c2adSjeremylt 1772b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, vec)); 1780436c2adSjeremylt (*vec)->ceed = ceed; 1792b730f8bSJeremy L Thompson CeedCall(CeedReference(ceed)); 180d1d35e2fSjeremylt (*vec)->ref_count = 1; 1810436c2adSjeremylt (*vec)->length = length; 1820436c2adSjeremylt (*vec)->state = 0; 1832b730f8bSJeremy L Thompson CeedCall(ceed->VectorCreate(length, *vec)); 184e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1850436c2adSjeremylt } 1860436c2adSjeremylt 1870436c2adSjeremylt /** 188ea61e9acSJeremy L Thompson @brief Copy the pointer to a CeedVector. 189ea61e9acSJeremy L Thompson Both pointers should be destroyed with `CeedVectorDestroy()`. 190512bb800SJeremy L Thompson 191512bb800SJeremy 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. 192512bb800SJeremy L Thompson This CeedVector will be destroyed if `vec_copy` is the only reference to this CeedVector. 1939560d06aSjeremylt 194ea61e9acSJeremy L Thompson @param[in] vec CeedVector to copy reference to 195ea61e9acSJeremy L Thompson @param[in,out] vec_copy Variable to store copied reference 1969560d06aSjeremylt 1979560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 1989560d06aSjeremylt 1999560d06aSjeremylt @ref User 2009560d06aSjeremylt **/ 2019560d06aSjeremylt int CeedVectorReferenceCopy(CeedVector vec, CeedVector *vec_copy) { 202393ac2cdSJeremy L Thompson if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) CeedCall(CeedVectorReference(vec)); 2032b730f8bSJeremy L Thompson CeedCall(CeedVectorDestroy(vec_copy)); 2049560d06aSjeremylt *vec_copy = vec; 2059560d06aSjeremylt return CEED_ERROR_SUCCESS; 2069560d06aSjeremylt } 2079560d06aSjeremylt 2089560d06aSjeremylt /** 2095fb68f37SKaren (Ren) Stengel @brief Copy a CeedVector into a different CeedVector. 2105fb68f37SKaren (Ren) Stengel Both pointers should be destroyed with `CeedVectorDestroy()`. 2115fb68f37SKaren (Ren) Stengel Note: If `*vec_copy` is non-NULL, then it is assumed that `*vec_copy` is a pointer to a CeedVector. 2125fb68f37SKaren (Ren) Stengel This CeedVector will be destroyed if `*vec_copy` is the only reference to this CeedVector. 2135fb68f37SKaren (Ren) Stengel 2145fb68f37SKaren (Ren) Stengel @param[in] vec CeedVector to copy 2155fb68f37SKaren (Ren) Stengel @param[in,out] vec_copy Variable to store copied CeedVector to 2165fb68f37SKaren (Ren) Stengel 2175fb68f37SKaren (Ren) Stengel @return An error code: 0 - success, otherwise - failure 2185fb68f37SKaren (Ren) Stengel 2195fb68f37SKaren (Ren) Stengel @ref User 2205fb68f37SKaren (Ren) Stengel **/ 2215fb68f37SKaren (Ren) Stengel int CeedVectorCopy(CeedVector vec, CeedVector vec_copy) { 2225fb68f37SKaren (Ren) Stengel Ceed ceed; 2235fb68f37SKaren (Ren) Stengel CeedMemType mem_type, mem_type_copy; 2245fb68f37SKaren (Ren) Stengel CeedScalar *array; 2255fb68f37SKaren (Ren) Stengel 2265fb68f37SKaren (Ren) Stengel // Get the preferred memory type 2275fb68f37SKaren (Ren) Stengel CeedVectorGetCeed(vec, &ceed); 2285fb68f37SKaren (Ren) Stengel CeedGetPreferredMemType(ceed, &mem_type); 2295fb68f37SKaren (Ren) Stengel 2305fb68f37SKaren (Ren) Stengel // Get the preferred memory type 2315fb68f37SKaren (Ren) Stengel CeedVectorGetCeed(vec_copy, &ceed); 2325fb68f37SKaren (Ren) Stengel CeedGetPreferredMemType(ceed, &mem_type_copy); 2335fb68f37SKaren (Ren) Stengel 2345fb68f37SKaren (Ren) Stengel // Check that both have same memory type 2355fb68f37SKaren (Ren) Stengel if (mem_type != mem_type_copy) mem_type = CEED_MEM_HOST; 2365fb68f37SKaren (Ren) Stengel 2375fb68f37SKaren (Ren) Stengel // Copy the values from vec to vec_copy 2385fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorGetArray(vec, mem_type, &array)); 2395fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorSetArray(vec_copy, mem_type, CEED_COPY_VALUES, array)); 2405fb68f37SKaren (Ren) Stengel 2415fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorRestoreArray(vec, &array)); 2425fb68f37SKaren (Ren) Stengel return CEED_ERROR_SUCCESS; 2435fb68f37SKaren (Ren) Stengel } 2445fb68f37SKaren (Ren) Stengel 2455fb68f37SKaren (Ren) Stengel /** 246ea61e9acSJeremy L Thompson @brief Set the array used by a CeedVector, freeing any previously allocated array if applicable. 247ea61e9acSJeremy L Thompson The backend may copy values to a different memtype, such as during @ref CeedOperatorApply(). 2486a6c615bSJeremy L Thompson See also @ref CeedVectorSyncArray() and @ref CeedVectorTakeArray(). 2490436c2adSjeremylt 250ea61e9acSJeremy L Thompson @param[in,out] vec CeedVector 251ea61e9acSJeremy L Thompson @param[in] mem_type Memory type of the array being passed 252ea61e9acSJeremy L Thompson @param[in] copy_mode Copy mode for the array 253ea61e9acSJeremy L Thompson @param[in] array Array to be used, or NULL with @ref CEED_COPY_VALUES to have the library allocate 2540436c2adSjeremylt 2550436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 2560436c2adSjeremylt 2577a982d89SJeremy L. Thompson @ref User 2580436c2adSjeremylt **/ 2592b730f8bSJeremy L Thompson int CeedVectorSetArray(CeedVector vec, CeedMemType mem_type, CeedCopyMode copy_mode, CeedScalar *array) { 260*6574a04fSJeremy L Thompson CeedCheck(vec->SetArray, vec->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support VectorSetArray"); 261*6574a04fSJeremy L Thompson CeedCheck(vec->state % 2 == 0, vec->ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, the access lock is already in use"); 262*6574a04fSJeremy L Thompson CeedCheck(vec->num_readers == 0, vec->ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, a process has read access"); 2630436c2adSjeremylt 2642b730f8bSJeremy L Thompson CeedCall(vec->SetArray(vec, mem_type, copy_mode, array)); 2650436c2adSjeremylt vec->state += 2; 266e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2670436c2adSjeremylt } 2680436c2adSjeremylt 2690436c2adSjeremylt /** 2700436c2adSjeremylt @brief Set the CeedVector to a constant value 2710436c2adSjeremylt 272ea61e9acSJeremy L Thompson @param[in,out] vec CeedVector 2730436c2adSjeremylt @param[in] value Value to be used 2740436c2adSjeremylt 2750436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 2760436c2adSjeremylt 2777a982d89SJeremy L. Thompson @ref User 2780436c2adSjeremylt **/ 2790436c2adSjeremylt int CeedVectorSetValue(CeedVector vec, CeedScalar value) { 280*6574a04fSJeremy L Thompson CeedCheck(vec->state % 2 == 0, vec->ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, the access lock is already in use"); 281*6574a04fSJeremy L Thompson CeedCheck(vec->num_readers == 0, vec->ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, a process has read access"); 2820436c2adSjeremylt 2830436c2adSjeremylt if (vec->SetValue) { 2842b730f8bSJeremy L Thompson CeedCall(vec->SetValue(vec, value)); 2850436c2adSjeremylt } else { 2860436c2adSjeremylt CeedScalar *array; 2872b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayWrite(vec, CEED_MEM_HOST, &array)); 28892ae7e47SJeremy L Thompson for (CeedInt i = 0; i < vec->length; i++) array[i] = value; 2892b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArray(vec, &array)); 2900436c2adSjeremylt } 2910436c2adSjeremylt vec->state += 2; 292e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2930436c2adSjeremylt } 2940436c2adSjeremylt 2950436c2adSjeremylt /** 296ea61e9acSJeremy L Thompson @brief Sync the CeedVector to a specified memtype. 297ea61e9acSJeremy L Thompson This function is used to force synchronization of arrays set with @ref CeedVectorSetArray(). 298ea61e9acSJeremy L Thompson If the requested memtype is already synchronized, this function results in a no-op. 2990436c2adSjeremylt 300ea61e9acSJeremy L Thompson @param[in,out] vec CeedVector 301ea61e9acSJeremy L Thompson @param[in] mem_type Memtype to be synced 3020436c2adSjeremylt 3030436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 3040436c2adSjeremylt 3057a982d89SJeremy L. Thompson @ref User 3060436c2adSjeremylt **/ 307d1d35e2fSjeremylt int CeedVectorSyncArray(CeedVector vec, CeedMemType mem_type) { 308*6574a04fSJeremy L Thompson CeedCheck(vec->state % 2 == 0, vec->ceed, CEED_ERROR_ACCESS, "Cannot sync CeedVector, the access lock is already in use"); 3090436c2adSjeremylt 3100436c2adSjeremylt if (vec->SyncArray) { 3112b730f8bSJeremy L Thompson CeedCall(vec->SyncArray(vec, mem_type)); 3120436c2adSjeremylt } else { 3130436c2adSjeremylt const CeedScalar *array; 3142b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(vec, mem_type, &array)); 3152b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArrayRead(vec, &array)); 3160436c2adSjeremylt } 317e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3180436c2adSjeremylt } 3190436c2adSjeremylt 3200436c2adSjeremylt /** 321ea61e9acSJeremy 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. 3229c774eddSJeremy L Thompson The caller is responsible for managing and freeing the array. 323ea61e9acSJeremy L Thompson This function will error if @ref CeedVectorSetArray() was not previously called with @ref CEED_USE_POINTER for the corresponding mem_type. 3246a6c615bSJeremy L Thompson 325ea61e9acSJeremy L Thompson @param[in,out] vec CeedVector 326ea61e9acSJeremy L Thompson @param[in] mem_type Memory type on which to take the array. 327ea61e9acSJeremy L Thompson If the backend uses a different memory type, this will perform a copy. 328ea61e9acSJeremy L Thompson @param[out] array Array on memory type mem_type, or NULL if array pointer is not required 3296a6c615bSJeremy L Thompson 3306a6c615bSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 3316a6c615bSJeremy L Thompson 3326a6c615bSJeremy L Thompson @ref User 3336a6c615bSJeremy L Thompson **/ 3342b730f8bSJeremy L Thompson int CeedVectorTakeArray(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 335*6574a04fSJeremy L Thompson CeedCheck(vec->state % 2 == 0, vec->ceed, CEED_ERROR_ACCESS, "Cannot take CeedVector array, the access lock is already in use"); 336*6574a04fSJeremy L Thompson CeedCheck(vec->num_readers == 0, vec->ceed, CEED_ERROR_ACCESS, "Cannot take CeedVector array, a process has read access"); 3376a6c615bSJeremy L Thompson 33850c643e1SJed Brown CeedScalar *temp_array = NULL; 33950c643e1SJed Brown if (vec->length > 0) { 3409c774eddSJeremy L Thompson bool has_borrowed_array_of_type = true; 3412b730f8bSJeremy L Thompson CeedCall(CeedVectorHasBorrowedArrayOfType(vec, mem_type, &has_borrowed_array_of_type)); 342*6574a04fSJeremy L Thompson CeedCheck(has_borrowed_array_of_type, vec->ceed, CEED_ERROR_BACKEND, 343*6574a04fSJeremy L Thompson "CeedVector has no borrowed %s array, must set array with CeedVectorSetArray", CeedMemTypes[mem_type]); 3449c774eddSJeremy L Thompson 3459c774eddSJeremy L Thompson bool has_valid_array = true; 3462b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(vec, &has_valid_array)); 347*6574a04fSJeremy L Thompson CeedCheck(has_valid_array, vec->ceed, CEED_ERROR_BACKEND, 3482b730f8bSJeremy L Thompson "CeedVector has no valid data to take, must set data with CeedVectorSetValue or CeedVectorSetArray"); 3499c774eddSJeremy L Thompson 3502b730f8bSJeremy L Thompson CeedCall(vec->TakeArray(vec, mem_type, &temp_array)); 35150c643e1SJed Brown } 352d1d35e2fSjeremylt if (array) (*array) = temp_array; 353e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3546a6c615bSJeremy L Thompson } 3556a6c615bSJeremy L Thompson 3566a6c615bSJeremy L Thompson /** 357b3cf021fSjeremylt @brief Get read/write access to a CeedVector via the specified memory type. 358b3cf021fSjeremylt Restore access with @ref CeedVectorRestoreArray(). 3590436c2adSjeremylt 360ea61e9acSJeremy L Thompson @param[in,out] vec CeedVector to access 361ea61e9acSJeremy L Thompson @param[in] mem_type Memory type on which to access the array. 362ea61e9acSJeremy L Thompson If the backend uses a different memory type, this will perform a copy. 363d1d35e2fSjeremylt @param[out] array Array on memory type mem_type 3640436c2adSjeremylt 365ea61e9acSJeremy L Thompson @note The CeedVectorGetArray* and CeedVectorRestoreArray* functions provide access to array pointers in the desired memory space. 366ea61e9acSJeremy L Thompson Pairing get/restore allows the Vector to track access, thus knowing if norms or other operations may need to be recomputed. 3670436c2adSjeremylt 3680436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 3690436c2adSjeremylt 3707a982d89SJeremy L. Thompson @ref User 3710436c2adSjeremylt **/ 3722b730f8bSJeremy L Thompson int CeedVectorGetArray(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 373*6574a04fSJeremy L Thompson CeedCheck(vec->GetArray, vec->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetArray"); 374*6574a04fSJeremy L Thompson CeedCheck(vec->state % 2 == 0, vec->ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, the access lock is already in use"); 375*6574a04fSJeremy L Thompson CeedCheck(vec->num_readers == 0, vec->ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, a process has read access"); 3760436c2adSjeremylt 3779c774eddSJeremy L Thompson bool has_valid_array = true; 3782b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(vec, &has_valid_array)); 379*6574a04fSJeremy L Thompson CeedCheck(has_valid_array, vec->ceed, CEED_ERROR_BACKEND, 3802b730f8bSJeremy L Thompson "CeedVector has no valid data to read, must set data with CeedVectorSetValue or CeedVectorSetArray"); 3819c774eddSJeremy L Thompson 3822b730f8bSJeremy L Thompson CeedCall(vec->GetArray(vec, mem_type, array)); 38328bfd0b7SJeremy L Thompson vec->state++; 384e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3850436c2adSjeremylt } 3860436c2adSjeremylt 3870436c2adSjeremylt /** 388b3cf021fSjeremylt @brief Get read-only access to a CeedVector via the specified memory type. 389b3cf021fSjeremylt Restore access with @ref CeedVectorRestoreArrayRead(). 3900436c2adSjeremylt 391ea61e9acSJeremy L Thompson @param[in] vec CeedVector to access 392ea61e9acSJeremy L Thompson @param[in] mem_type Memory type on which to access the array. 393ea61e9acSJeremy L Thompson If the backend uses a different memory type, this will perform a copy (possibly cached). 394d1d35e2fSjeremylt @param[out] array Array on memory type mem_type 3950436c2adSjeremylt 3960436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 3970436c2adSjeremylt 3987a982d89SJeremy L. Thompson @ref User 3990436c2adSjeremylt **/ 4002b730f8bSJeremy L Thompson int CeedVectorGetArrayRead(CeedVector vec, CeedMemType mem_type, const CeedScalar **array) { 401*6574a04fSJeremy L Thompson CeedCheck(vec->GetArrayRead, vec->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetArrayRead"); 402*6574a04fSJeremy L Thompson CeedCheck(vec->state % 2 == 0, vec->ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector read-only array access, the access lock is already in use"); 4030436c2adSjeremylt 40450c643e1SJed Brown if (vec->length > 0) { 4059c774eddSJeremy L Thompson bool has_valid_array = true; 4062b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(vec, &has_valid_array)); 407*6574a04fSJeremy L Thompson CeedCheck(has_valid_array, vec->ceed, CEED_ERROR_BACKEND, 4082b730f8bSJeremy L Thompson "CeedVector has no valid data to read, must set data with CeedVectorSetValue or CeedVectorSetArray"); 4099c774eddSJeremy L Thompson 4102b730f8bSJeremy L Thompson CeedCall(vec->GetArrayRead(vec, mem_type, array)); 41150c643e1SJed Brown } else { 41250c643e1SJed Brown *array = NULL; 41350c643e1SJed Brown } 414d1d35e2fSjeremylt vec->num_readers++; 415e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4160436c2adSjeremylt } 4170436c2adSjeremylt 4180436c2adSjeremylt /** 4199c774eddSJeremy L Thompson @brief Get write access to a CeedVector via the specified memory type. 420ea61e9acSJeremy L Thompson Restore access with @ref CeedVectorRestoreArray(). 421ea61e9acSJeremy L Thompson All old values should be assumed to be invalid. 4229c774eddSJeremy L Thompson 423ea61e9acSJeremy L Thompson @param[in,out] vec CeedVector to access 424ea61e9acSJeremy L Thompson @param[in] mem_type Memory type on which to access the array. 4259c774eddSJeremy L Thompson @param[out] array Array on memory type mem_type 4269c774eddSJeremy L Thompson 4279c774eddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 4289c774eddSJeremy L Thompson 4299c774eddSJeremy L Thompson @ref User 4309c774eddSJeremy L Thompson **/ 4312b730f8bSJeremy L Thompson int CeedVectorGetArrayWrite(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 432*6574a04fSJeremy L Thompson CeedCheck(vec->GetArrayWrite, vec->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetArrayWrite"); 433*6574a04fSJeremy L Thompson CeedCheck(vec->state % 2 == 0, vec->ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, the access lock is already in use"); 434*6574a04fSJeremy L Thompson CeedCheck(vec->num_readers == 0, vec->ceed, CEED_ERROR_ACCESS, "Cannot grant CeedVector array access, a process has read access"); 4359c774eddSJeremy L Thompson 4362b730f8bSJeremy L Thompson CeedCall(vec->GetArrayWrite(vec, mem_type, array)); 43728bfd0b7SJeremy L Thompson vec->state++; 4389c774eddSJeremy L Thompson return CEED_ERROR_SUCCESS; 4399c774eddSJeremy L Thompson } 4409c774eddSJeremy L Thompson 4419c774eddSJeremy L Thompson /** 442ea61e9acSJeremy L Thompson @brief Restore an array obtained using @ref CeedVectorGetArray() or @ref CeedVectorGetArrayWrite() 4430436c2adSjeremylt 444ea61e9acSJeremy L Thompson @param[in,out] vec CeedVector to restore 445ea61e9acSJeremy L Thompson @param[in,out] array Array of vector data 4460436c2adSjeremylt 4470436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 4480436c2adSjeremylt 4497a982d89SJeremy L. Thompson @ref User 4500436c2adSjeremylt **/ 4510436c2adSjeremylt int CeedVectorRestoreArray(CeedVector vec, CeedScalar **array) { 452*6574a04fSJeremy L Thompson CeedCheck(vec->state % 2 == 1, vec->ceed, CEED_ERROR_ACCESS, "Cannot restore CeedVector array access, access was not granted"); 4532b730f8bSJeremy L Thompson if (vec->RestoreArray) CeedCall(vec->RestoreArray(vec)); 4540436c2adSjeremylt *array = NULL; 45528bfd0b7SJeremy L Thompson vec->state++; 456e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4570436c2adSjeremylt } 4580436c2adSjeremylt 4590436c2adSjeremylt /** 460b3cf021fSjeremylt @brief Restore an array obtained using @ref CeedVectorGetArrayRead() 4610436c2adSjeremylt 462ea61e9acSJeremy L Thompson @param[in] vec CeedVector to restore 463ea61e9acSJeremy L Thompson @param[in,out] array Array of vector data 4640436c2adSjeremylt 4650436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 4660436c2adSjeremylt 4677a982d89SJeremy L. Thompson @ref User 4680436c2adSjeremylt **/ 4690436c2adSjeremylt int CeedVectorRestoreArrayRead(CeedVector vec, const CeedScalar **array) { 470*6574a04fSJeremy L Thompson CeedCheck(vec->num_readers > 0, vec->ceed, CEED_ERROR_ACCESS, "Cannot restore CeedVector array read access, access was not granted"); 4719c774eddSJeremy L Thompson 47275a19770SJeremy L Thompson vec->num_readers--; 4732b730f8bSJeremy L Thompson if (vec->num_readers == 0 && vec->RestoreArrayRead) CeedCall(vec->RestoreArrayRead(vec)); 4740436c2adSjeremylt *array = NULL; 47575a19770SJeremy L Thompson 476e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4770436c2adSjeremylt } 4780436c2adSjeremylt 4790436c2adSjeremylt /** 480171f8ca9Sjeremylt @brief Get the norm of a CeedVector. 481171f8ca9Sjeremylt 482ea61e9acSJeremy L Thompson Note: This operation is local to the CeedVector. 483ea61e9acSJeremy 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 484ea61e9acSJeremy L Thompson duplicated or hanging nodes. 485547d9b97Sjeremylt 486ea61e9acSJeremy L Thompson @param[in] vec CeedVector to retrieve maximum value 487ea61e9acSJeremy L Thompson @param[in] norm_type Norm type @ref CEED_NORM_1, @ref CEED_NORM_2, or @ref CEED_NORM_MAX 488547d9b97Sjeremylt @param[out] norm Variable to store norm value 489547d9b97Sjeremylt 490547d9b97Sjeremylt @return An error code: 0 - success, otherwise - failure 491547d9b97Sjeremylt 4927a982d89SJeremy L. Thompson @ref User 493547d9b97Sjeremylt **/ 494d1d35e2fSjeremylt int CeedVectorNorm(CeedVector vec, CeedNormType norm_type, CeedScalar *norm) { 4959c774eddSJeremy L Thompson bool has_valid_array = true; 4962b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(vec, &has_valid_array)); 497*6574a04fSJeremy L Thompson CeedCheck(has_valid_array, vec->ceed, CEED_ERROR_BACKEND, 4982b730f8bSJeremy L Thompson "CeedVector has no valid data to compute norm, must set data with CeedVectorSetValue or CeedVectorSetArray"); 4999c774eddSJeremy L Thompson 500547d9b97Sjeremylt // Backend impl for GPU, if added 501547d9b97Sjeremylt if (vec->Norm) { 5022b730f8bSJeremy L Thompson CeedCall(vec->Norm(vec, norm_type, norm)); 503e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 504547d9b97Sjeremylt } 505547d9b97Sjeremylt 506547d9b97Sjeremylt const CeedScalar *array; 5072b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(vec, CEED_MEM_HOST, &array)); 508547d9b97Sjeremylt 509547d9b97Sjeremylt *norm = 0.; 510d1d35e2fSjeremylt switch (norm_type) { 511547d9b97Sjeremylt case CEED_NORM_1: 51292ae7e47SJeremy L Thompson for (CeedInt i = 0; i < vec->length; i++) { 513547d9b97Sjeremylt *norm += fabs(array[i]); 514547d9b97Sjeremylt } 515547d9b97Sjeremylt break; 516547d9b97Sjeremylt case CEED_NORM_2: 51792ae7e47SJeremy L Thompson for (CeedInt i = 0; i < vec->length; i++) { 518547d9b97Sjeremylt *norm += fabs(array[i]) * fabs(array[i]); 519547d9b97Sjeremylt } 520547d9b97Sjeremylt break; 521547d9b97Sjeremylt case CEED_NORM_MAX: 52292ae7e47SJeremy L Thompson for (CeedInt i = 0; i < vec->length; i++) { 523d1d35e2fSjeremylt const CeedScalar abs_v_i = fabs(array[i]); 524d1d35e2fSjeremylt *norm = *norm > abs_v_i ? *norm : abs_v_i; 525547d9b97Sjeremylt } 526547d9b97Sjeremylt } 5272b730f8bSJeremy L Thompson if (norm_type == CEED_NORM_2) *norm = sqrt(*norm); 528547d9b97Sjeremylt 5292b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArrayRead(vec, &array)); 530e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 531547d9b97Sjeremylt } 532547d9b97Sjeremylt 533547d9b97Sjeremylt /** 534e0dd3b27Sjeremylt @brief Compute x = alpha x 535e0dd3b27Sjeremylt 53696b902e2Sjeremylt @param[in,out] x vector for scaling 53796b902e2Sjeremylt @param[in] alpha scaling factor 538e0dd3b27Sjeremylt 539e0dd3b27Sjeremylt @return An error code: 0 - success, otherwise - failure 540e0dd3b27Sjeremylt 541e0dd3b27Sjeremylt @ref User 542e0dd3b27Sjeremylt **/ 543e0dd3b27Sjeremylt int CeedVectorScale(CeedVector x, CeedScalar alpha) { 54473380422SJeremy L Thompson CeedScalar *x_array = NULL; 5451f9221feSJeremy L Thompson CeedSize n_x; 546e0dd3b27Sjeremylt 5479c774eddSJeremy L Thompson bool has_valid_array = true; 5482b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(x, &has_valid_array)); 549*6574a04fSJeremy L Thompson CeedCheck(has_valid_array, x->ceed, CEED_ERROR_BACKEND, 5502b730f8bSJeremy L Thompson "CeedVector has no valid data to scale, must set data with CeedVectorSetValue or CeedVectorSetArray"); 5519c774eddSJeremy L Thompson 5522b730f8bSJeremy L Thompson CeedCall(CeedVectorGetLength(x, &n_x)); 553e0dd3b27Sjeremylt 554e0dd3b27Sjeremylt // Backend implementation 5552b730f8bSJeremy L Thompson if (x->Scale) return x->Scale(x, alpha); 556e0dd3b27Sjeremylt 557e0dd3b27Sjeremylt // Default implementation 5582b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayWrite(x, CEED_MEM_HOST, &x_array)); 5592b730f8bSJeremy L Thompson for (CeedInt i = 0; i < n_x; i++) x_array[i] *= alpha; 5602b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArray(x, &x_array)); 561e0dd3b27Sjeremylt 562e0dd3b27Sjeremylt return CEED_ERROR_SUCCESS; 563e0dd3b27Sjeremylt } 564e0dd3b27Sjeremylt 565e0dd3b27Sjeremylt /** 5660f7fd0f8Sjeremylt @brief Compute y = alpha x + y 5670f7fd0f8Sjeremylt 56896b902e2Sjeremylt @param[in,out] y target vector for sum 56996b902e2Sjeremylt @param[in] alpha scaling factor 57096b902e2Sjeremylt @param[in] x second vector, must be different than y 5710f7fd0f8Sjeremylt 5720f7fd0f8Sjeremylt @return An error code: 0 - success, otherwise - failure 5730f7fd0f8Sjeremylt 5740f7fd0f8Sjeremylt @ref User 5750f7fd0f8Sjeremylt **/ 5760f7fd0f8Sjeremylt int CeedVectorAXPY(CeedVector y, CeedScalar alpha, CeedVector x) { 57773380422SJeremy L Thompson CeedScalar *y_array = NULL; 57873380422SJeremy L Thompson CeedScalar const *x_array = NULL; 5791f9221feSJeremy L Thompson CeedSize n_x, n_y; 5800f7fd0f8Sjeremylt 5812b730f8bSJeremy L Thompson CeedCall(CeedVectorGetLength(y, &n_y)); 5822b730f8bSJeremy L Thompson CeedCall(CeedVectorGetLength(x, &n_x)); 583*6574a04fSJeremy L Thompson CeedCheck(n_x == n_y, y->ceed, CEED_ERROR_UNSUPPORTED, "Cannot add vector of different lengths"); 584*6574a04fSJeremy L Thompson CeedCheck(x != y, y->ceed, CEED_ERROR_UNSUPPORTED, "Cannot use same vector for x and y in CeedVectorAXPY"); 5850f7fd0f8Sjeremylt 5869c774eddSJeremy L Thompson bool has_valid_array_x = true, has_valid_array_y = true; 5872b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(x, &has_valid_array_x)); 588*6574a04fSJeremy L Thompson CeedCheck(has_valid_array_x, x->ceed, CEED_ERROR_BACKEND, 589*6574a04fSJeremy L Thompson "CeedVector x has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 5902b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(y, &has_valid_array_y)); 591*6574a04fSJeremy L Thompson CeedCheck(has_valid_array_y, y->ceed, CEED_ERROR_BACKEND, 592*6574a04fSJeremy L Thompson "CeedVector y has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 5939c774eddSJeremy L Thompson 5942d04630dSjeremylt Ceed ceed_parent_x, ceed_parent_y; 5952b730f8bSJeremy L Thompson CeedCall(CeedGetParent(x->ceed, &ceed_parent_x)); 5962b730f8bSJeremy L Thompson CeedCall(CeedGetParent(y->ceed, &ceed_parent_y)); 597*6574a04fSJeremy L Thompson CeedCheck(ceed_parent_x == ceed_parent_y, y->ceed, CEED_ERROR_INCOMPATIBLE, "Vectors x and y must be created by the same Ceed context"); 5982d04630dSjeremylt 5990f7fd0f8Sjeremylt // Backend implementation 600eaf62fffSJeremy L Thompson if (y->AXPY) { 6012b730f8bSJeremy L Thompson CeedCall(y->AXPY(y, alpha, x)); 602eaf62fffSJeremy L Thompson return CEED_ERROR_SUCCESS; 603eaf62fffSJeremy L Thompson } 6040f7fd0f8Sjeremylt 6050f7fd0f8Sjeremylt // Default implementation 6062b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayWrite(y, CEED_MEM_HOST, &y_array)); 6072b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(x, CEED_MEM_HOST, &x_array)); 6080f7fd0f8Sjeremylt 6092b730f8bSJeremy L Thompson assert(x_array); 6102b730f8bSJeremy L Thompson assert(y_array); 61173380422SJeremy L Thompson 6122b730f8bSJeremy L Thompson for (CeedInt i = 0; i < n_y; i++) y_array[i] += alpha * x_array[i]; 6130f7fd0f8Sjeremylt 6142b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArray(y, &y_array)); 6152b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArrayRead(x, &x_array)); 6160f7fd0f8Sjeremylt 6170f7fd0f8Sjeremylt return CEED_ERROR_SUCCESS; 6180f7fd0f8Sjeremylt } 6190f7fd0f8Sjeremylt 6200f7fd0f8Sjeremylt /** 6215fb68f37SKaren (Ren) Stengel @brief Compute y = alpha x + beta y 6225fb68f37SKaren (Ren) Stengel 6235fb68f37SKaren (Ren) Stengel @param[in,out] y target vector for sum 6245fb68f37SKaren (Ren) Stengel @param[in] alpha first scaling factor 6255fb68f37SKaren (Ren) Stengel @param[in] beta second scaling factor 6265fb68f37SKaren (Ren) Stengel @param[in] x second vector, must be different than y 6275fb68f37SKaren (Ren) Stengel 6285fb68f37SKaren (Ren) Stengel @return An error code: 0 - success, otherwise - failure 6295fb68f37SKaren (Ren) Stengel 6305fb68f37SKaren (Ren) Stengel @ref User 6315fb68f37SKaren (Ren) Stengel **/ 6325fb68f37SKaren (Ren) Stengel int CeedVectorAXPBY(CeedVector y, CeedScalar alpha, CeedScalar beta, CeedVector x) { 6335fb68f37SKaren (Ren) Stengel CeedScalar *y_array = NULL; 6345fb68f37SKaren (Ren) Stengel CeedScalar const *x_array = NULL; 6355fb68f37SKaren (Ren) Stengel CeedSize n_x, n_y; 6365fb68f37SKaren (Ren) Stengel 6375fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorGetLength(y, &n_y)); 6385fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorGetLength(x, &n_x)); 639*6574a04fSJeremy L Thompson CeedCheck(n_x == n_y, y->ceed, CEED_ERROR_UNSUPPORTED, "Cannot add vector of different lengths"); 640*6574a04fSJeremy L Thompson CeedCheck(x != y, y->ceed, CEED_ERROR_UNSUPPORTED, "Cannot use same vector for x and y in CeedVectorAXPBY"); 6415fb68f37SKaren (Ren) Stengel 6425fb68f37SKaren (Ren) Stengel bool has_valid_array_x = true, has_valid_array_y = true; 6435fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorHasValidArray(x, &has_valid_array_x)); 644*6574a04fSJeremy L Thompson CeedCheck(has_valid_array_x, x->ceed, CEED_ERROR_BACKEND, 645*6574a04fSJeremy L Thompson "CeedVector x has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 6465fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorHasValidArray(y, &has_valid_array_y)); 647*6574a04fSJeremy L Thompson CeedCheck(has_valid_array_y, y->ceed, CEED_ERROR_BACKEND, 648*6574a04fSJeremy L Thompson "CeedVector y has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 6495fb68f37SKaren (Ren) Stengel 6505fb68f37SKaren (Ren) Stengel Ceed ceed_parent_x, ceed_parent_y; 6515fb68f37SKaren (Ren) Stengel CeedCall(CeedGetParent(x->ceed, &ceed_parent_x)); 6525fb68f37SKaren (Ren) Stengel CeedCall(CeedGetParent(y->ceed, &ceed_parent_y)); 653*6574a04fSJeremy L Thompson CeedCheck(ceed_parent_x == ceed_parent_y, y->ceed, CEED_ERROR_INCOMPATIBLE, "Vectors x and y must be created by the same Ceed context"); 6545fb68f37SKaren (Ren) Stengel 6555fb68f37SKaren (Ren) Stengel // Backend implementation 6565fb68f37SKaren (Ren) Stengel if (y->AXPBY) { 6575fb68f37SKaren (Ren) Stengel CeedCall(y->AXPBY(y, alpha, beta, x)); 6585fb68f37SKaren (Ren) Stengel return CEED_ERROR_SUCCESS; 6595fb68f37SKaren (Ren) Stengel } 6605fb68f37SKaren (Ren) Stengel 6615fb68f37SKaren (Ren) Stengel // Default implementation 6625fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorGetArray(y, CEED_MEM_HOST, &y_array)); 6635fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorGetArrayRead(x, CEED_MEM_HOST, &x_array)); 6645fb68f37SKaren (Ren) Stengel 6655fb68f37SKaren (Ren) Stengel assert(x_array); 6665fb68f37SKaren (Ren) Stengel assert(y_array); 6675fb68f37SKaren (Ren) Stengel 6685fb68f37SKaren (Ren) Stengel for (CeedInt i = 0; i < n_y; i++) y_array[i] += alpha * x_array[i] + beta * y_array[i]; 6695fb68f37SKaren (Ren) Stengel 6705fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorRestoreArray(y, &y_array)); 6715fb68f37SKaren (Ren) Stengel CeedCall(CeedVectorRestoreArrayRead(x, &x_array)); 6725fb68f37SKaren (Ren) Stengel 6735fb68f37SKaren (Ren) Stengel return CEED_ERROR_SUCCESS; 6745fb68f37SKaren (Ren) Stengel } 6755fb68f37SKaren (Ren) Stengel 6765fb68f37SKaren (Ren) Stengel /** 677ea61e9acSJeremy L Thompson @brief Compute the pointwise multiplication w = x .* y. 678ea61e9acSJeremy L Thompson Any subset of x, y, and w may be the same vector. 6790f7fd0f8Sjeremylt 68096b902e2Sjeremylt @param[out] w target vector for the product 68196b902e2Sjeremylt @param[in] x first vector for product 68296b902e2Sjeremylt @param[in] y second vector for the product 6830f7fd0f8Sjeremylt 6840f7fd0f8Sjeremylt @return An error code: 0 - success, otherwise - failure 6850f7fd0f8Sjeremylt 6860f7fd0f8Sjeremylt @ref User 6870f7fd0f8Sjeremylt **/ 6880f7fd0f8Sjeremylt int CeedVectorPointwiseMult(CeedVector w, CeedVector x, CeedVector y) { 68973380422SJeremy L Thompson CeedScalar *w_array = NULL; 69073380422SJeremy L Thompson CeedScalar const *x_array = NULL, *y_array = NULL; 6911f9221feSJeremy L Thompson CeedSize n_w, n_x, n_y; 6920f7fd0f8Sjeremylt 6932b730f8bSJeremy L Thompson CeedCall(CeedVectorGetLength(w, &n_w)); 6942b730f8bSJeremy L Thompson CeedCall(CeedVectorGetLength(x, &n_x)); 6952b730f8bSJeremy L Thompson CeedCall(CeedVectorGetLength(y, &n_y)); 696*6574a04fSJeremy L Thompson CeedCheck(n_w == n_x && n_w == n_y, w->ceed, CEED_ERROR_UNSUPPORTED, "Cannot multiply vectors of different lengths"); 6970f7fd0f8Sjeremylt 6982d04630dSjeremylt Ceed ceed_parent_w, ceed_parent_x, ceed_parent_y; 6992b730f8bSJeremy L Thompson CeedCall(CeedGetParent(w->ceed, &ceed_parent_w)); 7002b730f8bSJeremy L Thompson CeedCall(CeedGetParent(x->ceed, &ceed_parent_x)); 7012b730f8bSJeremy L Thompson CeedCall(CeedGetParent(y->ceed, &ceed_parent_y)); 702*6574a04fSJeremy L Thompson CeedCheck(ceed_parent_w == ceed_parent_x && ceed_parent_w == ceed_parent_y, w->ceed, CEED_ERROR_INCOMPATIBLE, 703*6574a04fSJeremy L Thompson "Vectors w, x, and y must be created by the same Ceed context"); 7042d04630dSjeremylt 7059c774eddSJeremy L Thompson bool has_valid_array_x = true, has_valid_array_y = true; 7062b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(x, &has_valid_array_x)); 707*6574a04fSJeremy L Thompson CeedCheck(has_valid_array_x, x->ceed, CEED_ERROR_BACKEND, 708*6574a04fSJeremy L Thompson "CeedVector x has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 7092b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(y, &has_valid_array_y)); 710*6574a04fSJeremy L Thompson CeedCheck(has_valid_array_y, y->ceed, CEED_ERROR_BACKEND, 711*6574a04fSJeremy L Thompson "CeedVector y has no valid data, must set data with CeedVectorSetValue or CeedVectorSetArray"); 7129c774eddSJeremy L Thompson 7130f7fd0f8Sjeremylt // Backend implementation 714eaf62fffSJeremy L Thompson if (w->PointwiseMult) { 7152b730f8bSJeremy L Thompson CeedCall(w->PointwiseMult(w, x, y)); 716eaf62fffSJeremy L Thompson return CEED_ERROR_SUCCESS; 717eaf62fffSJeremy L Thompson } 7180f7fd0f8Sjeremylt 7190f7fd0f8Sjeremylt // Default implementation 7200f7fd0f8Sjeremylt if (x != w) { 7212b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(x, CEED_MEM_HOST, &x_array)); 7220f7fd0f8Sjeremylt } else { 723c6d796c6SJeremy L Thompson CeedCall(CeedVectorGetArray(w, CEED_MEM_HOST, &w_array)); 7240f7fd0f8Sjeremylt x_array = w_array; 7250f7fd0f8Sjeremylt } 7260f7fd0f8Sjeremylt if (y != w && y != x) { 7272b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(y, CEED_MEM_HOST, &y_array)); 728c6d796c6SJeremy L Thompson } else if (y == x) { 7290f7fd0f8Sjeremylt y_array = x_array; 730c6d796c6SJeremy L Thompson } else { 731c6d796c6SJeremy L Thompson CeedCall(CeedVectorGetArray(w, CEED_MEM_HOST, &w_array)); 732c6d796c6SJeremy L Thompson y_array = w_array; 7330f7fd0f8Sjeremylt } 734c6d796c6SJeremy L Thompson if (!w_array) CeedCall(CeedVectorGetArrayWrite(w, CEED_MEM_HOST, &w_array)); 7350f7fd0f8Sjeremylt 7362b730f8bSJeremy L Thompson assert(w_array); 7372b730f8bSJeremy L Thompson assert(x_array); 7382b730f8bSJeremy L Thompson assert(y_array); 73973380422SJeremy L Thompson 7402b730f8bSJeremy L Thompson for (CeedInt i = 0; i < n_w; i++) w_array[i] = x_array[i] * y_array[i]; 7410f7fd0f8Sjeremylt 7422b730f8bSJeremy L Thompson if (y != w && y != x) CeedCall(CeedVectorRestoreArrayRead(y, &y_array)); 7432b730f8bSJeremy L Thompson if (x != w) CeedCall(CeedVectorRestoreArrayRead(x, &x_array)); 7442b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArray(w, &w_array)); 7450f7fd0f8Sjeremylt return CEED_ERROR_SUCCESS; 7460f7fd0f8Sjeremylt } 7470f7fd0f8Sjeremylt 7480f7fd0f8Sjeremylt /** 749d99fa3c5SJeremy L Thompson @brief Take the reciprocal of a CeedVector. 750d99fa3c5SJeremy L Thompson 751ea61e9acSJeremy L Thompson @param[in,out] vec CeedVector to take reciprocal 752d99fa3c5SJeremy L Thompson 753d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 754d99fa3c5SJeremy L Thompson 755d99fa3c5SJeremy L Thompson @ref User 756d99fa3c5SJeremy L Thompson **/ 757d99fa3c5SJeremy L Thompson int CeedVectorReciprocal(CeedVector vec) { 7589c774eddSJeremy L Thompson bool has_valid_array = true; 7592b730f8bSJeremy L Thompson CeedCall(CeedVectorHasValidArray(vec, &has_valid_array)); 7602b730f8bSJeremy L Thompson 761*6574a04fSJeremy L Thompson CeedCheck(has_valid_array, vec->ceed, CEED_ERROR_BACKEND, 7622b730f8bSJeremy L Thompson "CeedVector has no valid data to compute reciprocal, must set data with CeedVectorSetValue or CeedVectorSetArray"); 7639c774eddSJeremy L Thompson 764d99fa3c5SJeremy L Thompson // Check if vector data set 765*6574a04fSJeremy L Thompson CeedCheck(vec->state > 0, vec->ceed, CEED_ERROR_INCOMPLETE, "CeedVector must have data set to take reciprocal"); 766d99fa3c5SJeremy L Thompson 767d99fa3c5SJeremy L Thompson // Backend impl for GPU, if added 768d99fa3c5SJeremy L Thompson if (vec->Reciprocal) { 7692b730f8bSJeremy L Thompson CeedCall(vec->Reciprocal(vec)); 770e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 771d99fa3c5SJeremy L Thompson } 772d99fa3c5SJeremy L Thompson 7731f9221feSJeremy L Thompson CeedSize len; 7742b730f8bSJeremy L Thompson CeedCall(CeedVectorGetLength(vec, &len)); 775d99fa3c5SJeremy L Thompson CeedScalar *array; 7762b730f8bSJeremy L Thompson CeedCall(CeedVectorGetArrayWrite(vec, CEED_MEM_HOST, &array)); 7772b730f8bSJeremy L Thompson for (CeedInt i = 0; i < len; i++) { 7782b730f8bSJeremy L Thompson if (fabs(array[i]) > CEED_EPSILON) array[i] = 1. / array[i]; 7792b730f8bSJeremy L Thompson } 780d99fa3c5SJeremy L Thompson 7812b730f8bSJeremy L Thompson CeedCall(CeedVectorRestoreArray(vec, &array)); 782e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 783d99fa3c5SJeremy L Thompson } 784d99fa3c5SJeremy L Thompson 785d99fa3c5SJeremy L Thompson /** 7867a982d89SJeremy L. Thompson @brief View a CeedVector 7870436c2adSjeremylt 788acb2c48cSJeremy L Thompson Note: It is safe to use any unsigned values for `start` or `stop` and any nonzero integer for `step`. 789acb2c48cSJeremy L Thompson Any portion of the provided range that is outside the range of valid indices for the CeedVector will be ignored. 790acb2c48cSJeremy L Thompson 791acb2c48cSJeremy L Thompson @param[in] vec CeedVector to view 792acb2c48cSJeremy L Thompson @param[in] start Index of first CeedVector entry to view 793acb2c48cSJeremy L Thompson @param[in] stop Index of last CeedVector entry to view 794acb2c48cSJeremy L Thompson @param[in] step Step between CeedVector entries to view 795acb2c48cSJeremy L Thompson @param[in] fp_fmt Printing format 796acb2c48cSJeremy L Thompson @param[in] stream Filestream to write to 797acb2c48cSJeremy L Thompson 798acb2c48cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 799acb2c48cSJeremy L Thompson 800acb2c48cSJeremy L Thompson @ref User 801acb2c48cSJeremy L Thompson **/ 802acb2c48cSJeremy L Thompson int CeedVectorViewRange(CeedVector vec, CeedSize start, CeedSize stop, CeedInt step, const char *fp_fmt, FILE *stream) { 803acb2c48cSJeremy L Thompson const CeedScalar *x; 804acb2c48cSJeremy L Thompson char fmt[1024]; 805acb2c48cSJeremy L Thompson 806*6574a04fSJeremy L Thompson CeedCheck(step != 0, vec->ceed, CEED_ERROR_MINOR, "View range 'step' must be nonzero"); 807acb2c48cSJeremy L Thompson 808acb2c48cSJeremy L Thompson fprintf(stream, "CeedVector length %ld\n", (long)vec->length); 809acb2c48cSJeremy L Thompson if (start != 0 || stop != vec->length || step != 1) { 810acb2c48cSJeremy L Thompson fprintf(stream, " start: %ld\n stop: %ld\n step: %" CeedInt_FMT "\n", (long)start, (long)stop, step); 811acb2c48cSJeremy L Thompson } 812acb2c48cSJeremy L Thompson if (start > vec->length) start = vec->length; 813acb2c48cSJeremy L Thompson if (stop > vec->length) stop = vec->length; 814acb2c48cSJeremy L Thompson 815acb2c48cSJeremy L Thompson snprintf(fmt, sizeof fmt, " %s\n", fp_fmt ? fp_fmt : "%g"); 816acb2c48cSJeremy L Thompson CeedCall(CeedVectorGetArrayRead(vec, CEED_MEM_HOST, &x)); 817acb2c48cSJeremy L Thompson for (CeedInt i = start; step > 0 ? (i < stop) : (i > stop); i += step) fprintf(stream, fmt, x[i]); 818acb2c48cSJeremy L Thompson CeedCall(CeedVectorRestoreArrayRead(vec, &x)); 819acb2c48cSJeremy L Thompson if (stop != vec->length) fprintf(stream, " ...\n"); 820acb2c48cSJeremy L Thompson 821acb2c48cSJeremy L Thompson return CEED_ERROR_SUCCESS; 822acb2c48cSJeremy L Thompson } 823acb2c48cSJeremy L Thompson 824acb2c48cSJeremy L Thompson /** 825acb2c48cSJeremy L Thompson @brief View a CeedVector 826acb2c48cSJeremy L Thompson 8270a0da059Sjeremylt @param[in] vec CeedVector to view 828d1d35e2fSjeremylt @param[in] fp_fmt Printing format 8290a0da059Sjeremylt @param[in] stream Filestream to write to 8300a0da059Sjeremylt 8310436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 8320436c2adSjeremylt 8337a982d89SJeremy L. Thompson @ref User 8340436c2adSjeremylt **/ 835d1d35e2fSjeremylt int CeedVectorView(CeedVector vec, const char *fp_fmt, FILE *stream) { 836acb2c48cSJeremy L Thompson CeedCall(CeedVectorViewRange(vec, 0, vec->length, 1, fp_fmt, stream)); 837e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8380436c2adSjeremylt } 8390436c2adSjeremylt 8400436c2adSjeremylt /** 841b7c9bbdaSJeremy L Thompson @brief Get the Ceed associated with a CeedVector 842b7c9bbdaSJeremy L Thompson 843ea61e9acSJeremy L Thompson @param[in] vec CeedVector to retrieve state 844b7c9bbdaSJeremy L Thompson @param[out] ceed Variable to store ceed 845b7c9bbdaSJeremy L Thompson 846b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 847b7c9bbdaSJeremy L Thompson 848b7c9bbdaSJeremy L Thompson @ref Advanced 849b7c9bbdaSJeremy L Thompson **/ 850b7c9bbdaSJeremy L Thompson int CeedVectorGetCeed(CeedVector vec, Ceed *ceed) { 851b7c9bbdaSJeremy L Thompson *ceed = vec->ceed; 852b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 853b7c9bbdaSJeremy L Thompson } 854b7c9bbdaSJeremy L Thompson 855b7c9bbdaSJeremy L Thompson /** 8567a982d89SJeremy L. Thompson @brief Get the length of a CeedVector 8570436c2adSjeremylt 858ea61e9acSJeremy L Thompson @param[in] vec CeedVector to retrieve length 8597a982d89SJeremy L. Thompson @param[out] length Variable to store length 8600436c2adSjeremylt 8610436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 8620436c2adSjeremylt 8637a982d89SJeremy L. Thompson @ref User 8640436c2adSjeremylt **/ 8651f9221feSJeremy L Thompson int CeedVectorGetLength(CeedVector vec, CeedSize *length) { 8667a982d89SJeremy L. Thompson *length = vec->length; 867e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8680436c2adSjeremylt } 8690436c2adSjeremylt 8700436c2adSjeremylt /** 8710436c2adSjeremylt @brief Destroy a CeedVector 8720436c2adSjeremylt 873ea61e9acSJeremy L Thompson @param[in,out] vec CeedVector to destroy 8740436c2adSjeremylt 8750436c2adSjeremylt @return An error code: 0 - success, otherwise - failure 8760436c2adSjeremylt 8777a982d89SJeremy L. Thompson @ref User 8780436c2adSjeremylt **/ 8790436c2adSjeremylt int CeedVectorDestroy(CeedVector *vec) { 8807425e127SJeremy L Thompson if (!*vec || *vec == CEED_VECTOR_ACTIVE || *vec == CEED_VECTOR_NONE || --(*vec)->ref_count > 0) { 881ad6481ceSJeremy L Thompson *vec = NULL; 882ad6481ceSJeremy L Thompson return CEED_ERROR_SUCCESS; 883ad6481ceSJeremy L Thompson } 884*6574a04fSJeremy L Thompson CeedCheck((*vec)->state % 2 == 0, (*vec)->ceed, CEED_ERROR_ACCESS, "Cannot destroy CeedVector, the writable access lock is in use"); 885*6574a04fSJeremy L Thompson CeedCheck((*vec)->num_readers == 0, (*vec)->ceed, CEED_ERROR_ACCESS, "Cannot destroy CeedVector, a process has read access"); 8860436c2adSjeremylt 8872b730f8bSJeremy L Thompson if ((*vec)->Destroy) CeedCall((*vec)->Destroy(*vec)); 8882b730f8bSJeremy L Thompson 8892b730f8bSJeremy L Thompson CeedCall(CeedDestroy(&(*vec)->ceed)); 8902b730f8bSJeremy L Thompson CeedCall(CeedFree(vec)); 891e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8920436c2adSjeremylt } 8930436c2adSjeremylt 8940436c2adSjeremylt /// @} 895