xref: /libCEED/backends/memcheck/ceed-memcheck-qfunction.c (revision 21f16bf6c2940c092555e126518ed0c98a2b88a9)
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   CeedQFunction_Memcheck *impl;
25 
26   CeedCallBackend(CeedQFunctionGetCeed(qf, &ceed));
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   for (CeedInt i = 0; i < num_in; i++) {
33     CeedCallBackend(CeedVectorGetArrayRead(U[i], CEED_MEM_HOST, &impl->inputs[i]));
34   }
35   int mem_block_ids[num_out];
36 
37   for (CeedInt i = 0; i < num_out; i++) {
38     CeedSize len;
39     char     name[32] = "";
40 
41     CeedCallBackend(CeedVectorGetArrayWrite(V[i], CEED_MEM_HOST, &impl->outputs[i]));
42 
43     CeedCallBackend(CeedVectorGetLength(V[i], &len));
44     VALGRIND_MAKE_MEM_UNDEFINED(impl->outputs[i], len);
45 
46     snprintf(name, 32, "'QFunction output %" CeedInt_FMT "'", i);
47     mem_block_ids[i] = VALGRIND_CREATE_BLOCK(impl->outputs[i], len, name);
48   }
49 
50   CeedCallBackend(f(ctx_data, Q, impl->inputs, impl->outputs));
51 
52   for (CeedInt i = 0; i < num_in; i++) {
53     CeedCallBackend(CeedVectorRestoreArrayRead(U[i], &impl->inputs[i]));
54   }
55   for (CeedInt i = 0; i < num_out; i++) {
56     CeedSize length;
57 
58     CeedCallBackend(CeedVectorGetLength(V[i], &length));
59     for (CeedSize j = 0; j < length; j++) {
60       CeedCheck(!isnan(impl->outputs[i][j]), ceed, CEED_ERROR_BACKEND, "QFunction output %d entry %ld is NaN after restoring write-only access", i,
61                 j);
62     }
63     CeedCallBackend(CeedVectorRestoreArray(V[i], &impl->outputs[i]));
64     VALGRIND_DISCARD(mem_block_ids[i]);
65   }
66   CeedCallBackend(CeedQFunctionRestoreContextData(qf, &ctx_data));
67   return CEED_ERROR_SUCCESS;
68 }
69 
70 //------------------------------------------------------------------------------
71 // QFunction Destroy
72 //------------------------------------------------------------------------------
73 static int CeedQFunctionDestroy_Memcheck(CeedQFunction qf) {
74   CeedQFunction_Memcheck *impl;
75 
76   CeedCallBackend(CeedQFunctionGetData(qf, (void *)&impl));
77   CeedCallBackend(CeedFree(&impl->inputs));
78   CeedCallBackend(CeedFree(&impl->outputs));
79   CeedCallBackend(CeedFree(&impl));
80   return CEED_ERROR_SUCCESS;
81 }
82 
83 //------------------------------------------------------------------------------
84 // QFunction Create
85 //------------------------------------------------------------------------------
86 int CeedQFunctionCreate_Memcheck(CeedQFunction qf) {
87   Ceed                    ceed;
88   CeedQFunction_Memcheck *impl;
89 
90   CeedCallBackend(CeedQFunctionGetCeed(qf, &ceed));
91   CeedCallBackend(CeedCalloc(1, &impl));
92   CeedCallBackend(CeedCalloc(CEED_FIELD_MAX, &impl->inputs));
93   CeedCallBackend(CeedCalloc(CEED_FIELD_MAX, &impl->outputs));
94   CeedCallBackend(CeedQFunctionSetData(qf, impl));
95   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunction", qf, "Apply", CeedQFunctionApply_Memcheck));
96   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunction", qf, "Destroy", CeedQFunctionDestroy_Memcheck));
97   return CEED_ERROR_SUCCESS;
98 }
99 
100 //------------------------------------------------------------------------------
101