1 // Copyright (c) 2017-2026, Lawrence Livermore National Security, LLC and other CEED contributors.
2 // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3 //
4 // SPDX-License-Identifier: BSD-2-Clause
5 //
6 // This file is part of CEED: http://github.com/ceed
7
8 #include <ceed.h>
9 #include <ceed/backend.h>
10 #include <math.h>
11 #include <stdio.h>
12 #include <valgrind/memcheck.h>
13
14 #include "ceed-memcheck.h"
15
16 //------------------------------------------------------------------------------
17 // QFunction Apply
18 //------------------------------------------------------------------------------
CeedQFunctionApply_Memcheck(CeedQFunction qf,CeedInt Q,CeedVector * U,CeedVector * V)19 static int CeedQFunctionApply_Memcheck(CeedQFunction qf, CeedInt Q, CeedVector *U, CeedVector *V) {
20 void *ctx_data = NULL;
21 int input_block_ids[CEED_FIELD_MAX], output_block_ids[CEED_FIELD_MAX];
22 CeedInt num_in, num_out;
23 CeedQFunctionUser f = NULL;
24 CeedQFunctionField *output_fields;
25 CeedQFunction_Memcheck *impl;
26
27 CeedCallBackend(CeedQFunctionGetData(qf, &impl));
28 CeedCallBackend(CeedQFunctionGetContextData(qf, CEED_MEM_HOST, &ctx_data));
29 CeedCallBackend(CeedQFunctionGetUserFunction(qf, &f));
30 CeedCallBackend(CeedQFunctionGetNumArgs(qf, &num_in, &num_out));
31
32 // Get input arrays
33 for (CeedInt i = 0; i < num_in; i++) {
34 CeedSize len;
35 char name[32] = "";
36
37 CeedCallBackend(CeedVectorGetArrayRead(U[i], CEED_MEM_HOST, &impl->inputs[i]));
38
39 CeedCallBackend(CeedVectorGetLength(U[i], &len));
40
41 snprintf(name, 32, "QFunction input %" CeedInt_FMT, i);
42 input_block_ids[i] = VALGRIND_CREATE_BLOCK(impl->inputs[i], len, name);
43 }
44
45 // Get output arrays
46 for (CeedInt i = 0; i < num_out; i++) {
47 CeedSize len;
48 char name[32] = "";
49
50 CeedCallBackend(CeedVectorGetArrayWrite(V[i], CEED_MEM_HOST, &impl->outputs[i]));
51
52 CeedCallBackend(CeedVectorGetLength(V[i], &len));
53 VALGRIND_MAKE_MEM_UNDEFINED(impl->outputs[i], len);
54
55 snprintf(name, 32, "QFunction output %" CeedInt_FMT, i);
56 output_block_ids[i] = VALGRIND_CREATE_BLOCK(impl->outputs[i], len, name);
57 }
58
59 // Call user function
60 CeedCallBackend(f(ctx_data, Q, impl->inputs, impl->outputs));
61
62 // Restore input arrays
63 for (CeedInt i = 0; i < num_in; i++) {
64 CeedCallBackend(CeedVectorRestoreArrayRead(U[i], &impl->inputs[i]));
65 VALGRIND_DISCARD(input_block_ids[i]);
66 }
67
68 // Check for unset output values and restore arrays
69 {
70 const char *kernel_name, *kernel_path;
71
72 CeedCallBackend(CeedQFunctionGetSourcePath(qf, &kernel_path));
73 CeedCallBackend(CeedQFunctionGetKernelName(qf, &kernel_name));
74 CeedCallBackend(CeedQFunctionGetFields(qf, NULL, NULL, NULL, &output_fields));
75 for (CeedInt i = 0; i < num_out; i++) {
76 const char *field_name;
77 CeedInt field_size;
78
79 // Note: need field size because vector may be longer than needed for output
80 CeedCallBackend(CeedQFunctionFieldGetSize(output_fields[i], &field_size));
81 CeedCallBackend(CeedQFunctionFieldGetName(output_fields[i], &field_name));
82 for (CeedSize j = 0; j < field_size * (CeedSize)Q; j++) {
83 CeedCheck(!isnan(impl->outputs[i][j]), CeedQFunctionReturnCeed(qf), CEED_ERROR_BACKEND,
84 "QFunction output %" CeedInt_FMT " '%s' entry %" CeedSize_FMT " is NaN after restoring write-only access: %s:%s ", i, field_name, j,
85 kernel_path, kernel_name);
86 }
87 CeedCallBackend(CeedVectorRestoreArray(V[i], &impl->outputs[i]));
88 VALGRIND_DISCARD(output_block_ids[i]);
89 }
90 }
91 CeedCallBackend(CeedQFunctionRestoreContextData(qf, &ctx_data));
92 return CEED_ERROR_SUCCESS;
93 }
94
95 //------------------------------------------------------------------------------
96 // QFunction Destroy
97 //------------------------------------------------------------------------------
CeedQFunctionDestroy_Memcheck(CeedQFunction qf)98 static int CeedQFunctionDestroy_Memcheck(CeedQFunction qf) {
99 CeedQFunction_Memcheck *impl;
100
101 CeedCallBackend(CeedQFunctionGetData(qf, &impl));
102 CeedCallBackend(CeedFree(&impl->inputs));
103 CeedCallBackend(CeedFree(&impl->outputs));
104 CeedCallBackend(CeedFree(&impl));
105 return CEED_ERROR_SUCCESS;
106 }
107
108 //------------------------------------------------------------------------------
109 // QFunction Create
110 //------------------------------------------------------------------------------
CeedQFunctionCreate_Memcheck(CeedQFunction qf)111 int CeedQFunctionCreate_Memcheck(CeedQFunction qf) {
112 Ceed ceed;
113 CeedQFunction_Memcheck *impl;
114
115 CeedCallBackend(CeedQFunctionGetCeed(qf, &ceed));
116 CeedCallBackend(CeedCalloc(1, &impl));
117 CeedCallBackend(CeedCalloc(CEED_FIELD_MAX, &impl->inputs));
118 CeedCallBackend(CeedCalloc(CEED_FIELD_MAX, &impl->outputs));
119 CeedCallBackend(CeedQFunctionSetData(qf, impl));
120 CeedCallBackend(CeedSetBackendFunction(ceed, "QFunction", qf, "Apply", CeedQFunctionApply_Memcheck));
121 CeedCallBackend(CeedSetBackendFunction(ceed, "QFunction", qf, "Destroy", CeedQFunctionDestroy_Memcheck));
122 CeedCallBackend(CeedDestroy(&ceed));
123 return CEED_ERROR_SUCCESS;
124 }
125
126 //------------------------------------------------------------------------------
127