xref: /libCEED/backends/memcheck/ceed-memcheck-vector.c (revision cc3bdf8cd7a97c52371610b7fbb458a86c2b0cc9)
15aed82e4SJeremy L Thompson // Copyright (c) 2017-2024, Lawrence Livermore National Security, LLC and other CEED contributors.
29798701eSJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
39798701eSJeremy L Thompson //
49798701eSJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
59798701eSJeremy L Thompson //
69798701eSJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
79798701eSJeremy L Thompson 
849aac155SJeremy L Thompson #include <ceed.h>
99798701eSJeremy L Thompson #include <ceed/backend.h>
1077d04a1cSJeremy L Thompson #include <assert.h>
119798701eSJeremy L Thompson #include <math.h>
1249aac155SJeremy L Thompson #include <stdbool.h>
139798701eSJeremy L Thompson #include <string.h>
149798701eSJeremy L Thompson #include <valgrind/memcheck.h>
159798701eSJeremy L Thompson 
169798701eSJeremy L Thompson #include "ceed-memcheck.h"
179798701eSJeremy L Thompson 
189798701eSJeremy L Thompson //------------------------------------------------------------------------------
199798701eSJeremy L Thompson // Has Valid Array
209798701eSJeremy L Thompson //------------------------------------------------------------------------------
219798701eSJeremy L Thompson static int CeedVectorHasValidArray_Memcheck(CeedVector vec, bool *has_valid_array) {
229798701eSJeremy L Thompson   CeedVector_Memcheck *impl;
23ad70ee2cSJeremy L Thompson 
249798701eSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
259937a20eSJeremy L Thompson   *has_valid_array = !!impl->array_allocated;
269798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
279798701eSJeremy L Thompson }
289798701eSJeremy L Thompson 
299798701eSJeremy L Thompson //------------------------------------------------------------------------------
309798701eSJeremy L Thompson // Check if has borrowed array of given type
319798701eSJeremy L Thompson //------------------------------------------------------------------------------
329798701eSJeremy L Thompson static inline int CeedVectorHasBorrowedArrayOfType_Memcheck(const CeedVector vec, CeedMemType mem_type, bool *has_borrowed_array_of_type) {
33ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
34ad70ee2cSJeremy L Thompson 
356e536b99SJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only set HOST memory for this backend");
369937a20eSJeremy L Thompson 
379937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
389937a20eSJeremy L Thompson   *has_borrowed_array_of_type = !!impl->array_borrowed;
399798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
409798701eSJeremy L Thompson }
419798701eSJeremy L Thompson 
429798701eSJeremy L Thompson //------------------------------------------------------------------------------
439798701eSJeremy L Thompson // Vector Set Array
449798701eSJeremy L Thompson //------------------------------------------------------------------------------
459798701eSJeremy L Thompson static int CeedVectorSetArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedCopyMode copy_mode, CeedScalar *array) {
46ad70ee2cSJeremy L Thompson   CeedSize             length;
47ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
48ad70ee2cSJeremy L Thompson 
499937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only set HOST memory for this backend");
509937a20eSJeremy L Thompson 
51ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
52ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
539798701eSJeremy L Thompson 
549937a20eSJeremy L Thompson   // Clear previous owned arrays
55d1931fc8SJeremy L Thompson   if (impl->array_allocated) {
56d1931fc8SJeremy L Thompson     for (CeedSize i = 0; i < length; i++) impl->array_allocated[i] = NAN;
570307dd02SJeremy L Thompson     VALGRIND_DISCARD(impl->allocated_block_id);
58d1931fc8SJeremy L Thompson   }
599798701eSJeremy L Thompson   CeedCallBackend(CeedFree(&impl->array_allocated));
60*cc3bdf8cSJeremy L Thompson   if (copy_mode != CEED_COPY_VALUES) {
61d1931fc8SJeremy L Thompson     if (impl->array_owned) {
62d1931fc8SJeremy L Thompson       for (CeedSize i = 0; i < length; i++) impl->array_owned[i] = NAN;
639937a20eSJeremy L Thompson       VALGRIND_DISCARD(impl->owned_block_id);
640307dd02SJeremy L Thompson     }
659798701eSJeremy L Thompson     CeedCallBackend(CeedFree(&impl->array_owned));
66*cc3bdf8cSJeremy L Thompson   }
679937a20eSJeremy L Thompson 
689937a20eSJeremy L Thompson   // Clear borrowed block id, if present
699937a20eSJeremy L Thompson   if (impl->array_borrowed) VALGRIND_DISCARD(impl->borrowed_block_id);
709937a20eSJeremy L Thompson 
719937a20eSJeremy L Thompson   // Set internal pointers to external arrays
729798701eSJeremy L Thompson   switch (copy_mode) {
739798701eSJeremy L Thompson     case CEED_COPY_VALUES:
74*cc3bdf8cSJeremy L Thompson       // Nothing to update
759798701eSJeremy L Thompson       break;
769798701eSJeremy L Thompson     case CEED_OWN_POINTER:
779798701eSJeremy L Thompson       impl->array_owned    = array;
789798701eSJeremy L Thompson       impl->array_borrowed = NULL;
799937a20eSJeremy L Thompson       impl->owned_block_id = VALGRIND_CREATE_BLOCK(impl->array_owned, length * sizeof(CeedScalar), "Owned external array buffer");
809798701eSJeremy L Thompson       break;
819798701eSJeremy L Thompson     case CEED_USE_POINTER:
829937a20eSJeremy L Thompson       impl->array_owned       = NULL;
839798701eSJeremy L Thompson       impl->array_borrowed    = array;
849937a20eSJeremy L Thompson       impl->borrowed_block_id = VALGRIND_CREATE_BLOCK(impl->array_borrowed, length * sizeof(CeedScalar), "Borrowed external array buffer");
859937a20eSJeremy L Thompson       break;
869798701eSJeremy L Thompson   }
879937a20eSJeremy L Thompson 
889937a20eSJeremy L Thompson   // Create internal array data buffer
899798701eSJeremy L Thompson   CeedCallBackend(CeedCalloc(length, &impl->array_allocated));
909937a20eSJeremy L Thompson   impl->allocated_block_id = VALGRIND_CREATE_BLOCK(impl->array_allocated, length * sizeof(CeedScalar), "Allocated internal array buffer");
919937a20eSJeremy L Thompson   if (array) {
929937a20eSJeremy L Thompson     memcpy(impl->array_allocated, array, length * sizeof(CeedScalar));
939937a20eSJeremy L Thompson   } else {
949937a20eSJeremy L Thompson     for (CeedInt i = 0; i < length; i++) impl->array_allocated[i] = NAN;
959937a20eSJeremy L Thompson   }
969937a20eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
979937a20eSJeremy L Thompson }
989937a20eSJeremy L Thompson 
999937a20eSJeremy L Thompson //------------------------------------------------------------------------------
10077d04a1cSJeremy L Thompson // Set internal array to value
10177d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
10277d04a1cSJeremy L Thompson static int CeedVectorSetValue_Memcheck(CeedVector vec, CeedScalar value) {
10377d04a1cSJeremy L Thompson   CeedSize             length;
10477d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl;
10577d04a1cSJeremy L Thompson 
10677d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
10777d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
10877d04a1cSJeremy L Thompson 
10977d04a1cSJeremy L Thompson   if (!impl->array_allocated) CeedCallBackend(CeedVectorSetArray_Memcheck(vec, CEED_MEM_HOST, CEED_COPY_VALUES, NULL));
11077d04a1cSJeremy L Thompson   assert(impl->array_allocated);
11177d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl->array_allocated[i] = value;
11277d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
11377d04a1cSJeremy L Thompson }
11477d04a1cSJeremy L Thompson 
11577d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
11677d04a1cSJeremy L Thompson // Set internal array to value strided
11777d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
11877d04a1cSJeremy L Thompson static int CeedVectorSetValueStrided_Memcheck(CeedVector vec, CeedSize start, CeedSize step, CeedScalar val) {
11977d04a1cSJeremy L Thompson   CeedSize             length;
12077d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl;
12177d04a1cSJeremy L Thompson 
12277d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
12377d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
12477d04a1cSJeremy L Thompson 
12577d04a1cSJeremy L Thompson   if (!impl->array_allocated) CeedCallBackend(CeedVectorSetArray_Memcheck(vec, CEED_MEM_HOST, CEED_COPY_VALUES, NULL));
12677d04a1cSJeremy L Thompson   assert(impl->array_allocated);
12777d04a1cSJeremy L Thompson   for (CeedSize i = start; i < length; i += step) impl->array_allocated[i] = val;
12877d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
12977d04a1cSJeremy L Thompson }
13077d04a1cSJeremy L Thompson 
13177d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
1329937a20eSJeremy L Thompson // Sync arrays
1339937a20eSJeremy L Thompson //------------------------------------------------------------------------------
1349937a20eSJeremy L Thompson static int CeedVectorSyncArray_Memcheck(const CeedVector vec, CeedMemType mem_type) {
1359937a20eSJeremy L Thompson   CeedSize             length;
1369937a20eSJeremy L Thompson   CeedVector_Memcheck *impl;
1379937a20eSJeremy L Thompson 
1389937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
1399937a20eSJeremy L Thompson 
1409937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
1419937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
1429937a20eSJeremy L Thompson 
1439937a20eSJeremy L Thompson   // Copy internal buffer back to owned or borrowed array
1449937a20eSJeremy L Thompson   if (impl->array_owned) {
1459937a20eSJeremy L Thompson     memcpy(impl->array_owned, impl->array_allocated, length * sizeof(CeedScalar));
1469937a20eSJeremy L Thompson   }
1479937a20eSJeremy L Thompson   if (impl->array_borrowed) {
1489937a20eSJeremy L Thompson     memcpy(impl->array_borrowed, impl->array_allocated, length * sizeof(CeedScalar));
1499937a20eSJeremy L Thompson   }
1509798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1519798701eSJeremy L Thompson }
1529798701eSJeremy L Thompson 
1539798701eSJeremy L Thompson //------------------------------------------------------------------------------
1549798701eSJeremy L Thompson // Vector Take Array
1559798701eSJeremy L Thompson //------------------------------------------------------------------------------
1569798701eSJeremy L Thompson static int CeedVectorTakeArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) {
157d1931fc8SJeremy L Thompson   CeedSize             length;
158ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
159ad70ee2cSJeremy L Thompson 
1609937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
1619937a20eSJeremy L Thompson 
162ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
163d1931fc8SJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
1649798701eSJeremy L Thompson 
1659937a20eSJeremy L Thompson   // Synchronize memory
1669937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorSyncArray_Memcheck(vec, CEED_MEM_HOST));
1679798701eSJeremy L Thompson 
1689937a20eSJeremy L Thompson   // Return borrowed array
1699798701eSJeremy L Thompson   (*array)             = impl->array_borrowed;
1709798701eSJeremy L Thompson   impl->array_borrowed = NULL;
1719937a20eSJeremy L Thompson   VALGRIND_DISCARD(impl->borrowed_block_id);
1729937a20eSJeremy L Thompson 
1739937a20eSJeremy L Thompson   // De-allocate internal memory
174d1931fc8SJeremy L Thompson   if (impl->array_allocated) {
175d1931fc8SJeremy L Thompson     for (CeedSize i = 0; i < length; i++) impl->array_allocated[i] = NAN;
1760307dd02SJeremy L Thompson     VALGRIND_DISCARD(impl->allocated_block_id);
177d1931fc8SJeremy L Thompson   }
1789798701eSJeremy L Thompson   CeedCallBackend(CeedFree(&impl->array_allocated));
1799798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1809798701eSJeremy L Thompson }
1819798701eSJeremy L Thompson 
1829798701eSJeremy L Thompson //------------------------------------------------------------------------------
1839798701eSJeremy L Thompson // Vector Get Array
1849798701eSJeremy L Thompson //------------------------------------------------------------------------------
1859798701eSJeremy L Thompson static int CeedVectorGetArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) {
1861a3e18b3SJeremy L Thompson   CeedSize             length;
187ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
188ad70ee2cSJeremy L Thompson 
1899937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
1909937a20eSJeremy L Thompson 
191ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
1921a3e18b3SJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
1939798701eSJeremy L Thompson 
1949937a20eSJeremy L Thompson   // Create and return writable buffer
1951a3e18b3SJeremy L Thompson   CeedCallBackend(CeedCalloc(length, &impl->array_writable_copy));
1969937a20eSJeremy L Thompson   impl->writable_block_id = VALGRIND_CREATE_BLOCK(impl->array_writable_copy, length * sizeof(CeedScalar), "Allocated writeable array buffer copy");
1979937a20eSJeremy L Thompson   memcpy(impl->array_writable_copy, impl->array_allocated, length * sizeof(CeedScalar));
1981a3e18b3SJeremy L Thompson   *array = impl->array_writable_copy;
1999798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
2009798701eSJeremy L Thompson }
2019798701eSJeremy L Thompson 
2029798701eSJeremy L Thompson //------------------------------------------------------------------------------
2039798701eSJeremy L Thompson // Vector Get Array Read
2049798701eSJeremy L Thompson //------------------------------------------------------------------------------
2059798701eSJeremy L Thompson static int CeedVectorGetArrayRead_Memcheck(CeedVector vec, CeedMemType mem_type, const CeedScalar **array) {
206ad70ee2cSJeremy L Thompson   CeedSize             length;
207ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
208ad70ee2cSJeremy L Thompson 
2099937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
2109937a20eSJeremy L Thompson 
211ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
212ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
2139798701eSJeremy L Thompson 
2149937a20eSJeremy L Thompson   // Create and return read-only buffer
2155b5dc0c8SJeremy L Thompson   if (!impl->array_read_only_copy) {
2169798701eSJeremy L Thompson     CeedCallBackend(CeedCalloc(length, &impl->array_read_only_copy));
2179937a20eSJeremy L Thompson     impl->writable_block_id = VALGRIND_CREATE_BLOCK(impl->array_read_only_copy, length * sizeof(CeedScalar), "Allocated read-only array buffer copy");
2189937a20eSJeremy L Thompson     memcpy(impl->array_read_only_copy, impl->array_allocated, length * sizeof(CeedScalar));
2195b5dc0c8SJeremy L Thompson   }
220d1931fc8SJeremy L Thompson   *array = impl->array_read_only_copy;
2219798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
2229798701eSJeremy L Thompson }
2239798701eSJeremy L Thompson 
2249798701eSJeremy L Thompson //------------------------------------------------------------------------------
2259798701eSJeremy L Thompson // Vector Get Array Write
2269798701eSJeremy L Thompson //------------------------------------------------------------------------------
2279798701eSJeremy L Thompson static int CeedVectorGetArrayWrite_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) {
228ad70ee2cSJeremy L Thompson   CeedSize             length;
229ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
230ad70ee2cSJeremy L Thompson 
2319937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
2329937a20eSJeremy L Thompson 
233ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
234ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
2359798701eSJeremy L Thompson 
2369937a20eSJeremy L Thompson   // Allocate buffer if necessary
2379937a20eSJeremy L Thompson   if (!impl->array_allocated) CeedCallBackend(CeedVectorSetArray_Memcheck(vec, mem_type, CEED_COPY_VALUES, NULL));
2389937a20eSJeremy L Thompson 
2399937a20eSJeremy L Thompson   // Get writable buffer
2409798701eSJeremy L Thompson   CeedCallBackend(CeedVectorGetArray_Memcheck(vec, mem_type, array));
2419937a20eSJeremy L Thompson 
2429937a20eSJeremy L Thompson   // Invalidate array data to prevent accidental reads
243dd39767dSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) (*array)[i] = NAN;
244df852985SJeremy L Thompson   impl->is_write_only_access = true;
2459798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
2469798701eSJeremy L Thompson }
2479798701eSJeremy L Thompson 
2489798701eSJeremy L Thompson //------------------------------------------------------------------------------
2499798701eSJeremy L Thompson // Vector Restore Array
2509798701eSJeremy L Thompson //------------------------------------------------------------------------------
2519798701eSJeremy L Thompson static int CeedVectorRestoreArray_Memcheck(CeedVector vec) {
252ad70ee2cSJeremy L Thompson   CeedSize             length;
253ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
254ad70ee2cSJeremy L Thompson 
255ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
256ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
2579798701eSJeremy L Thompson 
2589937a20eSJeremy L Thompson   // Check for unset entries after write-only access
259df852985SJeremy L Thompson   if (impl->is_write_only_access) {
260dd39767dSJeremy L Thompson     for (CeedSize i = 0; i < length; i++) {
2616c10af5dSJeremy L Thompson       if (isnan(impl->array_writable_copy[i])) {
2629bc66399SJeremy L Thompson         CeedDebug256(CeedVectorReturnCeed(vec), CEED_DEBUG_COLOR_WARNING,
2639bc66399SJeremy L Thompson                      "WARNING: Vec entry %" CeedSize_FMT " is NaN after restoring write-only access", i);
264df852985SJeremy L Thompson       }
2656c10af5dSJeremy L Thompson     }
266df852985SJeremy L Thompson     impl->is_write_only_access = false;
267df852985SJeremy L Thompson   }
2689937a20eSJeremy L Thompson 
2699937a20eSJeremy L Thompson   // Copy back to internal buffer and sync
2709937a20eSJeremy L Thompson   memcpy(impl->array_allocated, impl->array_writable_copy, length * sizeof(CeedScalar));
2719937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorSyncArray_Memcheck(vec, CEED_MEM_HOST));
2729937a20eSJeremy L Thompson 
2739937a20eSJeremy L Thompson   // Invalidate writable buffer
2749937a20eSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl->array_writable_copy[i] = NAN;
2759937a20eSJeremy L Thompson   CeedCallBackend(CeedFree(&impl->array_writable_copy));
2769937a20eSJeremy L Thompson   VALGRIND_DISCARD(impl->writable_block_id);
2779798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
2789798701eSJeremy L Thompson }
2799798701eSJeremy L Thompson 
2809798701eSJeremy L Thompson //------------------------------------------------------------------------------
2819798701eSJeremy L Thompson // Vector Restore Array Read-Only
2829798701eSJeremy L Thompson //------------------------------------------------------------------------------
2839798701eSJeremy L Thompson static int CeedVectorRestoreArrayRead_Memcheck(CeedVector vec) {
284ad70ee2cSJeremy L Thompson   CeedSize             length;
285ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
286ad70ee2cSJeremy L Thompson 
287ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
288ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
2899798701eSJeremy L Thompson 
2909937a20eSJeremy L Thompson   // Verify no changes made during read-only access
2919937a20eSJeremy L Thompson   bool is_changed = memcmp(impl->array_allocated, impl->array_read_only_copy, length * sizeof(CeedScalar));
2929798701eSJeremy L Thompson 
2939bc66399SJeremy L Thompson   CeedCheck(!is_changed, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Array data changed while accessed in read-only mode");
2949937a20eSJeremy L Thompson 
2959937a20eSJeremy L Thompson   // Invalidate read-only buffer
296d1931fc8SJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl->array_read_only_copy[i] = NAN;
2979798701eSJeremy L Thompson   CeedCallBackend(CeedFree(&impl->array_read_only_copy));
2989937a20eSJeremy L Thompson   VALGRIND_DISCARD(impl->read_only_block_id);
2999798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
3009798701eSJeremy L Thompson }
3019798701eSJeremy L Thompson 
3029798701eSJeremy L Thompson //------------------------------------------------------------------------------
30377d04a1cSJeremy L Thompson // Take reciprocal of a vector
30477d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
30577d04a1cSJeremy L Thompson static int CeedVectorReciprocal_Memcheck(CeedVector vec) {
30677d04a1cSJeremy L Thompson   CeedSize             length;
30777d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl;
30877d04a1cSJeremy L Thompson 
30977d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
31077d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
31177d04a1cSJeremy L Thompson 
31277d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) {
31377d04a1cSJeremy L Thompson     if (fabs(impl->array_allocated[i]) > CEED_EPSILON) impl->array_allocated[i] = 1. / impl->array_allocated[i];
31477d04a1cSJeremy L Thompson   }
31577d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
31677d04a1cSJeremy L Thompson }
31777d04a1cSJeremy L Thompson 
31877d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
31977d04a1cSJeremy L Thompson // Compute x = alpha x
32077d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
32177d04a1cSJeremy L Thompson static int CeedVectorScale_Memcheck(CeedVector x, CeedScalar alpha) {
32277d04a1cSJeremy L Thompson   CeedSize             length;
32377d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl;
32477d04a1cSJeremy L Thompson 
32577d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl));
32677d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(x, &length));
32777d04a1cSJeremy L Thompson 
32877d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl->array_allocated[i] *= alpha;
32977d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
33077d04a1cSJeremy L Thompson }
33177d04a1cSJeremy L Thompson 
33277d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
33377d04a1cSJeremy L Thompson // Compute y = alpha x + y
33477d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
33577d04a1cSJeremy L Thompson static int CeedVectorAXPY_Memcheck(CeedVector y, CeedScalar alpha, CeedVector x) {
33677d04a1cSJeremy L Thompson   CeedSize             length;
33777d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl_x, *impl_y;
33877d04a1cSJeremy L Thompson 
33977d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl_x));
34077d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(y, &impl_y));
34177d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(y, &length));
34277d04a1cSJeremy L Thompson 
34377d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl_y->array_allocated[i] += alpha * impl_x->array_allocated[i];
34477d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
34577d04a1cSJeremy L Thompson }
34677d04a1cSJeremy L Thompson 
34777d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
34877d04a1cSJeremy L Thompson // Compute y = alpha x + beta y
34977d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
35077d04a1cSJeremy L Thompson static int CeedVectorAXPBY_Memcheck(CeedVector y, CeedScalar alpha, CeedScalar beta, CeedVector x) {
35177d04a1cSJeremy L Thompson   CeedSize             length;
35277d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl_x, *impl_y;
35377d04a1cSJeremy L Thompson 
35477d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl_x));
35577d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(y, &impl_y));
35677d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(y, &length));
35777d04a1cSJeremy L Thompson 
35877d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl_y->array_allocated[i] = alpha * impl_x->array_allocated[i] + beta * impl_y->array_allocated[i];
35977d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
36077d04a1cSJeremy L Thompson }
36177d04a1cSJeremy L Thompson 
36277d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
36377d04a1cSJeremy L Thompson // Compute the pointwise multiplication w = x .* y
36477d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
36577d04a1cSJeremy L Thompson static int CeedVectorPointwiseMult_Memcheck(CeedVector w, CeedVector x, CeedVector y) {
36677d04a1cSJeremy L Thompson   CeedSize             length;
36777d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl_x, *impl_y, *impl_w;
36877d04a1cSJeremy L Thompson 
36977d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl_x));
37077d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(y, &impl_y));
37177d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(w, &impl_w));
37277d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(w, &length));
37377d04a1cSJeremy L Thompson 
37477d04a1cSJeremy L Thompson   if (!impl_w->array_allocated) CeedCallBackend(CeedVectorSetArray_Memcheck(w, CEED_MEM_HOST, CEED_COPY_VALUES, NULL));
37577d04a1cSJeremy L Thompson   assert(impl_w->array_allocated);
37677d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl_w->array_allocated[i] = impl_x->array_allocated[i] * impl_y->array_allocated[i];
37777d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
37877d04a1cSJeremy L Thompson }
37977d04a1cSJeremy L Thompson 
38077d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
3819798701eSJeremy L Thompson // Vector Destroy
3829798701eSJeremy L Thompson //------------------------------------------------------------------------------
3839798701eSJeremy L Thompson static int CeedVectorDestroy_Memcheck(CeedVector vec) {
3849798701eSJeremy L Thompson   CeedVector_Memcheck *impl;
3859798701eSJeremy L Thompson 
3869937a20eSJeremy L Thompson   // Free allocations and discard block ids
387ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
3889937a20eSJeremy L Thompson   if (impl->array_allocated) {
3899798701eSJeremy L Thompson     CeedCallBackend(CeedFree(&impl->array_allocated));
3909937a20eSJeremy L Thompson     VALGRIND_DISCARD(impl->allocated_block_id);
3919937a20eSJeremy L Thompson   }
3929937a20eSJeremy L Thompson   if (impl->array_owned) {
3939798701eSJeremy L Thompson     CeedCallBackend(CeedFree(&impl->array_owned));
3949937a20eSJeremy L Thompson     VALGRIND_DISCARD(impl->owned_block_id);
3959937a20eSJeremy L Thompson   }
3969937a20eSJeremy L Thompson   if (impl->array_borrowed) {
3979937a20eSJeremy L Thompson     VALGRIND_DISCARD(impl->borrowed_block_id);
3989937a20eSJeremy L Thompson   }
3999798701eSJeremy L Thompson   CeedCallBackend(CeedFree(&impl));
4009798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
4019798701eSJeremy L Thompson }
4029798701eSJeremy L Thompson 
4039798701eSJeremy L Thompson //------------------------------------------------------------------------------
4049798701eSJeremy L Thompson // Vector Create
4059798701eSJeremy L Thompson //------------------------------------------------------------------------------
4069798701eSJeremy L Thompson int CeedVectorCreate_Memcheck(CeedSize n, CeedVector vec) {
4079798701eSJeremy L Thompson   Ceed                 ceed;
408ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
4099798701eSJeremy L Thompson 
410ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetCeed(vec, &ceed));
4119798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "HasValidArray", CeedVectorHasValidArray_Memcheck));
4129798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "HasBorrowedArrayOfType", CeedVectorHasBorrowedArrayOfType_Memcheck));
4139798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SetArray", CeedVectorSetArray_Memcheck));
41477d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SetValue", CeedVectorSetValue_Memcheck));
41577d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SetValueStrided", CeedVectorSetValueStrided_Memcheck));
4169937a20eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SyncArray", CeedVectorSyncArray_Memcheck));
4179798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "TakeArray", CeedVectorTakeArray_Memcheck));
4189798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArray", CeedVectorGetArray_Memcheck));
4199798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayRead", CeedVectorGetArrayRead_Memcheck));
4209798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayWrite", CeedVectorGetArrayWrite_Memcheck));
4219798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArray", CeedVectorRestoreArray_Memcheck));
4229798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArrayRead", CeedVectorRestoreArrayRead_Memcheck));
42377d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "Reciprocal", CeedVectorReciprocal_Memcheck));
42477d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "Scale", CeedVectorScale_Memcheck));
42577d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "AXPY", CeedVectorAXPY_Memcheck));
42677d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "AXPBY", CeedVectorAXPBY_Memcheck));
42777d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "PointwiseMult", CeedVectorPointwiseMult_Memcheck));
4289798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "Destroy", CeedVectorDestroy_Memcheck));
4299bc66399SJeremy L Thompson   CeedCallBackend(CeedDestroy(&ceed));
4309bc66399SJeremy L Thompson   CeedCallBackend(CeedCalloc(1, &impl));
4319bc66399SJeremy L Thompson   CeedCallBackend(CeedVectorSetData(vec, impl));
4329798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
4339798701eSJeremy L Thompson }
4342a86cc9dSSebastian Grimberg 
4359798701eSJeremy L Thompson //------------------------------------------------------------------------------
436