I need some help understanding an issue I am encountering with regard to previous solutions inside a bi-linear/linear form. To demonstrate the problem I have coded up two versions of a Finite Element Transient Poisson (a non-dimensional heat equation). The first uses implicit Euler time-stepping, and the second explicit Euler.

The only difference between these two codes is the linear/bilinear forms. The implicit Euler solution converges as expected to a steady-state solution (the details of the model are included in the doc-string), while the explicit Euler does nothing (no change when time-stepping).

The program was designed to show convergence to a steady-state solution using ever-decreasing time-steps.

This problem identifies my lack of knowledge of Finite Element methods, or implementation in NGSolve, and help with either would be greatly appreciated.

here are a couple of comments which might help you:

You can move
bl.Assemble()
c.Update()
outside of the time-stepping loop (but inside the TaskManager), as the matrix does not change over time. At the moment this is quite a lot of redundant computational effort.

Doing soln.Set(0, definedon=mesh.Boundaries("left|right")) is unnecessary (if you zero out the Griduction at initialisation
soln = GridFunction(fes)
soln.vec[:] = 0.0) as Dirchlet DOFs remain unchanged when solving the system.

To copy the data from one GridFunction to another GridFunction (of the same space) I recommend doing

soln_prev.vec.data = soln.vec. As far as I understand, GridFunction.Set is designed to interpolate a CoefficientFunction into the discrete function, see thedocumentation.

Now to the explicit Euler part. At the moment you are missing the explicit evaluation of the diffusion operator. This could be done for example by doing

l += -dt * InnerProduct(grad(soln_prev), grad(v)) * dx

BUT: Explicit methods are only stable for very small time-steps. So a direct comparison might not be possible, since the explicit Euler might not be stable for you chosen time-steps. For example you might see that the solution looks good for a few time steps and then explodes.

Thanks so much for your quick reply and advice. I implemented all of it, and you were spot on for all of it. Thanks.

I realize I uploaded the wrong version of the explicit Euler originally. The version below with your advice implemented is correct. I was able to use these to build a Crank-Nicolson version, and then an adaptive time-stepping version (which was my ultimate goal).