xref: /libCEED/backends/memcheck/ceed-memcheck-qfunction.c (revision 74d1b6c4d74ab01eefbd8940b6e3a2db84651b5c)
1 // Copyright (c) 2017-2022, 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 //------------------------------------------------------------------------------
19 static int CeedQFunctionApply_Memcheck(CeedQFunction qf, CeedInt Q, CeedVector *U, CeedVector *V) {
20   Ceed                    ceed;
21   void                   *ctx_data = NULL;
22   CeedInt                 num_in, num_out;
23   CeedQFunctionUser       f = NULL;
24   CeedQFunctionField     *output_fields;
25   CeedQFunction_Memcheck *impl;
26 
27   CeedCallBackend(CeedQFunctionGetCeed(qf, &ceed));
28   CeedCallBackend(CeedQFunctionGetData(qf, &impl));
29   CeedCallBackend(CeedQFunctionGetContextData(qf, CEED_MEM_HOST, &ctx_data));
30   CeedCallBackend(CeedQFunctionGetUserFunction(qf, &f));
31   CeedCallBackend(CeedQFunctionGetNumArgs(qf, &num_in, &num_out));
32   int mem_block_ids[num_out];
33 
34   // Get input/output arrays
35   for (CeedInt i = 0; i < num_in; i++) {
36     CeedCallBackend(CeedVectorGetArrayRead(U[i], CEED_MEM_HOST, &impl->inputs[i]));
37   }
38   for (CeedInt i = 0; i < num_out; i++) {
39     CeedSize len;
40     char     name[32] = "";
41 
42     CeedCallBackend(CeedVectorGetArrayWrite(V[i], CEED_MEM_HOST, &impl->outputs[i]));
43 
44     CeedCallBackend(CeedVectorGetLength(V[i], &len));
45     VALGRIND_MAKE_MEM_UNDEFINED(impl->outputs[i], len);
46 
47     snprintf(name, 32, "'QFunction output %" CeedInt_FMT "'", i);
48     mem_block_ids[i] = VALGRIND_CREATE_BLOCK(impl->outputs[i], len, name);
49   }
50 
51   // Call user function
52   CeedCallBackend(f(ctx_data, Q, impl->inputs, impl->outputs));
53 
54   // Restore input arrays
55   for (CeedInt i = 0; i < num_in; i++) {
56     CeedCallBackend(CeedVectorRestoreArrayRead(U[i], &impl->inputs[i]));
57   }
58   // Check for unset output values
59   {
60     char *kernel_path, *kernel_name;
61 
62     CeedCallBackend(CeedQFunctionGetSourcePath(qf, &kernel_path));
63     CeedCallBackend(CeedQFunctionGetKernelName(qf, &kernel_name));
64     CeedCallBackend(CeedQFunctionGetFields(qf, NULL, NULL, NULL, &output_fields));
65     for (CeedInt i = 0; i < num_out; i++) {
66       CeedInt field_size;
67 
68       // Note: need field size because vector may be longer than needed for output
69       CeedCallBackend(CeedQFunctionFieldGetSize(output_fields[i], &field_size));
70       for (CeedSize j = 0; j < Q * field_size; j++) {
71         CeedCheck(!isnan(impl->outputs[i][j]), ceed, CEED_ERROR_BACKEND,
72                   "QFunction output %d entry %ld is NaN after restoring write-only access: %s:%s ", i, j, kernel_path, kernel_name);
73       }
74       CeedCallBackend(CeedVectorRestoreArray(V[i], &impl->outputs[i]));
75       VALGRIND_DISCARD(mem_block_ids[i]);
76     }
77   }
78   CeedCallBackend(CeedQFunctionRestoreContextData(qf, &ctx_data));
79   return CEED_ERROR_SUCCESS;
80 }
81 
82 //------------------------------------------------------------------------------
83 // QFunction Destroy
84 //------------------------------------------------------------------------------
85 static int CeedQFunctionDestroy_Memcheck(CeedQFunction qf) {
86   CeedQFunction_Memcheck *impl;
87 
88   CeedCallBackend(CeedQFunctionGetData(qf, (void *)&impl));
89   CeedCallBackend(CeedFree(&impl->inputs));
90   CeedCallBackend(CeedFree(&impl->outputs));
91   CeedCallBackend(CeedFree(&impl));
92   return CEED_ERROR_SUCCESS;
93 }
94 
95 //------------------------------------------------------------------------------
96 // QFunction Create
97 //------------------------------------------------------------------------------
98 int CeedQFunctionCreate_Memcheck(CeedQFunction qf) {
99   Ceed                    ceed;
100   CeedQFunction_Memcheck *impl;
101 
102   CeedCallBackend(CeedQFunctionGetCeed(qf, &ceed));
103   CeedCallBackend(CeedCalloc(1, &impl));
104   CeedCallBackend(CeedCalloc(CEED_FIELD_MAX, &impl->inputs));
105   CeedCallBackend(CeedCalloc(CEED_FIELD_MAX, &impl->outputs));
106   CeedCallBackend(CeedQFunctionSetData(qf, impl));
107   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunction", qf, "Apply", CeedQFunctionApply_Memcheck));
108   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunction", qf, "Destroy", CeedQFunctionDestroy_Memcheck));
109   return CEED_ERROR_SUCCESS;
110 }
111 
112 //------------------------------------------------------------------------------
113