I am working on a time-dependent problem where both the bilinear and linear forms vary with time. Based on the dynamics of my problem, I understand that I should create matrix and vector outside the time loop but update and reassemble them within each time step due to their time-dependent nature.

......
A1 = create_matrix(a1)
b1 = create_vector(L1)
solver1 = PETSc.KSP().create(mesh.comm)
solver1.setOperators(A1)
solver1.setType(PETSc.KSP.Type.GMRES)
for i in range(num_steps):
A1.zeroEntries()
assemble_matrix(A1, a1)
A1.assemble()
with b1.localForm() as loc:
loc.set(0)
assemble_vector(b1, L1)
b1.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE)
solver1.solve(b1, u_s.vector)
u_s.x.scatter_forward()

Assuming a1, L1 and some others are already defined, with boundary conditions being Neumann zero conditions, is every line of code in the time loop necessary? Especially in this line,

if I don’t applly Dirichlet boundary conditions, I need not to use apply_lifting(), but it seems like b1.ghostUpdate() must be added, otherwise the result will be incorrect.

Overall, my confusion lies in what are the necessary and unnecessary function calls for manually assembling PETSc problem.

If you have to re-assemble A at every time-step, you could just define a dolfinx.fem.petsc.LinearProblem outside the loop and use that.
I would only split into manual PETSc steps if I wanted to avoid such calls (say that you have a time-independent matrix, but a time dependent RHS).

The ghostUpdate reverse with addition is needed to accumulate contributions from all dofs when assembling the local array. It is similar to what happens within A1.assemble().

Sorry for not describing it completely. I need to update matrix that changes over time, but also need to use matrix constructed in variational form for some other calculations. I’m not sure, is there any way to obtain the compiled matrix if LinearProblem() is used.

There’s one more question:
In the absence of any Dirichlet boundary conditions, is it appropriate to entirely omit apply_lifting() and set_bc() from the assembly and solving process?