An unsolicited bit of advice:



 M_S:

    x_grad.backward(torch.ones_like(x), create_graph=True, retain_graph=True)
        x_grad = x.grad



don’t do that! Just use x_grad, = torch.autograd.grad(....). It is easy to get a memory leak if you use x.grad in autograd because it uses C++ shared pointers that are not garbage collected and so cycles will wreck havoc.
Edit: The sign here is wrong and so it’s bogus, sorry!
So one thing to say is that for the sine function f = sin(ωx), you have that ddf = ω**2 f, so indeed f + ddf in the loss term is something like (1+ω**2) f and would seem to push f towards 0. It might be better to put the function and ddf into separate terms.
More generally, I think it’s always good to look at each loss terms’s contribution to the loss.
Best regards
Thomas