xref: /libCEED/backends/memcheck/ceed-memcheck-vector.c (revision ff90b007c3dd968e763cc6a82bde1e90c117acbc)
1d275d636SJeremy L Thompson // Copyright (c) 2017-2025, 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));
60cc3bdf8cSJeremy 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));
66cc3bdf8cSJeremy 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:
74cc3bdf8cSJeremy 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 //------------------------------------------------------------------------------
118*ff90b007SJeremy L Thompson static int CeedVectorSetValueStrided_Memcheck(CeedVector vec, CeedSize start, CeedSize stop, 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);
127*ff90b007SJeremy L Thompson   if (stop == -1) stop = length;
128*ff90b007SJeremy L Thompson   for (CeedSize i = start; i < stop; i += step) impl->array_allocated[i] = val;
12977d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
13077d04a1cSJeremy L Thompson }
13177d04a1cSJeremy L Thompson 
13277d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
1339937a20eSJeremy L Thompson // Sync arrays
1349937a20eSJeremy L Thompson //------------------------------------------------------------------------------
1359937a20eSJeremy L Thompson static int CeedVectorSyncArray_Memcheck(const CeedVector vec, CeedMemType mem_type) {
1369937a20eSJeremy L Thompson   CeedSize             length;
1379937a20eSJeremy L Thompson   CeedVector_Memcheck *impl;
1389937a20eSJeremy L Thompson 
1399937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
1409937a20eSJeremy L Thompson 
1419937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
1429937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
1439937a20eSJeremy L Thompson 
1449937a20eSJeremy L Thompson   // Copy internal buffer back to owned or borrowed array
1459937a20eSJeremy L Thompson   if (impl->array_owned) {
1469937a20eSJeremy L Thompson     memcpy(impl->array_owned, impl->array_allocated, length * sizeof(CeedScalar));
1479937a20eSJeremy L Thompson   }
1489937a20eSJeremy L Thompson   if (impl->array_borrowed) {
1499937a20eSJeremy L Thompson     memcpy(impl->array_borrowed, impl->array_allocated, length * sizeof(CeedScalar));
1509937a20eSJeremy L Thompson   }
1519798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1529798701eSJeremy L Thompson }
1539798701eSJeremy L Thompson 
1549798701eSJeremy L Thompson //------------------------------------------------------------------------------
1559798701eSJeremy L Thompson // Vector Take Array
1569798701eSJeremy L Thompson //------------------------------------------------------------------------------
1579798701eSJeremy L Thompson static int CeedVectorTakeArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) {
158d1931fc8SJeremy L Thompson   CeedSize             length;
159ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
160ad70ee2cSJeremy L Thompson 
1619937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
1629937a20eSJeremy L Thompson 
163ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
164d1931fc8SJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
1659798701eSJeremy L Thompson 
1669937a20eSJeremy L Thompson   // Synchronize memory
1679937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorSyncArray_Memcheck(vec, CEED_MEM_HOST));
1689798701eSJeremy L Thompson 
1699937a20eSJeremy L Thompson   // Return borrowed array
1709798701eSJeremy L Thompson   (*array)             = impl->array_borrowed;
1719798701eSJeremy L Thompson   impl->array_borrowed = NULL;
1729937a20eSJeremy L Thompson   VALGRIND_DISCARD(impl->borrowed_block_id);
1739937a20eSJeremy L Thompson 
1749937a20eSJeremy L Thompson   // De-allocate internal memory
175d1931fc8SJeremy L Thompson   if (impl->array_allocated) {
176d1931fc8SJeremy L Thompson     for (CeedSize i = 0; i < length; i++) impl->array_allocated[i] = NAN;
1770307dd02SJeremy L Thompson     VALGRIND_DISCARD(impl->allocated_block_id);
178d1931fc8SJeremy L Thompson   }
1799798701eSJeremy L Thompson   CeedCallBackend(CeedFree(&impl->array_allocated));
1809798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1819798701eSJeremy L Thompson }
1829798701eSJeremy L Thompson 
1839798701eSJeremy L Thompson //------------------------------------------------------------------------------
1849798701eSJeremy L Thompson // Vector Get Array
1859798701eSJeremy L Thompson //------------------------------------------------------------------------------
1869798701eSJeremy L Thompson static int CeedVectorGetArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) {
1871a3e18b3SJeremy L Thompson   CeedSize             length;
188ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
189ad70ee2cSJeremy L Thompson 
1909937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
1919937a20eSJeremy L Thompson 
192ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
1931a3e18b3SJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
1949798701eSJeremy L Thompson 
1959937a20eSJeremy L Thompson   // Create and return writable buffer
1961a3e18b3SJeremy L Thompson   CeedCallBackend(CeedCalloc(length, &impl->array_writable_copy));
1979937a20eSJeremy L Thompson   impl->writable_block_id = VALGRIND_CREATE_BLOCK(impl->array_writable_copy, length * sizeof(CeedScalar), "Allocated writeable array buffer copy");
1989937a20eSJeremy L Thompson   memcpy(impl->array_writable_copy, impl->array_allocated, length * sizeof(CeedScalar));
1991a3e18b3SJeremy L Thompson   *array = impl->array_writable_copy;
2009798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
2019798701eSJeremy L Thompson }
2029798701eSJeremy L Thompson 
2039798701eSJeremy L Thompson //------------------------------------------------------------------------------
2049798701eSJeremy L Thompson // Vector Get Array Read
2059798701eSJeremy L Thompson //------------------------------------------------------------------------------
2069798701eSJeremy L Thompson static int CeedVectorGetArrayRead_Memcheck(CeedVector vec, CeedMemType mem_type, const CeedScalar **array) {
207ad70ee2cSJeremy L Thompson   CeedSize             length;
208ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
209ad70ee2cSJeremy L Thompson 
2109937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
2119937a20eSJeremy L Thompson 
212ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
213ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
2149798701eSJeremy L Thompson 
2159937a20eSJeremy L Thompson   // Create and return read-only buffer
2165b5dc0c8SJeremy L Thompson   if (!impl->array_read_only_copy) {
2179798701eSJeremy L Thompson     CeedCallBackend(CeedCalloc(length, &impl->array_read_only_copy));
2189937a20eSJeremy L Thompson     impl->writable_block_id = VALGRIND_CREATE_BLOCK(impl->array_read_only_copy, length * sizeof(CeedScalar), "Allocated read-only array buffer copy");
2199937a20eSJeremy L Thompson     memcpy(impl->array_read_only_copy, impl->array_allocated, length * sizeof(CeedScalar));
2205b5dc0c8SJeremy L Thompson   }
221d1931fc8SJeremy L Thompson   *array = impl->array_read_only_copy;
2229798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
2239798701eSJeremy L Thompson }
2249798701eSJeremy L Thompson 
2259798701eSJeremy L Thompson //------------------------------------------------------------------------------
2269798701eSJeremy L Thompson // Vector Get Array Write
2279798701eSJeremy L Thompson //------------------------------------------------------------------------------
2289798701eSJeremy L Thompson static int CeedVectorGetArrayWrite_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) {
229ad70ee2cSJeremy L Thompson   CeedSize             length;
230ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
231ad70ee2cSJeremy L Thompson 
2329937a20eSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
2339937a20eSJeremy L Thompson 
234ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
235ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
2369798701eSJeremy L Thompson 
2379937a20eSJeremy L Thompson   // Allocate buffer if necessary
2389937a20eSJeremy L Thompson   if (!impl->array_allocated) CeedCallBackend(CeedVectorSetArray_Memcheck(vec, mem_type, CEED_COPY_VALUES, NULL));
2399937a20eSJeremy L Thompson 
2409937a20eSJeremy L Thompson   // Get writable buffer
2419798701eSJeremy L Thompson   CeedCallBackend(CeedVectorGetArray_Memcheck(vec, mem_type, array));
2429937a20eSJeremy L Thompson 
2439937a20eSJeremy L Thompson   // Invalidate array data to prevent accidental reads
244dd39767dSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) (*array)[i] = NAN;
245df852985SJeremy L Thompson   impl->is_write_only_access = true;
2469798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
2479798701eSJeremy L Thompson }
2489798701eSJeremy L Thompson 
2499798701eSJeremy L Thompson //------------------------------------------------------------------------------
2509798701eSJeremy L Thompson // Vector Restore Array
2519798701eSJeremy L Thompson //------------------------------------------------------------------------------
2529798701eSJeremy L Thompson static int CeedVectorRestoreArray_Memcheck(CeedVector vec) {
253ad70ee2cSJeremy L Thompson   CeedSize             length;
254ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
255ad70ee2cSJeremy L Thompson 
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++) {
2626c10af5dSJeremy L Thompson       if (isnan(impl->array_writable_copy[i])) {
2639bc66399SJeremy L Thompson         CeedDebug256(CeedVectorReturnCeed(vec), CEED_DEBUG_COLOR_WARNING,
2649bc66399SJeremy L Thompson                      "WARNING: Vec entry %" CeedSize_FMT " is NaN after restoring write-only access", i);
265df852985SJeremy L Thompson       }
2666c10af5dSJeremy L Thompson     }
267df852985SJeremy L Thompson     impl->is_write_only_access = false;
268df852985SJeremy L Thompson   }
2699937a20eSJeremy L Thompson 
2709937a20eSJeremy L Thompson   // Copy back to internal buffer and sync
2719937a20eSJeremy L Thompson   memcpy(impl->array_allocated, impl->array_writable_copy, length * sizeof(CeedScalar));
2729937a20eSJeremy L Thompson   CeedCallBackend(CeedVectorSyncArray_Memcheck(vec, CEED_MEM_HOST));
2739937a20eSJeremy L Thompson 
2749937a20eSJeremy L Thompson   // Invalidate writable buffer
2759937a20eSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl->array_writable_copy[i] = NAN;
2769937a20eSJeremy L Thompson   CeedCallBackend(CeedFree(&impl->array_writable_copy));
2779937a20eSJeremy L Thompson   VALGRIND_DISCARD(impl->writable_block_id);
2789798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
2799798701eSJeremy L Thompson }
2809798701eSJeremy L Thompson 
2819798701eSJeremy L Thompson //------------------------------------------------------------------------------
2829798701eSJeremy L Thompson // Vector Restore Array Read-Only
2839798701eSJeremy L Thompson //------------------------------------------------------------------------------
2849798701eSJeremy L Thompson static int CeedVectorRestoreArrayRead_Memcheck(CeedVector vec) {
285ad70ee2cSJeremy L Thompson   CeedSize             length;
286ad70ee2cSJeremy L Thompson   CeedVector_Memcheck *impl;
287ad70ee2cSJeremy L Thompson 
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 
2949bc66399SJeremy L Thompson   CeedCheck(!is_changed, CeedVectorReturnCeed(vec), 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 //------------------------------------------------------------------------------
30477d04a1cSJeremy L Thompson // Take reciprocal of a vector
30577d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
30677d04a1cSJeremy L Thompson static int CeedVectorReciprocal_Memcheck(CeedVector vec) {
30777d04a1cSJeremy L Thompson   CeedSize             length;
30877d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl;
30977d04a1cSJeremy L Thompson 
31077d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(vec, &impl));
31177d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(vec, &length));
31277d04a1cSJeremy L Thompson 
31377d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) {
31477d04a1cSJeremy L Thompson     if (fabs(impl->array_allocated[i]) > CEED_EPSILON) impl->array_allocated[i] = 1. / impl->array_allocated[i];
31577d04a1cSJeremy L Thompson   }
31677d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
31777d04a1cSJeremy L Thompson }
31877d04a1cSJeremy L Thompson 
31977d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
32077d04a1cSJeremy L Thompson // Compute x = alpha x
32177d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
32277d04a1cSJeremy L Thompson static int CeedVectorScale_Memcheck(CeedVector x, CeedScalar alpha) {
32377d04a1cSJeremy L Thompson   CeedSize             length;
32477d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl;
32577d04a1cSJeremy L Thompson 
32677d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl));
32777d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(x, &length));
32877d04a1cSJeremy L Thompson 
32977d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl->array_allocated[i] *= alpha;
33077d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
33177d04a1cSJeremy L Thompson }
33277d04a1cSJeremy L Thompson 
33377d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
33477d04a1cSJeremy L Thompson // Compute y = alpha x + y
33577d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
33677d04a1cSJeremy L Thompson static int CeedVectorAXPY_Memcheck(CeedVector y, CeedScalar alpha, CeedVector x) {
33777d04a1cSJeremy L Thompson   CeedSize             length;
33877d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl_x, *impl_y;
33977d04a1cSJeremy L Thompson 
34077d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl_x));
34177d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(y, &impl_y));
34277d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(y, &length));
34377d04a1cSJeremy L Thompson 
34477d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl_y->array_allocated[i] += alpha * impl_x->array_allocated[i];
34577d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
34677d04a1cSJeremy L Thompson }
34777d04a1cSJeremy L Thompson 
34877d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
34977d04a1cSJeremy L Thompson // Compute y = alpha x + beta y
35077d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
35177d04a1cSJeremy L Thompson static int CeedVectorAXPBY_Memcheck(CeedVector y, CeedScalar alpha, CeedScalar beta, CeedVector x) {
35277d04a1cSJeremy L Thompson   CeedSize             length;
35377d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl_x, *impl_y;
35477d04a1cSJeremy L Thompson 
35577d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl_x));
35677d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(y, &impl_y));
35777d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(y, &length));
35877d04a1cSJeremy L Thompson 
35977d04a1cSJeremy 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];
36077d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
36177d04a1cSJeremy L Thompson }
36277d04a1cSJeremy L Thompson 
36377d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
36477d04a1cSJeremy L Thompson // Compute the pointwise multiplication w = x .* y
36577d04a1cSJeremy L Thompson //------------------------------------------------------------------------------
36677d04a1cSJeremy L Thompson static int CeedVectorPointwiseMult_Memcheck(CeedVector w, CeedVector x, CeedVector y) {
36777d04a1cSJeremy L Thompson   CeedSize             length;
36877d04a1cSJeremy L Thompson   CeedVector_Memcheck *impl_x, *impl_y, *impl_w;
36977d04a1cSJeremy L Thompson 
37077d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(x, &impl_x));
37177d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(y, &impl_y));
37277d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetData(w, &impl_w));
37377d04a1cSJeremy L Thompson   CeedCallBackend(CeedVectorGetLength(w, &length));
37477d04a1cSJeremy L Thompson 
37577d04a1cSJeremy L Thompson   if (!impl_w->array_allocated) CeedCallBackend(CeedVectorSetArray_Memcheck(w, CEED_MEM_HOST, CEED_COPY_VALUES, NULL));
37677d04a1cSJeremy L Thompson   assert(impl_w->array_allocated);
37777d04a1cSJeremy L Thompson   for (CeedSize i = 0; i < length; i++) impl_w->array_allocated[i] = impl_x->array_allocated[i] * impl_y->array_allocated[i];
37877d04a1cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
37977d04a1cSJeremy L Thompson }
38077d04a1cSJeremy L Thompson 
38177d04a1cSJeremy 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 
411ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedVectorGetCeed(vec, &ceed));
4129798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "HasValidArray", CeedVectorHasValidArray_Memcheck));
4139798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "HasBorrowedArrayOfType", CeedVectorHasBorrowedArrayOfType_Memcheck));
4149798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SetArray", CeedVectorSetArray_Memcheck));
41577d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SetValue", CeedVectorSetValue_Memcheck));
41677d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SetValueStrided", CeedVectorSetValueStrided_Memcheck));
4179937a20eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SyncArray", CeedVectorSyncArray_Memcheck));
4189798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "TakeArray", CeedVectorTakeArray_Memcheck));
4199798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArray", CeedVectorGetArray_Memcheck));
4209798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayRead", CeedVectorGetArrayRead_Memcheck));
4219798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayWrite", CeedVectorGetArrayWrite_Memcheck));
4229798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArray", CeedVectorRestoreArray_Memcheck));
4239798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArrayRead", CeedVectorRestoreArrayRead_Memcheck));
42477d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "Reciprocal", CeedVectorReciprocal_Memcheck));
42577d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "Scale", CeedVectorScale_Memcheck));
42677d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "AXPY", CeedVectorAXPY_Memcheck));
42777d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "AXPBY", CeedVectorAXPBY_Memcheck));
42877d04a1cSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "PointwiseMult", CeedVectorPointwiseMult_Memcheck));
4299798701eSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "Destroy", CeedVectorDestroy_Memcheck));
4309bc66399SJeremy L Thompson   CeedCallBackend(CeedDestroy(&ceed));
4319bc66399SJeremy L Thompson   CeedCallBackend(CeedCalloc(1, &impl));
4329bc66399SJeremy L Thompson   CeedCallBackend(CeedVectorSetData(vec, impl));
4339798701eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
4349798701eSJeremy L Thompson }
4352a86cc9dSSebastian Grimberg 
4369798701eSJeremy L Thompson //------------------------------------------------------------------------------
437