I need to calculate the gradient of each element of loss w.r.t parameters and  use it to compute gradient vector and hessian matrix.
my code is below:
        optimiser.zero_grad()
        Error_Train_1 = PDE_loss(train_x, train_y, loss_func)
        
        
        size_hess = q*p
        MyHess = torch.zeros([size_hess,size_hess])
        MyGrad = torch.zeros([size_hess,1])
        for j in range(Error_Train_1.shape[0]): 
            for i in range(q+1):
                jac = []
                optimiser.zero_grad()
                (Error_Train_1[j,i]).backward(retain_graph=True)
                        
                for params in self.parameters():
                    # in order to prevent stopping algorithm
                    if params.grad is None:
                       Pg = torch.zeros_like(params).reshape(-1)
                    else:
                       Pg = params.grad.reshape(-1)
                            
                    if len(jac) == 0: 
                       jac = Pg
                    else:
                       jac = torch.cat((jac, Pg)) 

                jac = torch.reshape(jac, (1, -1))     
                Hess = torch.matmul(torch.transpose(jac, 0, 1), jac)  
                Par_grad = torch.transpose(jac, 0, 1)*(Error_Train_1[j,i])  
                MyGrad +=  Par_grad
                MyHess += Hess

There are a lot of for loops and if conditions, which is not good for performance, and it takes a lot of time.
Could you please help me and let me know if there is any better way to handle if conditions or for loops?
Thanks.