sisl icon indicating copy to clipboard operation
sisl copied to clipboard

Bond completion (or saturation)

Open tfrederiksen opened this issue 4 years ago • 12 comments

The proposal of a nanoribbon geometry (#201) with edge-saturated atoms opened the idea to have more generally a method to complete bonds in geometries by adding extra atoms. This branch strives to achieve this.

tfrederiksen avatar Apr 03 '20 01:04 tfrederiksen

Codecov Report

Merging #202 into master will decrease coverage by 0.13%. The diff coverage is 6.25%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #202      +/-   ##
==========================================
- Coverage   85.23%   85.10%   -0.14%     
==========================================
  Files         121      121              
  Lines       19367    19398      +31     
==========================================
+ Hits        16507    16508       +1     
- Misses       2860     2890      +30     
Impacted Files Coverage Δ
sisl/geometry.py 85.37% <6.25%> (-1.55%) :arrow_down:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 07fa7aa...a5f5d11. Read the comment docs.

codecov[bot] avatar Apr 03 '20 01:04 codecov[bot]

Thanks for the MR! Sorry for the late return. However, your request spawned an idea I would like some feedback on. Once that is in, your saturation feature could be generalized based on atomic categories ;-) and thus work for any system, including bulk surfaces etc. ;)

zerothi avatar May 07 '20 10:05 zerothi

Hey! Can I update this PR to use categories so that it can be merged? It would help me with something that I need to do and I'd rather do it with an implementation in sisl than with some script in my computer that I won't be able to find in the future :) (Also, I'm sure it can be very useful for other people)

pfebrer avatar Aug 12 '20 16:08 pfebrer

Now that we are updating things in categories, I think for this (and maybe other cases) it could be very useful that categories had an apply method that will execute a function for each atom that is in the category. Otherwise, I believe categories don't add much in this case because you need to do 2 loops: one for finding atoms with less than X neighbours and another one for acting on those atoms (and you need to calculate the neighbours again).

Any ideas how this could be made efficient?

pfebrer avatar Aug 14 '20 12:08 pfebrer

Hey! Can I update this PR to use categories so that it can be merged? It would help me with something that I need to do and I'd rather do it with an implementation in sisl than with some script in my computer that I won't be able to find in the future :) (Also, I'm sure it can be very useful for other people)

Yes, please try out this :)

Now that we are updating things in categories, I think for this (and maybe other cases) it could be very useful that categories had an apply method that will execute a function for each atom that is in the category. Otherwise, I believe categories don't add much in this case because you need to do 2 loops: one for finding atoms with less than X neighbours and another one for acting on those atoms (and you need to calculate the neighbours again).

I think this should be carefully thought through. Problem is that if you start changing the geometry state while holding a list of indices etc, stuff may change unexpectedly. For now, I think we should not go this route and just settle with double calculation of neighbours. FYI, I initially did categories by storing state (number of neigbours, etc.), but that turned out to be extremely ugly and require quite a bit of documentation for end-users to extend. Hence I quickly abandoned it since it would mean that categories should ship with lots of secondary data.

zerothi avatar Aug 17 '20 07:08 zerothi

@tfrederiksen I hope it is ok if Pol takes a shot at this? Otherwise, chip in ;)

zerothi avatar Aug 17 '20 08:08 zerothi

No problem! :)

tfrederiksen avatar Aug 17 '20 10:08 tfrederiksen

Problem is that if you start changing the geometry state while holding a list of indices etc, stuff may change unexpectedly.

Why do you need to change the state of the geometry?

I was thinking something like:


def saturate(...):
    new_ats = []
    new_xyz = []

    def get_saturating_ats(...):
         ...calculate the new positions # this will only run for those atoms that fall in the defined category
         new_ats.append(...)
         new_xyz.append(...)

    AtomCategory(neighbours=2).apply(get_saturating_ats)

   return geom + Geometry(new_xyz, new_ats)

However it's hard to figure out what to do when you want to apply on a composite category, because you may need the information that comes from all the categories, and that's probably where you need this

I initially did categories by storing state

:confused:

pfebrer avatar Aug 17 '20 10:08 pfebrer

No problem! :)

@tfrederiksen I need permission to push to the branch to be able to update the PR :)

pfebrer avatar Aug 17 '20 12:08 pfebrer

No problem! :)

@tfrederiksen I need permission to push to the branch to be able to update the PR :)

Create a new one :) Much easier, just write it superseeds this one in the PR

zerothi avatar Aug 17 '20 12:08 zerothi

Ok!

pfebrer avatar Aug 17 '20 12:08 pfebrer

Problem is that if you start changing the geometry state while holding a list of indices etc, stuff may change unexpectedly.

Why do you need to change the state of the geometry?

I was thinking something like:

def saturate(...):
    new_ats = []
    new_xyz = []

    def get_saturating_ats(...):
         ...calculate the new positions # this will only run for those atoms that fall in the defined category
         new_ats.append(...)
         new_xyz.append(...)

    AtomCategory(neighbours=2).apply(get_saturating_ats)

   return geom + Geometry(new_xyz, new_ats)

However it's hard to figure out what to do when you want to apply on a composite category, because you may need the information that comes from all the categories, and that's probably where you need this

I initially did categories by storing state

I don't think it should be like this, probably it would be nice if the saturate method could adapt to different saturation atoms (based on the category).

Something like:

cA = AtomCategory(...) # first category
cB = AtomCategory(...) # second category
cC = AtomCategory(...) # third category
c = cA | cB | cC
saturate_atoms = dict(cA={"distance": 1.4, "atom": Atom[3]}, cB={"distance": 1.5, "atom": Atom[4]}, cC=callback_function)
saturate(geometry, atoms=c, saturate_atoms=saturate_atoms)

or something similar? This was why my first response to Thomas was that it should be more general so it could be used for surfaces etc. I also don't know if saturate would be the more natural name. Perhaps it could be merged with the Geometry.add method since it adds stuff based on common things. saturate assumes "dangling" bonds which isn't necessarily the case.

zerothi avatar Aug 17 '20 12:08 zerothi