Gradient computation for physics equations

AlbanOdot: <p>Hello.</p>
<p>I’m currently working on material behavior using Saint-Venant-Kirchoff (<a href="http://redbkit.github.io/redbKIT/math/SolidMechanics/" rel="nofollow noopener">really well explained here</a>). My network outputs the displacements.</p>
<p>Here is my problem : How can i get the gradient of the displacement (needed to compute the matrix <strong>F</strong> in the equations)<br>
I tried several things such as:</p>
<pre><code class="lang-auto">here ones is defined by 
ones = torch.ones_like(displacement).to(displacement.device)
</code></pre>
<pre><code class="lang-auto">displacement.backward(ones)

torch.autograd.grad(displacement, ones)  # Same a above

displacement2 = 1.0 * displacement.clone()  # desperately trying to make it a leaf
displacement2.backward(ones)
</code></pre>
<p>and many others failed attemps.<br>
It always raise the same problem. The tensor displacement is not a leaf hence, backward returns None.</p>
<p>My questions here are.<br>
Is there a clean way to compute the gradient ?<br>
How can i force my tensor to be a leaf ?</p>
<p>I’m sure it only a single line of code or just a function call but i didn’t find it in the documentation.</p>
<p>Thank you in advance for your answers.<br>
Alban.</p>

Zorobay: <p>I’m no expert, but a leaf node is a Tensor that you explicitly created <strong>not</strong> as a result of some operation, so like <code>torch.tensor([1.,2.])</code>.</p>
<p>I don’t know what your variable <code>displacement</code> is, or what type of function it is used in, but is it created like <code>torch.tensor(some_value, requires_grad=True)</code>?</p>

albanD: <p>Hi,</p>
<p>So you have <code>x = \phi(X)</code> and what you want is dx/dX (the derivative of the \phi function).<br>
So using pytorch word, your output is <code>x</code> and the input wrt to which you want the gradient is <code>X</code>.</p>
<p>So the leaf that will get the gradient is X: <code>X = torch.tensor(current_pos, requires_grad=True)</code> where current_pos is a python number, or a numpy array, or anything else.<br>
Then you want to get the output <strong>using only pytorch’s ops</strong> (otherwise the autograd won’t work): <code>x = phi_func(X)</code>.<br>
If you did this right and all ops in your function phi are differentiable, then you should get an output <code>x</code> that requires gradients.<br>
Now You can backward to get the gradient: <code>x.backward()</code> or <code>autograd.grad(x, X)</code>.</p>
<p>Note that autograd is doing automatic differentiation and so is computing a vector Jacobian product. So if your output is not scalar, you will need to provide this vector that will be multiplied with the Jacobian.</p>

AlbanOdot: <p>Thanks for your replies.</p>
<p>Ok so i have something that looks like your init.</p>
<pre><code class="lang-auto">x = torch.FloatTensor(self.inputs).to(device)
x.requires_grad = True
</code></pre>
<p>This goes straigth into the network which tries to produce the displacement <code>d = x - X</code>.<br>
So far only pytorch’s ops have been used.<br>
Since we get <code>F = dx/dX = grad(d) + I</code>, I naively though i could use <code>d.backward(one)</code></p>
<p>The problem might comes from the init since this is the only part that might not match perfectly what you just described.</p>

albanD: <p>Note that your call to <code>autograd.grad()</code> in the first post is not correct. You should give the input before the grad_output.</p>
<p>You can do:</p>
<pre><code class="lang-auto">X = torch.tensor(self.inputs, dtype=torch.float, device=device, requires_grad=True)

x = phi(X)

d = x - X

F, = autograd.grad(d, X, ones)
</code></pre>
<p>Is that what your code looks like?</p>