xref: /libCEED/rust/libceed-sys/c-src/backends/memcheck/ceed-memcheck-vector.c (revision 6c10af5d44be86c880e303f5037addb2f5724932)
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));
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 //------------------------------------------------------------------------------
9977d04a1cSJeremy L Thompson // Set internal array to value
10077d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
10177d04a1cSJeremy L Thompson static int CeedVectorSetValue_Memcheck(CeedVector vec, CeedScalar value) {
10277d04a1cSJeremy L Thompson   CeedSize             length;
10377d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl;
10477d04a1cSJeremy L Thompson 
10577d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
10677d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
10777d04a1cSJeremy L Thompson 
10877d04a1cSJeremy L Thompson   if (!impl->array_allocated) CeedCallBackend(CeedVectorSetArray_Memcheck(vec, CEED_MEM_HOST, CEED_COPY_VALUES, NULL));
10977d04a1cSJeremy L Thompson   assert(impl->array_allocated);
11077d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl->array_allocated[i] = value;
11177d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
11277d04a1cSJeremy L Thompson }
11377d04a1cSJeremy L Thompson 
11477d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
11577d04a1cSJeremy L Thompson // Set internal array to value strided
11677d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
11777d04a1cSJeremy L Thompson static int CeedVectorSetValueStrided_Memcheck(CeedVector vec, CeedSize start, CeedSize step, CeedScalar val) {
11877d04a1cSJeremy L Thompson   CeedSize             length;
11977d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl;
12077d04a1cSJeremy L Thompson 
12177d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
12277d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
12377d04a1cSJeremy L Thompson 
12477d04a1cSJeremy L Thompson   if (!impl->array_allocated) CeedCallBackend(CeedVectorSetArray_Memcheck(vec, CEED_MEM_HOST, CEED_COPY_VALUES, NULL));
12577d04a1cSJeremy L Thompson   assert(impl->array_allocated);
12677d04a1cSJeremy L Thompson   for (CeedSize i = start; i < length; i += step) impl->array_allocated[i] = val;
12777d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
12877d04a1cSJeremy L Thompson }
12977d04a1cSJeremy L Thompson 
13077d04a1cSJeremy 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++) {
262*6c10af5dSJeremy 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       }
265*6c10af5dSJeremy 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) {
2849937a20eSJeremy L Thompson   Ceed                 ceed;
285ad70ee2cSJeremy L Thompson   CeedSize             length;
286ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
287ad70ee2cSJeremy L Thompson 
2889937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorGetCeed(vec, &ceed));
289ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
290ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
2919798701eSJeremy L Thompson 
2929937a20eSJeremy L Thompson   // Verify no changes made during read-only access
2939937a20eSJeremy L Thompson   bool is_changed = memcmp(impl->array_allocated, impl->array_read_only_copy, length * sizeof(CeedScalar));
2949798701eSJeremy L Thompson 
2959937a20eSJeremy L Thompson   CeedCheck(!is_changed, ceed, CEED_ERROR_BACKEND, "Array data changed while accessed in read-only mode");
2969937a20eSJeremy L Thompson 
2979937a20eSJeremy L Thompson   // Invalidate read-only buffer
298d1931fc8SJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl->array_read_only_copy[i] = NAN;
2999798701eSJeremy L Thompson   CeedCallBackend(CeedFree(&impl->array_read_only_copy));
3009937a20eSJeremy L Thompson   VALGRIND_DISCARD(impl->read_only_block_id);
3019798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
3029798701eSJeremy L Thompson }
3039798701eSJeremy L Thompson 
3049798701eSJeremy L Thompson //------------------------------------------------------------------------------
30577d04a1cSJeremy L Thompson // Take reciprocal of a vector
30677d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
30777d04a1cSJeremy L Thompson static int CeedVectorReciprocal_Memcheck(CeedVector vec) {
30877d04a1cSJeremy L Thompson   CeedSize             length;
30977d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl;
31077d04a1cSJeremy L Thompson 
31177d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
31277d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
31377d04a1cSJeremy L Thompson 
31477d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) {
31577d04a1cSJeremy L Thompson     if (fabs(impl->array_allocated[i]) > CEED_EPSILON) impl->array_allocated[i] = 1. / impl->array_allocated[i];
31677d04a1cSJeremy L Thompson   }
31777d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
31877d04a1cSJeremy L Thompson }
31977d04a1cSJeremy L Thompson 
32077d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
32177d04a1cSJeremy L Thompson // Compute x = alpha x
32277d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
32377d04a1cSJeremy L Thompson static int CeedVectorScale_Memcheck(CeedVector x, CeedScalar alpha) {
32477d04a1cSJeremy L Thompson   CeedSize             length;
32577d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl;
32677d04a1cSJeremy L Thompson 
32777d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl));
32877d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(x, &length));
32977d04a1cSJeremy L Thompson 
33077d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl->array_allocated[i] *= alpha;
33177d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
33277d04a1cSJeremy L Thompson }
33377d04a1cSJeremy L Thompson 
33477d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
33577d04a1cSJeremy L Thompson // Compute y = alpha x + y
33677d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
33777d04a1cSJeremy L Thompson static int CeedVectorAXPY_Memcheck(CeedVector y, CeedScalar alpha, CeedVector x) {
33877d04a1cSJeremy L Thompson   CeedSize             length;
33977d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl_x, *impl_y;
34077d04a1cSJeremy L Thompson 
34177d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl_x));
34277d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(y, &impl_y));
34377d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(y, &length));
34477d04a1cSJeremy L Thompson 
34577d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl_y->array_allocated[i] += alpha * impl_x->array_allocated[i];
34677d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
34777d04a1cSJeremy L Thompson }
34877d04a1cSJeremy L Thompson 
34977d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
35077d04a1cSJeremy L Thompson // Compute y = alpha x + beta y
35177d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
35277d04a1cSJeremy L Thompson static int CeedVectorAXPBY_Memcheck(CeedVector y, CeedScalar alpha, CeedScalar beta, CeedVector x) {
35377d04a1cSJeremy L Thompson   CeedSize             length;
35477d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl_x, *impl_y;
35577d04a1cSJeremy L Thompson 
35677d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl_x));
35777d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(y, &impl_y));
35877d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(y, &length));
35977d04a1cSJeremy L Thompson 
36077d04a1cSJeremy 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];
36177d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
36277d04a1cSJeremy L Thompson }
36377d04a1cSJeremy L Thompson 
36477d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
36577d04a1cSJeremy L Thompson // Compute the pointwise multiplication w = x .* y
36677d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
36777d04a1cSJeremy L Thompson static int CeedVectorPointwiseMult_Memcheck(CeedVector w, CeedVector x, CeedVector y) {
36877d04a1cSJeremy L Thompson   CeedSize             length;
36977d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl_x, *impl_y, *impl_w;
37077d04a1cSJeremy L Thompson 
37177d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl_x));
37277d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(y, &impl_y));
37377d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(w, &impl_w));
37477d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(w, &length));
37577d04a1cSJeremy L Thompson 
37677d04a1cSJeremy L Thompson   if (!impl_w->array_allocated) CeedCallBackend(CeedVectorSetArray_Memcheck(w, CEED_MEM_HOST, CEED_COPY_VALUES, NULL));
37777d04a1cSJeremy L Thompson   assert(impl_w->array_allocated);
37877d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl_w->array_allocated[i] = impl_x->array_allocated[i] * impl_y->array_allocated[i];
37977d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
38077d04a1cSJeremy L Thompson }
38177d04a1cSJeremy L Thompson 
38277d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
3839798701eSJeremy L Thompson // Vector Destroy
3849798701eSJeremy L Thompson //------------------------------------------------------------------------------
3859798701eSJeremy L Thompson static int CeedVectorDestroy_Memcheck(CeedVector vec) {
3869798701eSJeremy L Thompson   CeedVector_Memcheck *impl;
3879798701eSJeremy L Thompson 
3889937a20eSJeremy L Thompson   // Free allocations and discard block ids
389ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
3909937a20eSJeremy L Thompson   if (impl->array_allocated) {
3919798701eSJeremy L Thompson     CeedCallBackend(CeedFree(&impl->array_allocated));
3929937a20eSJeremy L Thompson     VALGRIND_DISCARD(impl->allocated_block_id);
3939937a20eSJeremy L Thompson   }
3949937a20eSJeremy L Thompson   if (impl->array_owned) {
3959798701eSJeremy L Thompson     CeedCallBackend(CeedFree(&impl->array_owned));
3969937a20eSJeremy L Thompson     VALGRIND_DISCARD(impl->owned_block_id);
3979937a20eSJeremy L Thompson   }
3989937a20eSJeremy L Thompson   if (impl->array_borrowed) {
3999937a20eSJeremy L Thompson     VALGRIND_DISCARD(impl->borrowed_block_id);
4009937a20eSJeremy L Thompson   }
4019798701eSJeremy L Thompson   CeedCallBackend(CeedFree(&impl));
4029798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
4039798701eSJeremy L Thompson }
4049798701eSJeremy L Thompson 
4059798701eSJeremy L Thompson //------------------------------------------------------------------------------
4069798701eSJeremy L Thompson // Vector Create
4079798701eSJeremy L Thompson //------------------------------------------------------------------------------
4089798701eSJeremy L Thompson int CeedVectorCreate_Memcheck(CeedSize n, CeedVector vec) {
4099798701eSJeremy L Thompson   Ceed                 ceed;
410ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
4119798701eSJeremy L Thompson 
4129e82028bSJeremy L Thompson   CeedCallBackend(CeedCalloc(1, &impl));
4139e82028bSJeremy L Thompson   CeedCallBackend(CeedVectorSetData(vec, impl));
4149e82028bSJeremy L Thompson 
415ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetCeed(vec, &ceed));
4169798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "HasValidArray", CeedVectorHasValidArray_Memcheck));
4179798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "HasBorrowedArrayOfType", CeedVectorHasBorrowedArrayOfType_Memcheck));
4189798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SetArray", CeedVectorSetArray_Memcheck));
41977d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SetValue", CeedVectorSetValue_Memcheck));
42077d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SetValueStrided", CeedVectorSetValueStrided_Memcheck));
4219937a20eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SyncArray", CeedVectorSyncArray_Memcheck));
4229798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "TakeArray", CeedVectorTakeArray_Memcheck));
4239798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArray", CeedVectorGetArray_Memcheck));
4249798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayRead", CeedVectorGetArrayRead_Memcheck));
4259798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayWrite", CeedVectorGetArrayWrite_Memcheck));
4269798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArray", CeedVectorRestoreArray_Memcheck));
4279798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArrayRead", CeedVectorRestoreArrayRead_Memcheck));
42877d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "Reciprocal", CeedVectorReciprocal_Memcheck));
42977d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "Scale", CeedVectorScale_Memcheck));
43077d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "AXPY", CeedVectorAXPY_Memcheck));
43177d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "AXPBY", CeedVectorAXPBY_Memcheck));
43277d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "PointwiseMult", CeedVectorPointwiseMult_Memcheck));
4339798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "Destroy", CeedVectorDestroy_Memcheck));
4349798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
4359798701eSJeremy L Thompson }
4362a86cc9dSSebastian Grimberg 
4379798701eSJeremy L Thompson //------------------------------------------------------------------------------
438