Differentiation of symbolic expressions

I am trying to understand how symbolic differentiation works in NGSolve for coefficient-dependent bilinear forms.

Suppose I have:

V = H1(mesh, order=2)
Q = L2(mesh, order=0)

u, v = V.TnT()
g, dg = Q.TnT()

cf = g * InnerProduct(grad(u), grad(v))

My goal is to compute the derivative of the stiffness matrix with respect to the L2 coefficient field g.

I understand that:

cf.Diff(g)

produces something equivalent to

InnerProduct(grad(u), grad(v))

But I am still confused about how this maps to assembled matrices.

Questions:

  1. Is cf.Diff(g) the correct symbolic representation of the derivative of the bilinear form with respect to g?

  2. If Q = L2(order=0), should the derivative with respect to each L2 dof correspond to one sparse matrix localized on one element?

  3. Is there a built-in way to assemble the tensor

    \frac{\partial A_{mn}}{\partial g_i}

    directly, rather than manually looping over L2 basis functions?

  4. Is there a way to inspect/debug the symbolic expression tree generated internally by Variation or Diff?

I would also appreciate clarification on the conceptual distinction between:

  • differentiating w.r.t. a GridFunction

  • differentiating w.r.t. a proxy function from Q.TnT()

Thanks!