Efficient management of interacting atoms based on their mutual distance
5 views (last 30 days)
Show older comments
Dear all
Currently, I am dealing with a dataset, which I attach here in the "File.txt", file, where the first column is an atomic label ranging from 0 to 95900 (that it is, to the number of atoms-1). Each row represents the spatial coordinates of each i-th atom of the system, denoting the second, third, and fourth columns the coordinate values, in Angstroms, along x-, y-, and z-th directions. It is important to note that the fourth column, that it is, the z-th spatial coordinate, only can have two different values, 3.27645 and 9.82515. So basically, I have two monolayers at two different heights.
My goal is, for each atom, to loop over the first ten nearest interlayer atoms. That it is, for the i-th atom, to loop over the atoms with the lowest deviations in the xy plane from (xi,yi) and with different value of the z-th component. Importantly, if, for example, during the looping one founds that atom with id 4 and 560 have in common the atom with 1100 as one of the ten nearest neighbors to them, it would be very desirable that when looping in for 1100, the program knows, from the previous calculations, that atoms with label 4 and 560 are indeed two of the ten nearest neighbors to 1100.
I had in mind something like:
file=readmatrix('File.txt');
counter=0;
for i=1:length(file(:,1))
indices=file(file(:,4)~=file(i,4));
atoms=file(indices,1:3);
for j=1:length(indices)
distances(j)=norm(atoms(j,2:3)-file(i,2:3)); % Angstroms
end
sorted_distances=unique(distances); % Angstroms
interacting_distances=sorted_distances(1:10); % Angstroms
interacting_atoms=find(distances<=max(interacting_distances));
for j=1:length(interacting_atoms(:,1))
counter=counter+1;
interaction_list(counter,1)=file(i,1); % i-th atom id
interaction_list(counter,2)=interacting_atoms(j,1); % j-th atom id
interaction_list(counter,3)=somevalue;
end
clear indices distances sorted_distances interacting_distances interacting_atoms
end
Obviously, this approach does not seem to be very fast/efficient. Also, this won't meet one of the requirements I explained above: that if one finds that i-th atom interacts with j-th atom, one knows that j-th atom interacts with i-th atom (double counting). In that case, I would need to save in the interaction_list(counter,3)=-somevalue. If, for example, during the looping atom with atom id 30500 it was already identified as one of the ten nearest interlayer neighbors of ten different atoms, it would be desirable that, when i=30500+1, MatLab does proceed to look for the ten nearest interlayer neighbors, since they have been already identified before!
Any idea?
0 Comments
Answers (1)
John D'Errico
on 31 Jul 2024
Edited: John D'Errico
on 31 Jul 2024
No. It is NOT true that in a set, if atom x is one of the k closest atoms to atom y, that the converse is also true, i.e., that atom y is one of the k closest atoms to atom x. You seem to want to make that assumption, and it is patently false. We need only consider a trivial counter-exmple. This works in 1 dimension as a counter-example, but it would also apply to higher dimensions.
x = [0,10:15];
In the vector x, what are the three nearest neighbors to 0? Clearly that are the elements [10,11,12]. But 0 is NOT one of the three nearest neighbors to any of the numbers 10, 11, or 12.
Nearest neighbor-ness does not commute.
Anyway, the simple solution would seem to be to use tools like knnsearch, or, better yet, KDtreeSearcher. Then you will be able to create a kd-tree, and then search it repeatedly.
help KDTreeSearcher
2 Comments
John D'Errico
on 1 Aug 2024
If you want to search within a plane, then build a series of kd-trees, one for each plane. You may need to reduce your data then to 2-dimensions, but at that point, the problem is essenitally already 2-dimensional.
See Also
Categories
Find more on Particle & Nuclear Physics in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!