xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-vector.c (revision b7c9bbdafc9b91976b65f80ebb2c5357c2efd8bc)
10436c2adSjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
20436c2adSjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
30436c2adSjeremylt // reserved. See files LICENSE and NOTICE for details.
40436c2adSjeremylt //
50436c2adSjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software
60436c2adSjeremylt // libraries and APIs for efficient high-order finite element and spectral
70436c2adSjeremylt // element discretizations for exascale applications. For more information and
80436c2adSjeremylt // source code availability see http://github.com/ceed.
90436c2adSjeremylt //
100436c2adSjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
110436c2adSjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office
120436c2adSjeremylt // of Science and the National Nuclear Security Administration) responsible for
130436c2adSjeremylt // the planning and preparation of a capable exascale ecosystem, including
140436c2adSjeremylt // software, applications, hardware, advanced system engineering and early
150436c2adSjeremylt // testbed platforms, in support of the nation's exascale computing imperative.
160436c2adSjeremylt 
17ec3da8bcSJed Brown #include <ceed/ceed.h>
18ec3da8bcSJed Brown #include <ceed/backend.h>
193d576824SJeremy L Thompson #include <ceed-impl.h>
20547d9b97Sjeremylt #include <math.h>
213d576824SJeremy L Thompson #include <stdint.h>
223d576824SJeremy L Thompson #include <stdio.h>
230436c2adSjeremylt 
247a982d89SJeremy L. Thompson /// @file
257a982d89SJeremy L. Thompson /// Implementation of public CeedVector interfaces
267a982d89SJeremy L. Thompson 
270436c2adSjeremylt /// @cond DOXYGEN_SKIP
280436c2adSjeremylt static struct CeedVector_private ceed_vector_active;
290436c2adSjeremylt static struct CeedVector_private ceed_vector_none;
300436c2adSjeremylt /// @endcond
310436c2adSjeremylt 
327a982d89SJeremy L. Thompson /// @addtogroup CeedVectorUser
337a982d89SJeremy L. Thompson /// @{
347a982d89SJeremy L. Thompson 
357a982d89SJeremy L. Thompson /// Indicate that vector will be provided as an explicit argument to
367a982d89SJeremy L. Thompson ///   CeedOperatorApply().
377a982d89SJeremy L. Thompson const CeedVector CEED_VECTOR_ACTIVE = &ceed_vector_active;
387a982d89SJeremy L. Thompson 
3996b902e2Sjeremylt /// Indicate that no vector is applicable (i.e., for @ref CEED_EVAL_WEIGHT).
407a982d89SJeremy L. Thompson const CeedVector CEED_VECTOR_NONE = &ceed_vector_none;
417a982d89SJeremy L. Thompson 
427a982d89SJeremy L. Thompson /// @}
437a982d89SJeremy L. Thompson 
447a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
457a982d89SJeremy L. Thompson /// CeedVector Backend API
467a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
477a982d89SJeremy L. Thompson /// @addtogroup CeedVectorBackend
487a982d89SJeremy L. Thompson /// @{
497a982d89SJeremy L. Thompson 
507a982d89SJeremy L. Thompson /**
517a982d89SJeremy L. Thompson   @brief Get the state of a CeedVector
527a982d89SJeremy L. Thompson 
537a982d89SJeremy L. Thompson   @param vec         CeedVector to retrieve state
547a982d89SJeremy L. Thompson   @param[out] state  Variable to store state
557a982d89SJeremy L. Thompson 
567a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
577a982d89SJeremy L. Thompson 
587a982d89SJeremy L. Thompson   @ref Backend
597a982d89SJeremy L. Thompson **/
607a982d89SJeremy L. Thompson int CeedVectorGetState(CeedVector vec, uint64_t *state) {
617a982d89SJeremy L. Thompson   *state = vec->state;
62e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
637a982d89SJeremy L. Thompson }
647a982d89SJeremy L. Thompson 
657a982d89SJeremy L. Thompson /**
6627312b0fSJed Brown   @brief Add a reference to a CeedVector
677a982d89SJeremy L. Thompson 
685f67fadeSJeremy L Thompson   @param[out] vec  CeedVector to increment reference counter
697a982d89SJeremy L. Thompson 
707a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
717a982d89SJeremy L. Thompson 
727a982d89SJeremy L. Thompson   @ref Backend
737a982d89SJeremy L. Thompson **/
747a982d89SJeremy L. Thompson int CeedVectorAddReference(CeedVector vec) {
75d1d35e2fSjeremylt   vec->ref_count++;
76e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
777a982d89SJeremy L. Thompson }
787a982d89SJeremy L. Thompson 
797a982d89SJeremy L. Thompson /**
807a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedVector
817a982d89SJeremy L. Thompson 
827a982d89SJeremy L. Thompson   @param vec        CeedVector to retrieve state
837a982d89SJeremy L. Thompson   @param[out] data  Variable to store data
847a982d89SJeremy L. Thompson 
857a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
867a982d89SJeremy L. Thompson 
877a982d89SJeremy L. Thompson   @ref Backend
887a982d89SJeremy L. Thompson **/
89777ff853SJeremy L Thompson int CeedVectorGetData(CeedVector vec, void *data) {
90777ff853SJeremy L Thompson   *(void **)data = vec->data;
91e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
927a982d89SJeremy L. Thompson }
937a982d89SJeremy L. Thompson 
947a982d89SJeremy L. Thompson /**
957a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedVector
967a982d89SJeremy L. Thompson 
977a982d89SJeremy L. Thompson   @param[out] vec  CeedVector to retrieve state
987a982d89SJeremy L. Thompson   @param data      Data to set
997a982d89SJeremy L. Thompson 
1007a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1017a982d89SJeremy L. Thompson 
1027a982d89SJeremy L. Thompson   @ref Backend
1037a982d89SJeremy L. Thompson **/
104777ff853SJeremy L Thompson int CeedVectorSetData(CeedVector vec, void *data) {
105777ff853SJeremy L Thompson   vec->data = data;
106e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1077a982d89SJeremy L. Thompson }
1087a982d89SJeremy L. Thompson 
10934359f16Sjeremylt /**
11034359f16Sjeremylt   @brief Increment the reference counter for a CeedVector
11134359f16Sjeremylt 
11234359f16Sjeremylt   @param vec  CeedVector to increment the reference counter
11334359f16Sjeremylt 
11434359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
11534359f16Sjeremylt 
11634359f16Sjeremylt   @ref Backend
11734359f16Sjeremylt **/
1189560d06aSjeremylt int CeedVectorReference(CeedVector vec) {
11934359f16Sjeremylt   vec->ref_count++;
12034359f16Sjeremylt   return CEED_ERROR_SUCCESS;
12134359f16Sjeremylt }
12234359f16Sjeremylt 
1237a982d89SJeremy L. Thompson /// @}
1247a982d89SJeremy L. Thompson 
1257a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1267a982d89SJeremy L. Thompson /// CeedVector Public API
1277a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1287a982d89SJeremy L. Thompson /// @addtogroup CeedVectorUser
1290436c2adSjeremylt /// @{
1300436c2adSjeremylt 
1310436c2adSjeremylt /**
1320436c2adSjeremylt   @brief Create a CeedVector of the specified length (does not allocate memory)
1330436c2adSjeremylt 
1340436c2adSjeremylt   @param ceed      Ceed object where the CeedVector will be created
1350436c2adSjeremylt   @param length    Length of vector
1360436c2adSjeremylt   @param[out] vec  Address of the variable where the newly created
1370436c2adSjeremylt                      CeedVector will be stored
1380436c2adSjeremylt 
1390436c2adSjeremylt   @return An error code: 0 - success, otherwise - failure
1400436c2adSjeremylt 
1417a982d89SJeremy L. Thompson   @ref User
1420436c2adSjeremylt **/
1430436c2adSjeremylt int CeedVectorCreate(Ceed ceed, CeedInt length, CeedVector *vec) {
1440436c2adSjeremylt   int ierr;
1450436c2adSjeremylt 
1460436c2adSjeremylt   if (!ceed->VectorCreate) {
1470436c2adSjeremylt     Ceed delegate;
1480436c2adSjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Vector"); CeedChk(ierr);
1490436c2adSjeremylt 
1500436c2adSjeremylt     if (!delegate)
1510436c2adSjeremylt       // LCOV_EXCL_START
152e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
153e15f9bd0SJeremy L Thompson                        "Backend does not support VectorCreate");
1540436c2adSjeremylt     // LCOV_EXCL_STOP
1550436c2adSjeremylt 
1560436c2adSjeremylt     ierr = CeedVectorCreate(delegate, length, vec); CeedChk(ierr);
157e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
1580436c2adSjeremylt   }
1590436c2adSjeremylt 
1600436c2adSjeremylt   ierr = CeedCalloc(1, vec); CeedChk(ierr);
1610436c2adSjeremylt   (*vec)->ceed = ceed;
1629560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
163d1d35e2fSjeremylt   (*vec)->ref_count = 1;
1640436c2adSjeremylt   (*vec)->length = length;
1650436c2adSjeremylt   (*vec)->state = 0;
1660436c2adSjeremylt   ierr = ceed->VectorCreate(length, *vec); CeedChk(ierr);
167e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1680436c2adSjeremylt }
1690436c2adSjeremylt 
1700436c2adSjeremylt /**
1719560d06aSjeremylt   @brief Copy the pointer to a CeedVector. Both pointers should
1729560d06aSjeremylt            be destroyed with `CeedVectorDestroy()`;
1739560d06aSjeremylt            Note: If `*vec_copy` is non-NULL, then it is assumed that
1749560d06aSjeremylt            `*vec_copy` is a pointer to a CeedVector. This
1759560d06aSjeremylt            CeedVector will be destroyed if `*vec_copy` is the only
1769560d06aSjeremylt            reference to this CeedVector.
1779560d06aSjeremylt 
1789560d06aSjeremylt   @param vec            CeedVector to copy reference to
1799560d06aSjeremylt   @param[out] vec_copy  Variable to store copied reference
1809560d06aSjeremylt 
1819560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
1829560d06aSjeremylt 
1839560d06aSjeremylt   @ref User
1849560d06aSjeremylt **/
1859560d06aSjeremylt int CeedVectorReferenceCopy(CeedVector vec, CeedVector *vec_copy) {
1869560d06aSjeremylt   int ierr;
1879560d06aSjeremylt 
1889560d06aSjeremylt   ierr = CeedVectorReference(vec); CeedChk(ierr);
1899560d06aSjeremylt   ierr = CeedVectorDestroy(vec_copy); CeedChk(ierr);
1909560d06aSjeremylt   *vec_copy = vec;
1919560d06aSjeremylt   return CEED_ERROR_SUCCESS;
1929560d06aSjeremylt }
1939560d06aSjeremylt 
1949560d06aSjeremylt /**
1950436c2adSjeremylt   @brief Set the array used by a CeedVector, freeing any previously allocated
196b3cf021fSjeremylt            array if applicable. The backend may copy values to a different
197b3cf021fSjeremylt            memtype, such as during @ref CeedOperatorApply().
1986a6c615bSJeremy L Thompson            See also @ref CeedVectorSyncArray() and @ref CeedVectorTakeArray().
1990436c2adSjeremylt 
2000436c2adSjeremylt   @param vec        CeedVector
201d1d35e2fSjeremylt   @param mem_type   Memory type of the array being passed
202d1d35e2fSjeremylt   @param copy_mode  Copy mode for the array
2034cc79fe7SJed Brown   @param array      Array to be used, or NULL with @ref CEED_COPY_VALUES to have the
2040436c2adSjeremylt                       library allocate
2050436c2adSjeremylt 
2060436c2adSjeremylt   @return An error code: 0 - success, otherwise - failure
2070436c2adSjeremylt 
2087a982d89SJeremy L. Thompson   @ref User
2090436c2adSjeremylt **/
210d1d35e2fSjeremylt int CeedVectorSetArray(CeedVector vec, CeedMemType mem_type,
211d1d35e2fSjeremylt                        CeedCopyMode copy_mode,
2120436c2adSjeremylt                        CeedScalar *array) {
2130436c2adSjeremylt   int ierr;
2140436c2adSjeremylt 
2150436c2adSjeremylt   if (!vec->SetArray)
2160436c2adSjeremylt     // LCOV_EXCL_START
217e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_UNSUPPORTED,
218e15f9bd0SJeremy L Thompson                      "Backend does not support VectorSetArray");
2190436c2adSjeremylt   // LCOV_EXCL_STOP
2200436c2adSjeremylt 
2210436c2adSjeremylt   if (vec->state % 2 == 1)
222e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_ACCESS,
223e15f9bd0SJeremy L Thompson                      "Cannot grant CeedVector array access, the "
2240436c2adSjeremylt                      "access lock is already in use");
2250436c2adSjeremylt 
226d1d35e2fSjeremylt   if (vec->num_readers > 0)
227e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_ACCESS,
228e15f9bd0SJeremy L Thompson                      "Cannot grant CeedVector array access, a "
2290436c2adSjeremylt                      "process has read access");
2300436c2adSjeremylt 
231d1d35e2fSjeremylt   ierr = vec->SetArray(vec, mem_type, copy_mode, array); CeedChk(ierr);
2320436c2adSjeremylt   vec->state += 2;
233e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2340436c2adSjeremylt }
2350436c2adSjeremylt 
2360436c2adSjeremylt /**
2370436c2adSjeremylt   @brief Set the CeedVector to a constant value
2380436c2adSjeremylt 
2390436c2adSjeremylt   @param vec        CeedVector
2400436c2adSjeremylt   @param[in] value  Value to be used
2410436c2adSjeremylt 
2420436c2adSjeremylt   @return An error code: 0 - success, otherwise - failure
2430436c2adSjeremylt 
2447a982d89SJeremy L. Thompson   @ref User
2450436c2adSjeremylt **/
2460436c2adSjeremylt int CeedVectorSetValue(CeedVector vec, CeedScalar value) {
2470436c2adSjeremylt   int ierr;
2480436c2adSjeremylt 
2490436c2adSjeremylt   if (vec->state % 2 == 1)
250e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_ACCESS,
251e15f9bd0SJeremy L Thompson                      "Cannot grant CeedVector array access, the "
2520436c2adSjeremylt                      "access lock is already in use");
2530436c2adSjeremylt 
2540436c2adSjeremylt   if (vec->SetValue) {
2550436c2adSjeremylt     ierr = vec->SetValue(vec, value); CeedChk(ierr);
2560436c2adSjeremylt   } else {
2570436c2adSjeremylt     CeedScalar *array;
2580436c2adSjeremylt     ierr = CeedVectorGetArray(vec, CEED_MEM_HOST, &array); CeedChk(ierr);
2590436c2adSjeremylt     for (int i=0; i<vec->length; i++) array[i] = value;
2600436c2adSjeremylt     ierr = CeedVectorRestoreArray(vec, &array); CeedChk(ierr);
2610436c2adSjeremylt   }
2620436c2adSjeremylt   vec->state += 2;
263e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2640436c2adSjeremylt }
2650436c2adSjeremylt 
2660436c2adSjeremylt /**
267b3cf021fSjeremylt   @brief Sync the CeedVector to a specified memtype. This function is used to
268b3cf021fSjeremylt            force synchronization of arrays set with @ref CeedVectorSetArray().
269b3cf021fSjeremylt            If the requested memtype is already synchronized, this function
270b3cf021fSjeremylt            results in a no-op.
2710436c2adSjeremylt 
2720436c2adSjeremylt   @param vec       CeedVector
273d1d35e2fSjeremylt   @param mem_type  Memtype to be synced
2740436c2adSjeremylt 
2750436c2adSjeremylt   @return An error code: 0 - success, otherwise - failure
2760436c2adSjeremylt 
2777a982d89SJeremy L. Thompson   @ref User
2780436c2adSjeremylt **/
279d1d35e2fSjeremylt int CeedVectorSyncArray(CeedVector vec, CeedMemType mem_type) {
2800436c2adSjeremylt   int ierr;
2810436c2adSjeremylt 
2820436c2adSjeremylt   if (vec->state % 2 == 1)
283e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_ACCESS,
284e15f9bd0SJeremy L Thompson                      "Cannot sync CeedVector, the access lock is "
2850436c2adSjeremylt                      "already in use");
2860436c2adSjeremylt 
2870436c2adSjeremylt   if (vec->SyncArray) {
288d1d35e2fSjeremylt     ierr = vec->SyncArray(vec, mem_type); CeedChk(ierr);
2890436c2adSjeremylt   } else {
2900436c2adSjeremylt     const CeedScalar *array;
291d1d35e2fSjeremylt     ierr = CeedVectorGetArrayRead(vec, mem_type, &array); CeedChk(ierr);
2920436c2adSjeremylt     ierr = CeedVectorRestoreArrayRead(vec, &array); CeedChk(ierr);
2930436c2adSjeremylt   }
294e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2950436c2adSjeremylt }
2960436c2adSjeremylt 
2970436c2adSjeremylt /**
2986a6c615bSJeremy L Thompson   @brief Take ownership of the CeedVector array and remove the array from the
29958921e9fSJeremy L Thompson            CeedVector. The caller is responsible for managing and freeing
30058921e9fSJeremy L Thompson            the array.
3016a6c615bSJeremy L Thompson 
3026a6c615bSJeremy L Thompson   @param vec         CeedVector
303d1d35e2fSjeremylt   @param mem_type    Memory type on which to take the array. If the backend
3046a6c615bSJeremy L Thompson                        uses a different memory type, this will perform a copy.
305d1d35e2fSjeremylt   @param[out] array  Array on memory type mem_type, or NULL if array pointer is
3066a6c615bSJeremy L Thompson                        not required
3076a6c615bSJeremy L Thompson 
3086a6c615bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
3096a6c615bSJeremy L Thompson 
3106a6c615bSJeremy L Thompson   @ref User
3116a6c615bSJeremy L Thompson **/
312d1d35e2fSjeremylt int CeedVectorTakeArray(CeedVector vec, CeedMemType mem_type,
313d1d35e2fSjeremylt                         CeedScalar **array) {
3146a6c615bSJeremy L Thompson   int ierr;
3156a6c615bSJeremy L Thompson 
3166a6c615bSJeremy L Thompson   if (vec->state % 2 == 1)
3176a6c615bSJeremy L Thompson     // LCOV_EXCL_START
318e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_ACCESS,
319e15f9bd0SJeremy L Thompson                      "Cannot take CeedVector array, the access "
3206a6c615bSJeremy L Thompson                      "lock is already in use");
3216a6c615bSJeremy L Thompson   // LCOV_EXCL_STOP
322d1d35e2fSjeremylt   if (vec->num_readers > 0)
3236a6c615bSJeremy L Thompson     // LCOV_EXCL_START
324e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_ACCESS,
325e15f9bd0SJeremy L Thompson                      "Cannot take CeedVector array, a process "
3266a6c615bSJeremy L Thompson                      "has read access");
3276a6c615bSJeremy L Thompson   // LCOV_EXCL_STOP
3286a6c615bSJeremy L Thompson 
329d1d35e2fSjeremylt   CeedScalar *temp_array = NULL;
330d1d35e2fSjeremylt   ierr = vec->TakeArray(vec, mem_type, &temp_array); CeedChk(ierr);
331d1d35e2fSjeremylt   if (array) (*array) = temp_array;
332e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3336a6c615bSJeremy L Thompson }
3346a6c615bSJeremy L Thompson 
3356a6c615bSJeremy L Thompson /**
336b3cf021fSjeremylt   @brief Get read/write access to a CeedVector via the specified memory type.
337b3cf021fSjeremylt            Restore access with @ref CeedVectorRestoreArray().
3380436c2adSjeremylt 
3390436c2adSjeremylt   @param vec         CeedVector to access
340d1d35e2fSjeremylt   @param mem_type    Memory type on which to access the array. If the backend
341b3cf021fSjeremylt                        uses a different memory type, this will perform a copy.
342d1d35e2fSjeremylt   @param[out] array  Array on memory type mem_type
3430436c2adSjeremylt 
3440436c2adSjeremylt   @note The CeedVectorGetArray* and CeedVectorRestoreArray* functions provide
3450436c2adSjeremylt     access to array pointers in the desired memory space. Pairing get/restore
3460436c2adSjeremylt     allows the Vector to track access, thus knowing if norms or other
3470436c2adSjeremylt     operations may need to be recomputed.
3480436c2adSjeremylt 
3490436c2adSjeremylt   @return An error code: 0 - success, otherwise - failure
3500436c2adSjeremylt 
3517a982d89SJeremy L. Thompson   @ref User
3520436c2adSjeremylt **/
353d1d35e2fSjeremylt int CeedVectorGetArray(CeedVector vec, CeedMemType mem_type,
354d1d35e2fSjeremylt                        CeedScalar **array) {
3550436c2adSjeremylt   int ierr;
3560436c2adSjeremylt 
3570436c2adSjeremylt   if (!vec->GetArray)
3580436c2adSjeremylt     // LCOV_EXCL_START
359e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_UNSUPPORTED,
360e15f9bd0SJeremy L Thompson                      "Backend does not support GetArray");
3610436c2adSjeremylt   // LCOV_EXCL_STOP
3620436c2adSjeremylt 
3630436c2adSjeremylt   if (vec->state % 2 == 1)
364e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_ACCESS,
365e15f9bd0SJeremy L Thompson                      "Cannot grant CeedVector array access, the "
3660436c2adSjeremylt                      "access lock is already in use");
3670436c2adSjeremylt 
368d1d35e2fSjeremylt   if (vec->num_readers > 0)
369e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_ACCESS,
370e15f9bd0SJeremy L Thompson                      "Cannot grant CeedVector array access, a "
3710436c2adSjeremylt                      "process has read access");
3720436c2adSjeremylt 
373d1d35e2fSjeremylt   ierr = vec->GetArray(vec, mem_type, array); CeedChk(ierr);
3740436c2adSjeremylt   vec->state += 1;
375e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3760436c2adSjeremylt }
3770436c2adSjeremylt 
3780436c2adSjeremylt /**
379b3cf021fSjeremylt   @brief Get read-only access to a CeedVector via the specified memory type.
380b3cf021fSjeremylt            Restore access with @ref CeedVectorRestoreArrayRead().
3810436c2adSjeremylt 
3820436c2adSjeremylt   @param vec         CeedVector to access
383d1d35e2fSjeremylt   @param mem_type    Memory type on which to access the array.  If the backend
3840436c2adSjeremylt                        uses a different memory type, this will perform a copy
3850436c2adSjeremylt                        (possibly cached).
386d1d35e2fSjeremylt   @param[out] array  Array on memory type mem_type
3870436c2adSjeremylt 
3880436c2adSjeremylt   @return An error code: 0 - success, otherwise - failure
3890436c2adSjeremylt 
3907a982d89SJeremy L. Thompson   @ref User
3910436c2adSjeremylt **/
392d1d35e2fSjeremylt int CeedVectorGetArrayRead(CeedVector vec, CeedMemType mem_type,
3930436c2adSjeremylt                            const CeedScalar **array) {
3940436c2adSjeremylt   int ierr;
3950436c2adSjeremylt 
3960436c2adSjeremylt   if (!vec->GetArrayRead)
3970436c2adSjeremylt     // LCOV_EXCL_START
398e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_UNSUPPORTED,
399e15f9bd0SJeremy L Thompson                      "Backend does not support GetArrayRead");
4000436c2adSjeremylt   // LCOV_EXCL_STOP
4010436c2adSjeremylt 
4020436c2adSjeremylt   if (vec->state % 2 == 1)
403e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_ACCESS,
404e15f9bd0SJeremy L Thompson                      "Cannot grant CeedVector read-only array "
4050436c2adSjeremylt                      "access, the access lock is already in use");
4060436c2adSjeremylt 
407d1d35e2fSjeremylt   ierr = vec->GetArrayRead(vec, mem_type, array); CeedChk(ierr);
408d1d35e2fSjeremylt   vec->num_readers++;
409e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4100436c2adSjeremylt }
4110436c2adSjeremylt 
4120436c2adSjeremylt /**
413b3cf021fSjeremylt   @brief Restore an array obtained using @ref CeedVectorGetArray()
4140436c2adSjeremylt 
4150436c2adSjeremylt   @param vec    CeedVector to restore
4160436c2adSjeremylt   @param array  Array of vector data
4170436c2adSjeremylt 
4180436c2adSjeremylt   @return An error code: 0 - success, otherwise - failure
4190436c2adSjeremylt 
4207a982d89SJeremy L. Thompson   @ref User
4210436c2adSjeremylt **/
4220436c2adSjeremylt int CeedVectorRestoreArray(CeedVector vec, CeedScalar **array) {
4230436c2adSjeremylt   int ierr;
4240436c2adSjeremylt 
4250436c2adSjeremylt   if (!vec->RestoreArray)
4260436c2adSjeremylt     // LCOV_EXCL_START
427e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_UNSUPPORTED,
428e15f9bd0SJeremy L Thompson                      "Backend does not support RestoreArray");
4290436c2adSjeremylt   // LCOV_EXCL_STOP
4300436c2adSjeremylt 
4310436c2adSjeremylt   if (vec->state % 2 != 1)
432e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_ACCESS,
433e15f9bd0SJeremy L Thompson                      "Cannot restore CeedVector array access, "
4340436c2adSjeremylt                      "access was not granted");
4350436c2adSjeremylt 
4360436c2adSjeremylt   ierr = vec->RestoreArray(vec); CeedChk(ierr);
4370436c2adSjeremylt   *array = NULL;
4380436c2adSjeremylt   vec->state += 1;
439e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4400436c2adSjeremylt }
4410436c2adSjeremylt 
4420436c2adSjeremylt /**
443b3cf021fSjeremylt   @brief Restore an array obtained using @ref CeedVectorGetArrayRead()
4440436c2adSjeremylt 
4450436c2adSjeremylt   @param vec    CeedVector to restore
4460436c2adSjeremylt   @param array  Array of vector data
4470436c2adSjeremylt 
4480436c2adSjeremylt   @return An error code: 0 - success, otherwise - failure
4490436c2adSjeremylt 
4507a982d89SJeremy L. Thompson   @ref User
4510436c2adSjeremylt **/
4520436c2adSjeremylt int CeedVectorRestoreArrayRead(CeedVector vec, const CeedScalar **array) {
4530436c2adSjeremylt   int ierr;
4540436c2adSjeremylt 
4550436c2adSjeremylt   if (!vec->RestoreArrayRead)
4560436c2adSjeremylt     // LCOV_EXCL_START
457e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_UNSUPPORTED,
458e15f9bd0SJeremy L Thompson                      "Backend does not support RestoreArrayRead");
4590436c2adSjeremylt   // LCOV_EXCL_STOP
4600436c2adSjeremylt 
4610436c2adSjeremylt   ierr = vec->RestoreArrayRead(vec); CeedChk(ierr);
4620436c2adSjeremylt   *array = NULL;
463d1d35e2fSjeremylt   vec->num_readers--;
464e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4650436c2adSjeremylt }
4660436c2adSjeremylt 
4670436c2adSjeremylt /**
468171f8ca9Sjeremylt   @brief Get the norm of a CeedVector.
469171f8ca9Sjeremylt 
470171f8ca9Sjeremylt   Note: This operation is local to the CeedVector. This function will likely
471171f8ca9Sjeremylt           not provide the desired results for the norm of the libCEED portion
472171f8ca9Sjeremylt           of a parallel vector or a CeedVector with duplicated or hanging nodes.
473547d9b97Sjeremylt 
474547d9b97Sjeremylt   @param vec        CeedVector to retrieve maximum value
475d1d35e2fSjeremylt   @param norm_type  Norm type @ref CEED_NORM_1, @ref CEED_NORM_2, or @ref CEED_NORM_MAX
476547d9b97Sjeremylt   @param[out] norm  Variable to store norm value
477547d9b97Sjeremylt 
478547d9b97Sjeremylt   @return An error code: 0 - success, otherwise - failure
479547d9b97Sjeremylt 
4807a982d89SJeremy L. Thompson   @ref User
481547d9b97Sjeremylt **/
482d1d35e2fSjeremylt int CeedVectorNorm(CeedVector vec, CeedNormType norm_type, CeedScalar *norm) {
483547d9b97Sjeremylt   int ierr;
484547d9b97Sjeremylt 
485547d9b97Sjeremylt   // Backend impl for GPU, if added
486547d9b97Sjeremylt   if (vec->Norm) {
487d1d35e2fSjeremylt     ierr = vec->Norm(vec, norm_type, norm); CeedChk(ierr);
488e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
489547d9b97Sjeremylt   }
490547d9b97Sjeremylt 
491547d9b97Sjeremylt   const CeedScalar *array;
492547d9b97Sjeremylt   ierr = CeedVectorGetArrayRead(vec, CEED_MEM_HOST, &array); CeedChk(ierr);
493547d9b97Sjeremylt 
494547d9b97Sjeremylt   *norm = 0.;
495d1d35e2fSjeremylt   switch (norm_type) {
496547d9b97Sjeremylt   case CEED_NORM_1:
497547d9b97Sjeremylt     for (int i=0; i<vec->length; i++) {
498547d9b97Sjeremylt       *norm += fabs(array[i]);
499547d9b97Sjeremylt     }
500547d9b97Sjeremylt     break;
501547d9b97Sjeremylt   case CEED_NORM_2:
502547d9b97Sjeremylt     for (int i=0; i<vec->length; i++) {
503547d9b97Sjeremylt       *norm += fabs(array[i])*fabs(array[i]);
504547d9b97Sjeremylt     }
505547d9b97Sjeremylt     break;
506547d9b97Sjeremylt   case CEED_NORM_MAX:
507547d9b97Sjeremylt     for (int i=0; i<vec->length; i++) {
508d1d35e2fSjeremylt       const CeedScalar abs_v_i = fabs(array[i]);
509d1d35e2fSjeremylt       *norm = *norm > abs_v_i ? *norm : abs_v_i;
510547d9b97Sjeremylt     }
511547d9b97Sjeremylt   }
512d1d35e2fSjeremylt   if (norm_type == CEED_NORM_2)
513547d9b97Sjeremylt     *norm = sqrt(*norm);
514547d9b97Sjeremylt 
515547d9b97Sjeremylt   ierr = CeedVectorRestoreArrayRead(vec, &array); CeedChk(ierr);
516e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
517547d9b97Sjeremylt }
518547d9b97Sjeremylt 
519547d9b97Sjeremylt /**
520e0dd3b27Sjeremylt   @brief Compute x = alpha x
521e0dd3b27Sjeremylt 
52296b902e2Sjeremylt   @param[in,out] x  vector for scaling
52396b902e2Sjeremylt   @param[in] alpha  scaling factor
524e0dd3b27Sjeremylt 
525e0dd3b27Sjeremylt   @return An error code: 0 - success, otherwise - failure
526e0dd3b27Sjeremylt 
527e0dd3b27Sjeremylt   @ref User
528e0dd3b27Sjeremylt **/
529e0dd3b27Sjeremylt int CeedVectorScale(CeedVector x, CeedScalar alpha) {
530e0dd3b27Sjeremylt   int ierr;
531e0dd3b27Sjeremylt   CeedScalar *x_array;
532e0dd3b27Sjeremylt   CeedInt n_x;
533e0dd3b27Sjeremylt 
534e0dd3b27Sjeremylt   ierr = CeedVectorGetLength(x, &n_x); CeedChk(ierr);
535e0dd3b27Sjeremylt 
536e0dd3b27Sjeremylt   // Backend implementation
537e0dd3b27Sjeremylt   if (x->Scale)
538e0dd3b27Sjeremylt     return x->Scale(x, alpha);
539e0dd3b27Sjeremylt 
540e0dd3b27Sjeremylt   // Default implementation
541e0dd3b27Sjeremylt   ierr = CeedVectorGetArray(x, CEED_MEM_HOST, &x_array); CeedChk(ierr);
542e0dd3b27Sjeremylt   for (CeedInt i=0; i<n_x; i++)
543e0dd3b27Sjeremylt     x_array[i] *= alpha;
544e0dd3b27Sjeremylt   ierr = CeedVectorRestoreArray(x, &x_array); CeedChk(ierr);
545e0dd3b27Sjeremylt 
546e0dd3b27Sjeremylt   return CEED_ERROR_SUCCESS;
547e0dd3b27Sjeremylt }
548e0dd3b27Sjeremylt 
549e0dd3b27Sjeremylt /**
5500f7fd0f8Sjeremylt   @brief Compute y = alpha x + y
5510f7fd0f8Sjeremylt 
55296b902e2Sjeremylt   @param[in,out] y  target vector for sum
55396b902e2Sjeremylt   @param[in] alpha  scaling factor
55496b902e2Sjeremylt   @param[in] x      second vector, must be different than y
5550f7fd0f8Sjeremylt 
5560f7fd0f8Sjeremylt   @return An error code: 0 - success, otherwise - failure
5570f7fd0f8Sjeremylt 
5580f7fd0f8Sjeremylt   @ref User
5590f7fd0f8Sjeremylt **/
5600f7fd0f8Sjeremylt int CeedVectorAXPY(CeedVector y, CeedScalar alpha, CeedVector x) {
5610f7fd0f8Sjeremylt   int ierr;
5620f7fd0f8Sjeremylt   CeedScalar *y_array;
5630f7fd0f8Sjeremylt   CeedScalar const *x_array;
5640f7fd0f8Sjeremylt   CeedInt n_x, n_y;
5650f7fd0f8Sjeremylt 
5660f7fd0f8Sjeremylt   ierr = CeedVectorGetLength(y, &n_y); CeedChk(ierr);
5670f7fd0f8Sjeremylt   ierr = CeedVectorGetLength(x, &n_x); CeedChk(ierr);
5680f7fd0f8Sjeremylt   if (n_x != n_y)
5690f7fd0f8Sjeremylt     // LCOV_EXCL_START
5700f7fd0f8Sjeremylt     return CeedError(y->ceed, CEED_ERROR_UNSUPPORTED,
5710f7fd0f8Sjeremylt                      "Cannot add vector of different lengths");
5720f7fd0f8Sjeremylt   // LCOV_EXCL_STOP
5730f7fd0f8Sjeremylt   if (x == y)
5740f7fd0f8Sjeremylt     // LCOV_EXCL_START
5750f7fd0f8Sjeremylt     return CeedError(y->ceed, CEED_ERROR_UNSUPPORTED,
5760f7fd0f8Sjeremylt                      "Cannot use same vector for x and y in CeedVectorAXPY");
5770f7fd0f8Sjeremylt   // LCOV_EXCL_STOP
5780f7fd0f8Sjeremylt 
5792d04630dSjeremylt   Ceed ceed_parent_x, ceed_parent_y;
5802d04630dSjeremylt   ierr = CeedGetParent(x->ceed, &ceed_parent_x); CeedChk(ierr);
5812d04630dSjeremylt   ierr = CeedGetParent(y->ceed, &ceed_parent_y); CeedChk(ierr);
5822d04630dSjeremylt   if (ceed_parent_x != ceed_parent_y)
5832d04630dSjeremylt     // LCOV_EXCL_START
5842d04630dSjeremylt     return CeedError(y->ceed, CEED_ERROR_INCOMPATIBLE,
5852d04630dSjeremylt                      "Vectors x and y must be created by the same Ceed context");
5862d04630dSjeremylt   // LCOV_EXCL_STOP
5872d04630dSjeremylt 
5880f7fd0f8Sjeremylt   // Backend implementation
589eaf62fffSJeremy L Thompson   if (y->AXPY) {
590eaf62fffSJeremy L Thompson     ierr = y->AXPY(y, alpha, x); CeedChk(ierr);
591eaf62fffSJeremy L Thompson     return CEED_ERROR_SUCCESS;
592eaf62fffSJeremy L Thompson   }
5930f7fd0f8Sjeremylt 
5940f7fd0f8Sjeremylt   // Default implementation
5950f7fd0f8Sjeremylt   ierr = CeedVectorGetArray(y, CEED_MEM_HOST, &y_array); CeedChk(ierr);
5960f7fd0f8Sjeremylt   ierr = CeedVectorGetArrayRead(x, CEED_MEM_HOST, &x_array); CeedChk(ierr);
5970f7fd0f8Sjeremylt 
5980f7fd0f8Sjeremylt   for (CeedInt i=0; i<n_y; i++)
5990f7fd0f8Sjeremylt     y_array[i] += alpha * x_array[i];
6000f7fd0f8Sjeremylt 
6010f7fd0f8Sjeremylt   ierr = CeedVectorRestoreArray(y, &y_array); CeedChk(ierr);
6020f7fd0f8Sjeremylt   ierr = CeedVectorRestoreArrayRead(x, &x_array); CeedChk(ierr);
6030f7fd0f8Sjeremylt 
6040f7fd0f8Sjeremylt   return CEED_ERROR_SUCCESS;
6050f7fd0f8Sjeremylt }
6060f7fd0f8Sjeremylt 
6070f7fd0f8Sjeremylt /**
6080c1bc3c2Sjeremylt   @brief Compute the pointwise multiplication w = x .* y. Any
6090f7fd0f8Sjeremylt            subset of x, y, and w may be the same vector.
6100f7fd0f8Sjeremylt 
61196b902e2Sjeremylt   @param[out] w  target vector for the product
61296b902e2Sjeremylt   @param[in] x   first vector for product
61396b902e2Sjeremylt   @param[in] y   second vector for the product
6140f7fd0f8Sjeremylt 
6150f7fd0f8Sjeremylt   @return An error code: 0 - success, otherwise - failure
6160f7fd0f8Sjeremylt 
6170f7fd0f8Sjeremylt   @ ref User
6180f7fd0f8Sjeremylt **/
6190f7fd0f8Sjeremylt int CeedVectorPointwiseMult(CeedVector w, CeedVector x, CeedVector y) {
6200f7fd0f8Sjeremylt   int ierr;
6210f7fd0f8Sjeremylt   CeedScalar *w_array;
6220f7fd0f8Sjeremylt   CeedScalar const *x_array, *y_array;
6232d04630dSjeremylt   CeedInt n_w, n_x, n_y;
6240f7fd0f8Sjeremylt 
6250f7fd0f8Sjeremylt   ierr = CeedVectorGetLength(w, &n_w); CeedChk(ierr);
6260f7fd0f8Sjeremylt   ierr = CeedVectorGetLength(x, &n_x); CeedChk(ierr);
6270f7fd0f8Sjeremylt   ierr = CeedVectorGetLength(y, &n_y); CeedChk(ierr);
6280f7fd0f8Sjeremylt   if (n_w != n_x || n_w != n_y)
6290f7fd0f8Sjeremylt     // LCOV_EXCL_START
6300f7fd0f8Sjeremylt     return CeedError(w->ceed, CEED_ERROR_UNSUPPORTED,
6310f7fd0f8Sjeremylt                      "Cannot multiply vectors of different lengths");
6320f7fd0f8Sjeremylt   // LCOV_EXCL_STOP
6330f7fd0f8Sjeremylt 
6342d04630dSjeremylt   Ceed ceed_parent_w, ceed_parent_x, ceed_parent_y;
6352d04630dSjeremylt   ierr = CeedGetParent(w->ceed, &ceed_parent_w); CeedChk(ierr);
6362d04630dSjeremylt   ierr = CeedGetParent(x->ceed, &ceed_parent_x); CeedChk(ierr);
6372d04630dSjeremylt   ierr = CeedGetParent(y->ceed, &ceed_parent_y); CeedChk(ierr);
6382d04630dSjeremylt   if ((ceed_parent_w != ceed_parent_y) ||
6392d04630dSjeremylt       (ceed_parent_w != ceed_parent_y))
6402d04630dSjeremylt     // LCOV_EXCL_START
6412d04630dSjeremylt     return CeedError(w->ceed, CEED_ERROR_INCOMPATIBLE,
6422d04630dSjeremylt                      "Vectors w, x, and y must be created by the same Ceed context");
6432d04630dSjeremylt   // LCOV_EXCL_STOP
6442d04630dSjeremylt 
6450f7fd0f8Sjeremylt   // Backend implementation
646eaf62fffSJeremy L Thompson   if (w->PointwiseMult) {
647eaf62fffSJeremy L Thompson     ierr = w->PointwiseMult(w, x, y); CeedChk(ierr);
648eaf62fffSJeremy L Thompson     return CEED_ERROR_SUCCESS;
649eaf62fffSJeremy L Thompson   }
6500f7fd0f8Sjeremylt 
6510f7fd0f8Sjeremylt   // Default implementation
6520f7fd0f8Sjeremylt   ierr = CeedVectorGetArray(w, CEED_MEM_HOST, &w_array); CeedChk(ierr);
6530f7fd0f8Sjeremylt   if (x != w) {
6540f7fd0f8Sjeremylt     ierr = CeedVectorGetArrayRead(x, CEED_MEM_HOST, &x_array); CeedChk(ierr);
6550f7fd0f8Sjeremylt   } else {
6560f7fd0f8Sjeremylt     x_array = w_array;
6570f7fd0f8Sjeremylt   }
6580f7fd0f8Sjeremylt   if (y != w && y != x) {
6590f7fd0f8Sjeremylt     ierr = CeedVectorGetArrayRead(y, CEED_MEM_HOST, &y_array); CeedChk(ierr);
6600f7fd0f8Sjeremylt   } else if (y != x) {
6610f7fd0f8Sjeremylt     y_array = w_array;
6620f7fd0f8Sjeremylt   } else {
6630f7fd0f8Sjeremylt     y_array = x_array;
6640f7fd0f8Sjeremylt   }
6650f7fd0f8Sjeremylt 
6660f7fd0f8Sjeremylt   for (CeedInt i=0; i<n_w; i++)
6670f7fd0f8Sjeremylt     w_array[i] = x_array[i] * y_array[i];
6680f7fd0f8Sjeremylt 
6690f7fd0f8Sjeremylt   if (y != w && y != x) {
6700f7fd0f8Sjeremylt     ierr = CeedVectorRestoreArrayRead(y, &y_array); CeedChk(ierr);
6710f7fd0f8Sjeremylt   }
6720f7fd0f8Sjeremylt   if (x != w) {
6730f7fd0f8Sjeremylt     ierr = CeedVectorRestoreArrayRead(x, &x_array); CeedChk(ierr);
6740f7fd0f8Sjeremylt   }
6750f7fd0f8Sjeremylt   ierr = CeedVectorRestoreArray(w, &w_array); CeedChk(ierr);
6760f7fd0f8Sjeremylt   return CEED_ERROR_SUCCESS;
6770f7fd0f8Sjeremylt }
6780f7fd0f8Sjeremylt 
6790f7fd0f8Sjeremylt /**
680d99fa3c5SJeremy L Thompson   @brief Take the reciprocal of a CeedVector.
681d99fa3c5SJeremy L Thompson 
682d99fa3c5SJeremy L Thompson   @param vec  CeedVector to take reciprocal
683d99fa3c5SJeremy L Thompson 
684d99fa3c5SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
685d99fa3c5SJeremy L Thompson 
686d99fa3c5SJeremy L Thompson   @ref User
687d99fa3c5SJeremy L Thompson **/
688d99fa3c5SJeremy L Thompson int CeedVectorReciprocal(CeedVector vec) {
689d99fa3c5SJeremy L Thompson   int ierr;
690d99fa3c5SJeremy L Thompson 
691d99fa3c5SJeremy L Thompson   // Check if vector data set
692d99fa3c5SJeremy L Thompson   if (!vec->state)
693d99fa3c5SJeremy L Thompson     // LCOV_EXCL_START
694e15f9bd0SJeremy L Thompson     return CeedError(vec->ceed, CEED_ERROR_INCOMPLETE,
695d99fa3c5SJeremy L Thompson                      "CeedVector must have data set to take reciprocal");
696d99fa3c5SJeremy L Thompson   // LCOV_EXCL_STOP
697d99fa3c5SJeremy L Thompson 
698d99fa3c5SJeremy L Thompson   // Backend impl for GPU, if added
699d99fa3c5SJeremy L Thompson   if (vec->Reciprocal) {
700d99fa3c5SJeremy L Thompson     ierr = vec->Reciprocal(vec); CeedChk(ierr);
701e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
702d99fa3c5SJeremy L Thompson   }
703d99fa3c5SJeremy L Thompson 
704d99fa3c5SJeremy L Thompson   CeedInt len;
705d99fa3c5SJeremy L Thompson   ierr = CeedVectorGetLength(vec, &len); CeedChk(ierr);
706d99fa3c5SJeremy L Thompson   CeedScalar *array;
707d99fa3c5SJeremy L Thompson   ierr = CeedVectorGetArray(vec, CEED_MEM_HOST, &array); CeedChk(ierr);
708d99fa3c5SJeremy L Thompson   for (CeedInt i=0; i<len; i++)
709d99fa3c5SJeremy L Thompson     if (fabs(array[i]) > CEED_EPSILON)
710d99fa3c5SJeremy L Thompson       array[i] = 1./array[i];
711d99fa3c5SJeremy L Thompson 
712e15f9bd0SJeremy L Thompson   ierr = CeedVectorRestoreArray(vec, &array); CeedChk(ierr);
713e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
714d99fa3c5SJeremy L Thompson }
715d99fa3c5SJeremy L Thompson 
716d99fa3c5SJeremy L Thompson /**
7177a982d89SJeremy L. Thompson   @brief View a CeedVector
7180436c2adSjeremylt 
7190a0da059Sjeremylt   @param[in] vec     CeedVector to view
720d1d35e2fSjeremylt   @param[in] fp_fmt  Printing format
7210a0da059Sjeremylt   @param[in] stream  Filestream to write to
7220a0da059Sjeremylt 
7230436c2adSjeremylt   @return An error code: 0 - success, otherwise - failure
7240436c2adSjeremylt 
7257a982d89SJeremy L. Thompson   @ref User
7260436c2adSjeremylt **/
727d1d35e2fSjeremylt int CeedVectorView(CeedVector vec, const char *fp_fmt, FILE *stream) {
7287a982d89SJeremy L. Thompson   const CeedScalar *x;
7297a982d89SJeremy L. Thompson 
7307a982d89SJeremy L. Thompson   int ierr = CeedVectorGetArrayRead(vec, CEED_MEM_HOST, &x); CeedChk(ierr);
7317a982d89SJeremy L. Thompson 
7327a982d89SJeremy L. Thompson   char fmt[1024];
7337a982d89SJeremy L. Thompson   fprintf(stream, "CeedVector length %ld\n", (long)vec->length);
734d1d35e2fSjeremylt   snprintf(fmt, sizeof fmt, "  %s\n", fp_fmt ? fp_fmt : "%g");
7357a982d89SJeremy L. Thompson   for (CeedInt i=0; i<vec->length; i++)
7367a982d89SJeremy L. Thompson     fprintf(stream, fmt, x[i]);
7377a982d89SJeremy L. Thompson 
7387a982d89SJeremy L. Thompson   ierr = CeedVectorRestoreArrayRead(vec, &x); CeedChk(ierr);
739e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7400436c2adSjeremylt }
7410436c2adSjeremylt 
7420436c2adSjeremylt /**
743*b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedVector
744*b7c9bbdaSJeremy L Thompson 
745*b7c9bbdaSJeremy L Thompson   @param vec        CeedVector to retrieve state
746*b7c9bbdaSJeremy L Thompson   @param[out] ceed  Variable to store ceed
747*b7c9bbdaSJeremy L Thompson 
748*b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
749*b7c9bbdaSJeremy L Thompson 
750*b7c9bbdaSJeremy L Thompson   @ref Advanced
751*b7c9bbdaSJeremy L Thompson **/
752*b7c9bbdaSJeremy L Thompson int CeedVectorGetCeed(CeedVector vec, Ceed *ceed) {
753*b7c9bbdaSJeremy L Thompson   *ceed = vec->ceed;
754*b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
755*b7c9bbdaSJeremy L Thompson }
756*b7c9bbdaSJeremy L Thompson 
757*b7c9bbdaSJeremy L Thompson /**
7587a982d89SJeremy L. Thompson   @brief Get the length of a CeedVector
7590436c2adSjeremylt 
7607a982d89SJeremy L. Thompson   @param vec          CeedVector to retrieve length
7617a982d89SJeremy L. Thompson   @param[out] length  Variable to store length
7620436c2adSjeremylt 
7630436c2adSjeremylt   @return An error code: 0 - success, otherwise - failure
7640436c2adSjeremylt 
7657a982d89SJeremy L. Thompson   @ref User
7660436c2adSjeremylt **/
7677a982d89SJeremy L. Thompson int CeedVectorGetLength(CeedVector vec, CeedInt *length) {
7687a982d89SJeremy L. Thompson   *length = vec->length;
769e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7700436c2adSjeremylt }
7710436c2adSjeremylt 
7720436c2adSjeremylt /**
7730436c2adSjeremylt   @brief Destroy a CeedVector
7740436c2adSjeremylt 
7750436c2adSjeremylt   @param vec  CeedVector to destroy
7760436c2adSjeremylt 
7770436c2adSjeremylt   @return An error code: 0 - success, otherwise - failure
7780436c2adSjeremylt 
7797a982d89SJeremy L. Thompson   @ref User
7800436c2adSjeremylt **/
7810436c2adSjeremylt int CeedVectorDestroy(CeedVector *vec) {
7820436c2adSjeremylt   int ierr;
7830436c2adSjeremylt 
784d1d35e2fSjeremylt   if (!*vec || --(*vec)->ref_count > 0) return CEED_ERROR_SUCCESS;
7850436c2adSjeremylt 
786187168c7SJeremy L Thompson   if (((*vec)->state % 2) == 1)
787e15f9bd0SJeremy L Thompson     return CeedError((*vec)->ceed, CEED_ERROR_ACCESS,
788187168c7SJeremy L Thompson                      "Cannot destroy CeedVector, the writable access "
7890436c2adSjeremylt                      "lock is in use");
7900436c2adSjeremylt 
791d1d35e2fSjeremylt   if ((*vec)->num_readers > 0)
792e92b641fSJeremy L Thompson     // LCOV_EXCL_START
793e15f9bd0SJeremy L Thompson     return CeedError((*vec)->ceed, CEED_ERROR_ACCESS,
794e15f9bd0SJeremy L Thompson                      "Cannot destroy CeedVector, a process has "
795187168c7SJeremy L Thompson                      "read access");
796e92b641fSJeremy L Thompson   // LCOV_EXCL_STOP
797187168c7SJeremy L Thompson 
7980436c2adSjeremylt   if ((*vec)->Destroy) {
7990436c2adSjeremylt     ierr = (*vec)->Destroy(*vec); CeedChk(ierr);
8000436c2adSjeremylt   }
8010436c2adSjeremylt 
8020436c2adSjeremylt   ierr = CeedDestroy(&(*vec)->ceed); CeedChk(ierr);
8030436c2adSjeremylt   ierr = CeedFree(vec); CeedChk(ierr);
804e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
8050436c2adSjeremylt }
8060436c2adSjeremylt 
8070436c2adSjeremylt /// @}
808