xref: /libCEED/rust/libceed-sys/c-src/backends/memcheck/ceed-memcheck-vector.c (revision 77d04a1cd52f4bd525fc353da4f86cac2faab0fe)
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>
10*77d04a1cSJeremy 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));
60d1931fc8SJeremy L Thompson   if (impl->array_owned) {
61d1931fc8SJeremy L Thompson     for (CeedSize i = 0; i < length; i++) impl->array_owned[i] = NAN;
629937a20eSJeremy L Thompson     VALGRIND_DISCARD(impl->owned_block_id);
630307dd02SJeremy L Thompson   }
649798701eSJeremy L Thompson   CeedCallBackend(CeedFree(&impl->array_owned));
659937a20eSJeremy L Thompson 
669937a20eSJeremy L Thompson   // Clear borrowed block id, if present
679937a20eSJeremy L Thompson   if (impl->array_borrowed) VALGRIND_DISCARD(impl->borrowed_block_id);
689937a20eSJeremy L Thompson 
699937a20eSJeremy L Thompson   // Set internal pointers to external arrays
709798701eSJeremy L Thompson   switch (copy_mode) {
719798701eSJeremy L Thompson     case CEED_COPY_VALUES:
729937a20eSJeremy L Thompson       impl->array_owned    = NULL;
739798701eSJeremy L Thompson       impl->array_borrowed = NULL;
749798701eSJeremy L Thompson       break;
759798701eSJeremy L Thompson     case CEED_OWN_POINTER:
769798701eSJeremy L Thompson       impl->array_owned    = array;
779798701eSJeremy L Thompson       impl->array_borrowed = NULL;
789937a20eSJeremy L Thompson       impl->owned_block_id = VALGRIND_CREATE_BLOCK(impl->array_owned, length * sizeof(CeedScalar), "Owned external array buffer");
799798701eSJeremy L Thompson       break;
809798701eSJeremy L Thompson     case CEED_USE_POINTER:
819937a20eSJeremy L Thompson       impl->array_owned       = NULL;
829798701eSJeremy L Thompson       impl->array_borrowed    = array;
839937a20eSJeremy L Thompson       impl->borrowed_block_id = VALGRIND_CREATE_BLOCK(impl->array_borrowed, length * sizeof(CeedScalar), "Borrowed external array buffer");
849937a20eSJeremy L Thompson       break;
859798701eSJeremy L Thompson   }
869937a20eSJeremy L Thompson 
879937a20eSJeremy L Thompson   // Create internal array data buffer
889798701eSJeremy L Thompson   CeedCallBackend(CeedCalloc(length, &impl->array_allocated));
899937a20eSJeremy L Thompson   impl->allocated_block_id = VALGRIND_CREATE_BLOCK(impl->array_allocated, length * sizeof(CeedScalar), "Allocated internal array buffer");
909937a20eSJeremy L Thompson   if (array) {
919937a20eSJeremy L Thompson     memcpy(impl->array_allocated, array, length * sizeof(CeedScalar));
929937a20eSJeremy L Thompson   } else {
939937a20eSJeremy L Thompson     for (CeedInt i = 0; i < length; i++) impl->array_allocated[i] = NAN;
949937a20eSJeremy L Thompson   }
959937a20eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
969937a20eSJeremy L Thompson }
979937a20eSJeremy L Thompson 
989937a20eSJeremy L Thompson //------------------------------------------------------------------------------
99*77d04a1cSJeremy L Thompson // Set internal array to value
100*77d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
101*77d04a1cSJeremy L Thompson static int CeedVectorSetValue_Memcheck(CeedVector vec, CeedScalar value) {
102*77d04a1cSJeremy L Thompson   CeedSize             length;
103*77d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl;
104*77d04a1cSJeremy L Thompson 
105*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
106*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
107*77d04a1cSJeremy L Thompson 
108*77d04a1cSJeremy L Thompson   if (!impl->array_allocated) CeedCallBackend(CeedVectorSetArray_Memcheck(vec, CEED_MEM_HOST, CEED_COPY_VALUES, NULL));
109*77d04a1cSJeremy L Thompson   assert(impl->array_allocated);
110*77d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl->array_allocated[i] = value;
111*77d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
112*77d04a1cSJeremy L Thompson }
113*77d04a1cSJeremy L Thompson 
114*77d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
115*77d04a1cSJeremy L Thompson // Set internal array to value strided
116*77d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
117*77d04a1cSJeremy L Thompson static int CeedVectorSetValueStrided_Memcheck(CeedVector vec, CeedSize start, CeedSize step, CeedScalar val) {
118*77d04a1cSJeremy L Thompson   CeedSize             length;
119*77d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl;
120*77d04a1cSJeremy L Thompson 
121*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
122*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
123*77d04a1cSJeremy L Thompson 
124*77d04a1cSJeremy L Thompson   if (!impl->array_allocated) CeedCallBackend(CeedVectorSetArray_Memcheck(vec, CEED_MEM_HOST, CEED_COPY_VALUES, NULL));
125*77d04a1cSJeremy L Thompson   assert(impl->array_allocated);
126*77d04a1cSJeremy L Thompson   for (CeedSize i = start; i < length; i += step) impl->array_allocated[i] = val;
127*77d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
128*77d04a1cSJeremy L Thompson }
129*77d04a1cSJeremy L Thompson 
130*77d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
1319937a20eSJeremy L Thompson // Sync arrays
1329937a20eSJeremy L Thompson //------------------------------------------------------------------------------
1339937a20eSJeremy L Thompson static int CeedVectorSyncArray_Memcheck(const CeedVector vec, CeedMemType mem_type) {
1349937a20eSJeremy L Thompson   CeedSize             length;
1359937a20eSJeremy L Thompson   CeedVector_Memcheck *impl;
1369937a20eSJeremy L Thompson 
1379937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
1389937a20eSJeremy L Thompson 
1399937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
1409937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
1419937a20eSJeremy L Thompson 
1429937a20eSJeremy L Thompson   // Copy internal buffer back to owned or borrowed array
1439937a20eSJeremy L Thompson   if (impl->array_owned) {
1449937a20eSJeremy L Thompson     memcpy(impl->array_owned, impl->array_allocated, length * sizeof(CeedScalar));
1459937a20eSJeremy L Thompson   }
1469937a20eSJeremy L Thompson   if (impl->array_borrowed) {
1479937a20eSJeremy L Thompson     memcpy(impl->array_borrowed, impl->array_allocated, length * sizeof(CeedScalar));
1489937a20eSJeremy L Thompson   }
1499798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1509798701eSJeremy L Thompson }
1519798701eSJeremy L Thompson 
1529798701eSJeremy L Thompson //------------------------------------------------------------------------------
1539798701eSJeremy L Thompson // Vector Take Array
1549798701eSJeremy L Thompson //------------------------------------------------------------------------------
1559798701eSJeremy L Thompson static int CeedVectorTakeArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) {
156d1931fc8SJeremy L Thompson   CeedSize             length;
157ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
158ad70ee2cSJeremy L Thompson 
1599937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
1609937a20eSJeremy L Thompson 
161ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
162d1931fc8SJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
1639798701eSJeremy L Thompson 
1649937a20eSJeremy L Thompson   // Synchronize memory
1659937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorSyncArray_Memcheck(vec, CEED_MEM_HOST));
1669798701eSJeremy L Thompson 
1679937a20eSJeremy L Thompson   // Return borrowed array
1689798701eSJeremy L Thompson   (*array)             = impl->array_borrowed;
1699798701eSJeremy L Thompson   impl->array_borrowed = NULL;
1709937a20eSJeremy L Thompson   VALGRIND_DISCARD(impl->borrowed_block_id);
1719937a20eSJeremy L Thompson 
1729937a20eSJeremy L Thompson   // De-allocate internal memory
173d1931fc8SJeremy L Thompson   if (impl->array_allocated) {
174d1931fc8SJeremy L Thompson     for (CeedSize i = 0; i < length; i++) impl->array_allocated[i] = NAN;
1750307dd02SJeremy L Thompson     VALGRIND_DISCARD(impl->allocated_block_id);
176d1931fc8SJeremy L Thompson   }
1779798701eSJeremy L Thompson   CeedCallBackend(CeedFree(&impl->array_allocated));
1789798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1799798701eSJeremy L Thompson }
1809798701eSJeremy L Thompson 
1819798701eSJeremy L Thompson //------------------------------------------------------------------------------
1829798701eSJeremy L Thompson // Vector Get Array
1839798701eSJeremy L Thompson //------------------------------------------------------------------------------
1849798701eSJeremy L Thompson static int CeedVectorGetArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) {
1851a3e18b3SJeremy L Thompson   CeedSize             length;
186ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
187ad70ee2cSJeremy L Thompson 
1889937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
1899937a20eSJeremy L Thompson 
190ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
1911a3e18b3SJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
1929798701eSJeremy L Thompson 
1939937a20eSJeremy L Thompson   // Create and return writable buffer
1941a3e18b3SJeremy L Thompson   CeedCallBackend(CeedCalloc(length, &impl->array_writable_copy));
1959937a20eSJeremy L Thompson   impl->writable_block_id = VALGRIND_CREATE_BLOCK(impl->array_writable_copy, length * sizeof(CeedScalar), "Allocated writeable array buffer copy");
1969937a20eSJeremy L Thompson   memcpy(impl->array_writable_copy, impl->array_allocated, length * sizeof(CeedScalar));
1971a3e18b3SJeremy L Thompson   *array = impl->array_writable_copy;
1989798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1999798701eSJeremy L Thompson }
2009798701eSJeremy L Thompson 
2019798701eSJeremy L Thompson //------------------------------------------------------------------------------
2029798701eSJeremy L Thompson // Vector Get Array Read
2039798701eSJeremy L Thompson //------------------------------------------------------------------------------
2049798701eSJeremy L Thompson static int CeedVectorGetArrayRead_Memcheck(CeedVector vec, CeedMemType mem_type, const CeedScalar **array) {
205ad70ee2cSJeremy L Thompson   CeedSize             length;
206ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
207ad70ee2cSJeremy L Thompson 
2089937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
2099937a20eSJeremy L Thompson 
210ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
211ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
2129798701eSJeremy L Thompson 
2139937a20eSJeremy L Thompson   // Create and return read-only buffer
2145b5dc0c8SJeremy L Thompson   if (!impl->array_read_only_copy) {
2159798701eSJeremy L Thompson     CeedCallBackend(CeedCalloc(length, &impl->array_read_only_copy));
2169937a20eSJeremy L Thompson     impl->writable_block_id = VALGRIND_CREATE_BLOCK(impl->array_read_only_copy, length * sizeof(CeedScalar), "Allocated read-only array buffer copy");
2179937a20eSJeremy L Thompson     memcpy(impl->array_read_only_copy, impl->array_allocated, length * sizeof(CeedScalar));
2185b5dc0c8SJeremy L Thompson   }
219d1931fc8SJeremy L Thompson   *array = impl->array_read_only_copy;
2209798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
2219798701eSJeremy L Thompson }
2229798701eSJeremy L Thompson 
2239798701eSJeremy L Thompson //------------------------------------------------------------------------------
2249798701eSJeremy L Thompson // Vector Get Array Write
2259798701eSJeremy L Thompson //------------------------------------------------------------------------------
2269798701eSJeremy L Thompson static int CeedVectorGetArrayWrite_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) {
227ad70ee2cSJeremy L Thompson   CeedSize             length;
228ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
229ad70ee2cSJeremy L Thompson 
2309937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
2319937a20eSJeremy L Thompson 
232ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
233ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
2349798701eSJeremy L Thompson 
2359937a20eSJeremy L Thompson   // Allocate buffer if necessary
2369937a20eSJeremy L Thompson   if (!impl->array_allocated) CeedCallBackend(CeedVectorSetArray_Memcheck(vec, mem_type, CEED_COPY_VALUES, NULL));
2379937a20eSJeremy L Thompson 
2389937a20eSJeremy L Thompson   // Get writable buffer
2399798701eSJeremy L Thompson   CeedCallBackend(CeedVectorGetArray_Memcheck(vec, mem_type, array));
2409937a20eSJeremy L Thompson 
2419937a20eSJeremy L Thompson   // Invalidate array data to prevent accidental reads
242dd39767dSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) (*array)[i] = NAN;
243df852985SJeremy L Thompson   impl->is_write_only_access = true;
2449798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
2459798701eSJeremy L Thompson }
2469798701eSJeremy L Thompson 
2479798701eSJeremy L Thompson //------------------------------------------------------------------------------
2489798701eSJeremy L Thompson // Vector Restore Array
2499798701eSJeremy L Thompson //------------------------------------------------------------------------------
2509798701eSJeremy L Thompson static int CeedVectorRestoreArray_Memcheck(CeedVector vec) {
2519798701eSJeremy L Thompson   Ceed                 ceed;
252ad70ee2cSJeremy L Thompson   CeedSize             length;
253ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
254ad70ee2cSJeremy L Thompson 
2559937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorGetCeed(vec, &ceed));
256ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
257ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
2589798701eSJeremy L Thompson 
2599937a20eSJeremy L Thompson   // Check for unset entries after write-only access
260df852985SJeremy L Thompson   if (impl->is_write_only_access) {
261dd39767dSJeremy L Thompson     for (CeedSize i = 0; i < length; i++) {
2629937a20eSJeremy L Thompson       if (isnan(impl->array_writable_copy[i]))
263249f8407SJeremy L Thompson         CeedDebug256(ceed, CEED_DEBUG_COLOR_WARNING, "WARNING: Vec entry %" CeedSize_FMT " is NaN after restoring write-only access", i);
264df852985SJeremy L Thompson     }
265df852985SJeremy L Thompson     impl->is_write_only_access = false;
266df852985SJeremy L Thompson   }
2679937a20eSJeremy L Thompson 
2689937a20eSJeremy L Thompson   // Copy back to internal buffer and sync
2699937a20eSJeremy L Thompson   memcpy(impl->array_allocated, impl->array_writable_copy, length * sizeof(CeedScalar));
2709937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorSyncArray_Memcheck(vec, CEED_MEM_HOST));
2719937a20eSJeremy L Thompson 
2729937a20eSJeremy L Thompson   // Invalidate writable buffer
2739937a20eSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl->array_writable_copy[i] = NAN;
2749937a20eSJeremy L Thompson   CeedCallBackend(CeedFree(&impl->array_writable_copy));
2759937a20eSJeremy L Thompson   VALGRIND_DISCARD(impl->writable_block_id);
2769798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
2779798701eSJeremy L Thompson }
2789798701eSJeremy L Thompson 
2799798701eSJeremy L Thompson //------------------------------------------------------------------------------
2809798701eSJeremy L Thompson // Vector Restore Array Read-Only
2819798701eSJeremy L Thompson //------------------------------------------------------------------------------
2829798701eSJeremy L Thompson static int CeedVectorRestoreArrayRead_Memcheck(CeedVector vec) {
2839937a20eSJeremy L Thompson   Ceed                 ceed;
284ad70ee2cSJeremy L Thompson   CeedSize             length;
285ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
286ad70ee2cSJeremy L Thompson 
2879937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorGetCeed(vec, &ceed));
288ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
289ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
2909798701eSJeremy L Thompson 
2919937a20eSJeremy L Thompson   // Verify no changes made during read-only access
2929937a20eSJeremy L Thompson   bool is_changed = memcmp(impl->array_allocated, impl->array_read_only_copy, length * sizeof(CeedScalar));
2939798701eSJeremy L Thompson 
2949937a20eSJeremy L Thompson   CeedCheck(!is_changed, ceed, CEED_ERROR_BACKEND, "Array data changed while accessed in read-only mode");
2959937a20eSJeremy L Thompson 
2969937a20eSJeremy L Thompson   // Invalidate read-only buffer
297d1931fc8SJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl->array_read_only_copy[i] = NAN;
2989798701eSJeremy L Thompson   CeedCallBackend(CeedFree(&impl->array_read_only_copy));
2999937a20eSJeremy L Thompson   VALGRIND_DISCARD(impl->read_only_block_id);
3009798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
3019798701eSJeremy L Thompson }
3029798701eSJeremy L Thompson 
3039798701eSJeremy L Thompson //------------------------------------------------------------------------------
304*77d04a1cSJeremy L Thompson // Take reciprocal of a vector
305*77d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
306*77d04a1cSJeremy L Thompson static int CeedVectorReciprocal_Memcheck(CeedVector vec) {
307*77d04a1cSJeremy L Thompson   CeedSize             length;
308*77d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl;
309*77d04a1cSJeremy L Thompson 
310*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
311*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
312*77d04a1cSJeremy L Thompson 
313*77d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) {
314*77d04a1cSJeremy L Thompson     if (fabs(impl->array_allocated[i]) > CEED_EPSILON) impl->array_allocated[i] = 1. / impl->array_allocated[i];
315*77d04a1cSJeremy L Thompson   }
316*77d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
317*77d04a1cSJeremy L Thompson }
318*77d04a1cSJeremy L Thompson 
319*77d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
320*77d04a1cSJeremy L Thompson // Compute x = alpha x
321*77d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
322*77d04a1cSJeremy L Thompson static int CeedVectorScale_Memcheck(CeedVector x, CeedScalar alpha) {
323*77d04a1cSJeremy L Thompson   CeedSize             length;
324*77d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl;
325*77d04a1cSJeremy L Thompson 
326*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl));
327*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(x, &length));
328*77d04a1cSJeremy L Thompson 
329*77d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl->array_allocated[i] *= alpha;
330*77d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
331*77d04a1cSJeremy L Thompson }
332*77d04a1cSJeremy L Thompson 
333*77d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
334*77d04a1cSJeremy L Thompson // Compute y = alpha x + y
335*77d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
336*77d04a1cSJeremy L Thompson static int CeedVectorAXPY_Memcheck(CeedVector y, CeedScalar alpha, CeedVector x) {
337*77d04a1cSJeremy L Thompson   CeedSize             length;
338*77d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl_x, *impl_y;
339*77d04a1cSJeremy L Thompson 
340*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl_x));
341*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(y, &impl_y));
342*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(y, &length));
343*77d04a1cSJeremy L Thompson 
344*77d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl_y->array_allocated[i] += alpha * impl_x->array_allocated[i];
345*77d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
346*77d04a1cSJeremy L Thompson }
347*77d04a1cSJeremy L Thompson 
348*77d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
349*77d04a1cSJeremy L Thompson // Compute y = alpha x + beta y
350*77d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
351*77d04a1cSJeremy L Thompson static int CeedVectorAXPBY_Memcheck(CeedVector y, CeedScalar alpha, CeedScalar beta, CeedVector x) {
352*77d04a1cSJeremy L Thompson   CeedSize             length;
353*77d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl_x, *impl_y;
354*77d04a1cSJeremy L Thompson 
355*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl_x));
356*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(y, &impl_y));
357*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(y, &length));
358*77d04a1cSJeremy L Thompson 
359*77d04a1cSJeremy 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];
360*77d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
361*77d04a1cSJeremy L Thompson }
362*77d04a1cSJeremy L Thompson 
363*77d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
364*77d04a1cSJeremy L Thompson // Compute the pointwise multiplication w = x .* y
365*77d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
366*77d04a1cSJeremy L Thompson static int CeedVectorPointwiseMult_Memcheck(CeedVector w, CeedVector x, CeedVector y) {
367*77d04a1cSJeremy L Thompson   CeedSize             length;
368*77d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl_x, *impl_y, *impl_w;
369*77d04a1cSJeremy L Thompson 
370*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl_x));
371*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(y, &impl_y));
372*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(w, &impl_w));
373*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(w, &length));
374*77d04a1cSJeremy L Thompson 
375*77d04a1cSJeremy L Thompson   if (!impl_w->array_allocated) CeedCallBackend(CeedVectorSetArray_Memcheck(w, CEED_MEM_HOST, CEED_COPY_VALUES, NULL));
376*77d04a1cSJeremy L Thompson   assert(impl_w->array_allocated);
377*77d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl_w->array_allocated[i] = impl_x->array_allocated[i] * impl_y->array_allocated[i];
378*77d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
379*77d04a1cSJeremy L Thompson }
380*77d04a1cSJeremy L Thompson 
381*77d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
3829798701eSJeremy L Thompson // Vector Destroy
3839798701eSJeremy L Thompson //------------------------------------------------------------------------------
3849798701eSJeremy L Thompson static int CeedVectorDestroy_Memcheck(CeedVector vec) {
3859798701eSJeremy L Thompson   CeedVector_Memcheck *impl;
3869798701eSJeremy L Thompson 
3879937a20eSJeremy L Thompson   // Free allocations and discard block ids
388ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
3899937a20eSJeremy L Thompson   if (impl->array_allocated) {
3909798701eSJeremy L Thompson     CeedCallBackend(CeedFree(&impl->array_allocated));
3919937a20eSJeremy L Thompson     VALGRIND_DISCARD(impl->allocated_block_id);
3929937a20eSJeremy L Thompson   }
3939937a20eSJeremy L Thompson   if (impl->array_owned) {
3949798701eSJeremy L Thompson     CeedCallBackend(CeedFree(&impl->array_owned));
3959937a20eSJeremy L Thompson     VALGRIND_DISCARD(impl->owned_block_id);
3969937a20eSJeremy L Thompson   }
3979937a20eSJeremy L Thompson   if (impl->array_borrowed) {
3989937a20eSJeremy L Thompson     VALGRIND_DISCARD(impl->borrowed_block_id);
3999937a20eSJeremy L Thompson   }
4009798701eSJeremy L Thompson   CeedCallBackend(CeedFree(&impl));
4019798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
4029798701eSJeremy L Thompson }
4039798701eSJeremy L Thompson 
4049798701eSJeremy L Thompson //------------------------------------------------------------------------------
4059798701eSJeremy L Thompson // Vector Create
4069798701eSJeremy L Thompson //------------------------------------------------------------------------------
4079798701eSJeremy L Thompson int CeedVectorCreate_Memcheck(CeedSize n, CeedVector vec) {
4089798701eSJeremy L Thompson   Ceed                 ceed;
409ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
4109798701eSJeremy L Thompson 
4119e82028bSJeremy L Thompson   CeedCallBackend(CeedCalloc(1, &impl));
4129e82028bSJeremy L Thompson   CeedCallBackend(CeedVectorSetData(vec, impl));
4139e82028bSJeremy L Thompson 
414ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetCeed(vec, &ceed));
4159798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "HasValidArray", CeedVectorHasValidArray_Memcheck));
4169798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "HasBorrowedArrayOfType", CeedVectorHasBorrowedArrayOfType_Memcheck));
4179798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SetArray", CeedVectorSetArray_Memcheck));
418*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SetValue", CeedVectorSetValue_Memcheck));
419*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SetValueStrided", CeedVectorSetValueStrided_Memcheck));
4209937a20eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SyncArray", CeedVectorSyncArray_Memcheck));
4219798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "TakeArray", CeedVectorTakeArray_Memcheck));
4229798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArray", CeedVectorGetArray_Memcheck));
4239798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayRead", CeedVectorGetArrayRead_Memcheck));
4249798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayWrite", CeedVectorGetArrayWrite_Memcheck));
4259798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArray", CeedVectorRestoreArray_Memcheck));
4269798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArrayRead", CeedVectorRestoreArrayRead_Memcheck));
427*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "Reciprocal", CeedVectorReciprocal_Memcheck));
428*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "Scale", CeedVectorScale_Memcheck));
429*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "AXPY", CeedVectorAXPY_Memcheck));
430*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "AXPBY", CeedVectorAXPBY_Memcheck));
431*77d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "PointwiseMult", CeedVectorPointwiseMult_Memcheck));
4329798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "Destroy", CeedVectorDestroy_Memcheck));
4339798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
4349798701eSJeremy L Thompson }
4352a86cc9dSSebastian Grimberg 
4369798701eSJeremy L Thompson //------------------------------------------------------------------------------
437