Hi Guosheng,
I tried to modify your ForwardEuler by replacing the Matrix-Vector multiplication, but this did not really help.
Code:
def ForwardEuler(sh, dt):
rhsS.data = aS.mat * sh
#rhsS.data = invm*rhsS
fesS.SolveM(rhsS)
return sh-dt*rhsS
Also to "inline" it did not bring a lot
Code:
#gfuS.vec.data = ForwardEuler(gfuS.vec, dt)
aS.Apply(gfuS.vec,rhsS)
gfuS.vec.data -= dt*invm*rhsS
However, the Compile flag made a huge difference! It is important to compile everything, not only a part of it
Code:
if kdg>0:
aS += (-uh*fw(ss)*grad(tt)).Compile(true_compile, wait=True)*dx
...
aS += (uh*n*Fhat*tt).Compile(true_compile, wait=True)*dx(element_boundary=True)
With this I got a speed up of a factor 3!
It is also possible to speed up your "fast" part even more. Instead of calling mat.Invert every time you can "update" the inverse:
Code:
a.Assemble()
inv = a.mat.Inverse(fesP.FreeDofs(True),inverse="sparsecholesky")
while time < tend-dt/2 :
if stepS%nsubcycles == 0:
a.Assemble()
inv.Update()
...
gfuP.vec.data = inv * rhsP
Then the symbolic factorization is done only once and not every step. This improved the "fast" part from 2.4 to 1.5 seconds on my machine.
Best
Michael