# Defining User Q-Functions An important feature of LibCEED.jl is the ability to define [user Q-functions](https://libceed.readthedocs.io/en/latest/libCEEDapi/#gallery-of-qfunctions) natively in Julia. These user Q-functions work with both the CPU and CUDA backends. User Q-functions describe the action of the $D$ operator at quadrature points (see [libCEED's theoretical framework](https://libceed.readthedocs.io/en/latest/libCEEDapi/#theoretical-framework)). Since the Q-functions are invoked at every quadrature point, efficiency is very important. ## Apply mass Q-function in C Before describing how to define user Q-functions in Julia, we will briefly given an example of a user Q-function defined in C. This is the "apply mass" Q-function from `ex1-volume.c`, which computes the action of the mass operator. The mass operator on each element can be written as $B^\intercal D B$, where $B$ is the basis operator, and $D$ represents multiplication by quadrature weights and geometric factors (i.e. the determinant of the mesh transformation Jacobian at each qudarture point). It is the action of $D$ that the Q-function must implement. The C source of the Q-function is: ```c /// libCEED Q-function for applying a mass operator CEED_QFUNCTION(f_apply_mass)(void *ctx, const CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { const CeedScalar *u = in[0], *qdata = in[1]; CeedScalar *v = out[0]; // Quadrature Point Loop CeedPragmaSIMD for (CeedInt i=0; i