Assemble without trial function

As far as I understand, when solving a linear variational problem, one may use a trial function (option A) and to

u = TrialFunction(V)
v = TestFunction(V)

F = c * dot(u, v)*dx + ...
a = lhs(F)
L = rhs(F)

then every time a parameter in the functional F changes, e.g., c, I need to re-assemble for the updated variational problem to be solved

A = assemble(a)
b = assemble(L)

and then apply the boundary conditions and call solve with

    [bc.apply(b) for bc in bc_u]
    solve(A, u_.vector(), b, 'bicgstab', 'hypre_amg').

So far, so good.

I can also (option B) solve the same problem without a trial function, by doing

u = Function(V)
v = TestFunction(V)

F = c * dot(u, v)*dx + ...
solve(F==0, u, bc_u)

If the parameter c or some other quantity in F changes and I want to solve the updated variational problem, do I need to call some equivalent of assemble also when using option B? Or is F automatically updated?

It must be. The notation F == 0 is used in general for nonlinear problems, which are solved with iterative methods such as the Newton method. In that case, F must be re-assembled at every iteration, because u changes at every iteration.

You don’t see this in your case because your F is linear in u, and thus the iterative method will converge in 1 iteration.

Oh I see, thank you.