-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Non zero gradients when all neighbors are periodic images #351
Comments
Hello all, I think the output needs to be partially multiplied with the direction vectors so we get zero gradients for this frame. Firstly we need to consider the sum of the gradient, because we also output the self contribution (this has been already discussed with @Luthaf last week but it was not enough to get zeros). Secondly I think the direction vector is not included in the computation for the spherical expansion gradient. I have printed two pair gradients of opposing ghost neighbours (central atom is at position (0.5, 0.5, 0.5) and we have a cubic cell [1, 1, 1])
So we need to multiply l mod 2 = 1 components with the direction vector and then it works out import ase
from ase import build
import numpy as np
from rascal.representations import SphericalExpansion
hypers = dict(
interaction_cutoff=4.5,
cutoff_smooth_width=0.5,
max_radial=6,
max_angular=6,
gaussian_sigma_type="Constant",
gaussian_sigma_constant=0.3,
radial_basis="GTO",
compute_gradients=True
)
se = SphericalExpansion(**hypers)
frame = ase.build.bulk("H", "fcc", 2.2)
#frame = ase.Atoms('H', positions=[(0.5,0.5,0.5)], cell=[1,1,1])
frame.pbc = True
representation = se.transform(frame)
gradients = representation.get_features_gradient(se)
dir_vec = representation.get_direction_vectors()
# (i, anlm) -> (i, a, n, l, m)
def relayout(x, hypers):
nmax = hypers['max_radial']
lmax = hypers['max_angular']
n = len(x)
nel = x.shape[1]//(nmax*(lmax+1)**2)
rx = x.reshape((n, nel, nmax, (lmax+1)**2))
nx = np.zeros((n, nel, nmax, lmax+1, 2*lmax+1)) # lazy layout for easier manipulation
for l in range(lmax+1):
nx[:,:,:,l,:2*l+1] = rx[:,:,:,l**2:(l+1)**2]
return nx
gradients = relayout(gradients, hypers)
sum_gradients_x = np.zeros((1, gradients.shape[1], gradients.shape[2], gradients.shape[3], gradients.shape[4]))
sum_gradients_y = np.zeros((1, gradients.shape[1], gradients.shape[2], gradients.shape[3], gradients.shape[4]))
sum_gradients_z = np.zeros((1, gradients.shape[1], gradients.shape[2], gradients.shape[3], gradients.shape[4]))
for i, sample in enumerate(dir_vec):
for angular_l in range(hypers['max_angular']):
if angular_l % 2 == 1:
sum_gradients_x += gradients[3 * i + 0, :, :, angular_l:angular_l+1, :] * dir_vec[i, 0]
sum_gradients_y += gradients[3 * i + 1, :, :, angular_l:angular_l+1, :] * dir_vec[i, 1]
sum_gradients_z += gradients[3 * i + 2, :, :, angular_l:angular_l+1, :] * dir_vec[i, 2]
else:
sum_gradients_x += gradients[3 * i + 0, :, :, angular_l:angular_l+1, :]
sum_gradients_y += gradients[3 * i + 1, :, :, angular_l:angular_l+1, :]
sum_gradients_z += gradients[3 * i + 2, :, :, angular_l:angular_l+1, :]
print(np.allclose(sum_gradients_x, np.zeros(sum_gradients_x.shape)))
print(np.allclose(sum_gradients_y, np.zeros(sum_gradients_y.shape)))
print(np.allclose(sum_gradients_z, np.zeros(sum_gradients_z.shape))) Output
I am not sure why librascal output it this way but it seems to be the solution to the problem. This needs to be definitely better documented |
Small update, I tried if the same thing happens for a nonghost atoms (within the cell) and here one does not need to include the direction vector. So it is inconsistent behavior with respect to the ghosts which is a bit worrisome import ase
from ase import build
import numpy as np
from rascal.representations import SphericalExpansion
se = SphericalExpansion(
interaction_cutoff=1.1,
cutoff_smooth_width=0.5,
max_radial=6,
max_angular=6,
gaussian_sigma_type="Constant",
gaussian_sigma_constant=0.3,
radial_basis="GTO",
compute_gradients=True,
)
frame = ase.Atoms('HHHHHHH', positions=[(1,1,1),(0.5,1,1),(1.5,1,1),(1,0.5,1),(1,1.5,1),(1,1,0.5),(1,1,1.5)], pbc=[False,False,False], cell=[2,2,2])
representation = se.transform(frame)
gradients = representation.get_features_gradient(se)
info = representation.get_gradients_info()
# shape (n_atoms*(n_neigh[i]+1)*xyz, n_feat)
# chose gradients corresponding to the atom in the middle of the two
# middle atom is at the beginning and has shape (6 [neighbours] + 1 [self contribution]) * 3 [xyz] = 21
print("x close to 0", np.allclose(np.sum(gradients[0:21][0::3]),0))
print("y close to 0", np.allclose(np.sum(gradients[0:21][1::3]),0))
print("z close to 0", np.allclose(np.sum(gradients[0:21][2::3]),0)) Output
|
Hello, @Luthaf do you still get an error when you increase the cutoff as you suggested in your first response? I don't get it and I checked the gradient provider in the tests it seems to ignore ghost atoms when computing the analytical gradients. It seems that the fix of issue #115 is related to this, // gives you always the within-cell atom tag of atom j
auto atom_j_tag = atom_j.get_atom_tag(); to // gives you always the tag of the j atom, even if j is ghost
auto atom_j_tag = neigh.get_atom_tag(); then the python script gives me zero without the contribution of direction vector, but the cpp tests fail for this periodic one-atom structure above. Since it seems to me that the the gradient provider |
Running the code below prints
False
, but I would expect it to printTrue
.This construct a structure containing a single atom, and then try to compute the spherical expansion using a large cutoff, meaning the atom have a lot of neighbors, all being periodic images of itself.
I'm wondering whether this is related to #324 (comment): there are also duplicated entries inside the gradients (the gradient shape is
(141, 3, 294)
while I would expect it to be(1, 3, 294)
since there is one environment with only one neighbor).Changing the cutoff in related tests to 5.5 (from 2.5) make the tests fail, so I'm relatively sure this is a bug.
https://github.com/cosmo-epfl/librascal/blob/43a410c6d7cea3d17852e9c8c6fe332ec46f13df/tests/test_calculator.hh#L428
The text was updated successfully, but these errors were encountered: