diff --git a/backends/cuda/ceed-cuda-common.c b/backends/cuda/ceed-cuda-common.c index cae17d11d5..f27b453e4d 100644 --- a/backends/cuda/ceed-cuda-common.c +++ b/backends/cuda/ceed-cuda-common.c @@ -53,10 +53,15 @@ static inline int CeedSetDeviceGenericArray_Cuda(Ceed ceed, const void *source_a void *target_array_owned, void *target_array_borrowed, void *target_array) { switch (copy_mode) { case CEED_COPY_VALUES: - if (!*(void **)target_array_owned) CeedCallCuda(ceed, cudaMalloc(target_array_owned, size_unit * num_values)); - if (source_array) CeedCallCuda(ceed, cudaMemcpy(*(void **)target_array_owned, source_array, size_unit * num_values, cudaMemcpyDeviceToDevice)); - *(void **)target_array_borrowed = NULL; - *(void **)target_array = *(void **)target_array_owned; + if (!*(void **)target_array) { + if (*(void **)target_array_borrowed) { + *(void **)target_array = *(void **)target_array_borrowed; + } else { + if (!*(void **)target_array_owned) CeedCallCuda(ceed, cudaMalloc(target_array_owned, size_unit * num_values)); + *(void **)target_array = *(void **)target_array_owned; + } + } + if (source_array) CeedCallCuda(ceed, cudaMemcpy(*(void **)target_array, source_array, size_unit * num_values, cudaMemcpyDeviceToDevice)); break; case CEED_OWN_POINTER: CeedCallCuda(ceed, cudaFree(*(void **)target_array_owned)); diff --git a/backends/hip/ceed-hip-common.c b/backends/hip/ceed-hip-common.c index 597aee9037..b73ef1ffb8 100644 --- a/backends/hip/ceed-hip-common.c +++ b/backends/hip/ceed-hip-common.c @@ -53,10 +53,15 @@ static inline int CeedSetDeviceGenericArray_Hip(Ceed ceed, const void *source_ar void *target_array_owned, void *target_array_borrowed, void *target_array) { switch (copy_mode) { case CEED_COPY_VALUES: - if (!*(void **)target_array_owned) CeedCallHip(ceed, hipMalloc(target_array_owned, size_unit * num_values)); - if (source_array) CeedCallHip(ceed, hipMemcpy(*(void **)target_array_owned, source_array, size_unit * num_values, hipMemcpyDeviceToDevice)); - *(void **)target_array_borrowed = NULL; - *(void **)target_array = *(void **)target_array_owned; + if (!*(void **)target_array) { + if (*(void **)target_array_borrowed) { + *(void **)target_array = *(void **)target_array_borrowed; + } else { + if (!*(void **)target_array_owned) CeedCallHip(ceed, hipMalloc(target_array_owned, size_unit * num_values)); + *(void **)target_array = *(void **)target_array_owned; + } + } + if (source_array) CeedCallHip(ceed, hipMemcpy(*(void **)target_array, source_array, size_unit * num_values, hipMemcpyDeviceToDevice)); break; case CEED_OWN_POINTER: CeedCallHip(ceed, hipFree(*(void **)target_array_owned)); diff --git a/backends/memcheck/ceed-memcheck-vector.c b/backends/memcheck/ceed-memcheck-vector.c index 52716d5c70..b2d6b5efd5 100644 --- a/backends/memcheck/ceed-memcheck-vector.c +++ b/backends/memcheck/ceed-memcheck-vector.c @@ -57,11 +57,13 @@ static int CeedVectorSetArray_Memcheck(CeedVector vec, CeedMemType mem_type, Cee VALGRIND_DISCARD(impl->allocated_block_id); } CeedCallBackend(CeedFree(&impl->array_allocated)); - if (impl->array_owned) { - for (CeedSize i = 0; i < length; i++) impl->array_owned[i] = NAN; - VALGRIND_DISCARD(impl->owned_block_id); + if (copy_mode != CEED_COPY_VALUES) { + if (impl->array_owned) { + for (CeedSize i = 0; i < length; i++) impl->array_owned[i] = NAN; + VALGRIND_DISCARD(impl->owned_block_id); + } + CeedCallBackend(CeedFree(&impl->array_owned)); } - CeedCallBackend(CeedFree(&impl->array_owned)); // Clear borrowed block id, if present if (impl->array_borrowed) VALGRIND_DISCARD(impl->borrowed_block_id); @@ -69,8 +71,7 @@ static int CeedVectorSetArray_Memcheck(CeedVector vec, CeedMemType mem_type, Cee // Set internal pointers to external arrays switch (copy_mode) { case CEED_COPY_VALUES: - impl->array_owned = NULL; - impl->array_borrowed = NULL; + // Nothing to update break; case CEED_OWN_POINTER: impl->array_owned = array; diff --git a/interface/ceed.c b/interface/ceed.c index a25e97a6b7..6ebade1da0 100644 --- a/interface/ceed.c +++ b/interface/ceed.c @@ -349,10 +349,15 @@ static inline int CeedSetHostGenericArray(const void *source_array, CeedCopyMode void *target_array_owned, void *target_array_borrowed, void *target_array) { switch (copy_mode) { case CEED_COPY_VALUES: - if (!*(void **)target_array_owned) CeedCall(CeedCallocArray(num_values, size_unit, target_array_owned)); - if (source_array) memcpy(*(void **)target_array_owned, source_array, size_unit * num_values); - *(void **)target_array_borrowed = NULL; - *(void **)target_array = *(void **)target_array_owned; + if (!*(void **)target_array) { + if (*(void **)target_array_borrowed) { + *(void **)target_array = *(void **)target_array_borrowed; + } else { + if (!*(void **)target_array_owned) CeedCall(CeedCallocArray(num_values, size_unit, target_array_owned)); + *(void **)target_array = *(void **)target_array_owned; + } + } + if (source_array) memcpy(*(void **)target_array, source_array, size_unit * num_values); break; case CEED_OWN_POINTER: CeedCall(CeedFree(target_array_owned)); diff --git a/python/tests/test-1-vector.py b/python/tests/test-1-vector.py index 246b82515e..73ed078bca 100644 --- a/python/tests/test-1-vector.py +++ b/python/tests/test-1-vector.py @@ -359,7 +359,7 @@ def test_126(ceed_resource, capsys): a = np.arange(10, 10 + n, dtype=ceed.scalar_type()) x.set_array(a, cmode=libceed.USE_POINTER) - a2 = np.arange(10, n, dtype=ceed.scalar_type()) + a2 = np.arange(0, n, dtype=ceed.scalar_type()) y.set_array(a2, cmode=libceed.USE_POINTER) y.copy_from(x) diff --git a/tests/t128-vector.c b/tests/t128-vector.c new file mode 100644 index 0000000000..037b482cbe --- /dev/null +++ b/tests/t128-vector.c @@ -0,0 +1,51 @@ +/// @file +/// Test copying into vector with borrowed pointer +/// \test Test copying into vector with borrowed pointer +#include +#include + +int main(int argc, char **argv) { + Ceed ceed; + CeedVector x, x_copy; + CeedInt len = 10; + CeedScalar array_borrowed[len]; + + CeedInit(argv[1], &ceed); + + CeedVectorCreate(ceed, len, &x); + CeedVectorCreate(ceed, len, &x_copy); + + { + CeedScalar array[len]; + + for (CeedInt i = 0; i < len; i++) { + array[i] = i; + array_borrowed[i] = 10 + i; + } + + CeedVectorSetArray(x, CEED_MEM_HOST, CEED_COPY_VALUES, array); + CeedVectorSetArray(x_copy, CEED_MEM_HOST, CEED_USE_POINTER, array_borrowed); + } + + // Copy to device if preferred + { + CeedMemType mem_type = CEED_MEM_HOST; + + CeedGetPreferredMemType(ceed, &mem_type); + if (mem_type == CEED_MEM_DEVICE) CeedVectorSyncArray(x, CEED_MEM_DEVICE); + } + + // Copy and sync borrowed array + CeedVectorCopy(x, x_copy); + CeedVectorSyncArray(x_copy, CEED_MEM_HOST); + + // Check that borrowed array is the same as the original input array a + for (CeedInt i = 0; i < len; i++) { + if (array_borrowed[i] != i) printf("Error in copying values of CeedVector\n"); + } + + CeedVectorDestroy(&x); + CeedVectorDestroy(&x_copy); + CeedDestroy(&ceed); + return 0; +}