Author Topic: Geometrical optimization of a TwoProbe system  (Read 3213 times)

0 Members and 1 Guest are viewing this topic.

Offline BandTheory

  • Heavy QuantumATK user
  • ***
  • Posts: 26
  • Reputation: 0
    • View Profile
Geometrical optimization of a TwoProbe system
« on: February 13, 2009, 22:27 »
First post here.

I have a bit of a question. I am trying to optimize a two probe system.  The manual says you must indicate the indices for those that will not move.  What are these indices ? 

If I have to define them, what is the best way to do so if I have a big bunch of atoms of the same type, like in a nanotube, but only wish to optimize a few of them? To be clear, I am referring to the atoms in the scattering region.

Thanks in advance,

BT

 

Offline Anders Blom

  • QuantumATK Staff
  • Supreme QuantumATK Wizard
  • *****
  • Posts: 5429
  • Country: dk
  • Reputation: 89
    • View Profile
    • QuantumATK at Synopsys
Re: Geometrical optimization of a TwoProbe system
« Reply #1 on: February 13, 2009, 23:58 »
Welcome aboard! The "indices" are integer numbers, corresponding to the list of atoms given as the scattering region in the two-probe configuration. The first atom in this list is index 0, and so on. To select many atoms, you can create the list from functions like "range" or "arange" (requires import of numpy). Lists have methods "insert" and "remove", so you can put in all atoms at first and then just remove a few. You can also easily concatenate lists. Note that range(a,b) returns a list with [a,a+1,a+2,...,b-1]. Thus, for instance, if we have 20 atoms, and wish to select the first 10 atoms and the last 5 (but no others), you can use
Code
ix = range(0,11) + range(15,20)
"ix" is the variable we then pass to the keyword geometric_constraints. If we want to only allow one specific atom (say, number 12, being the 13th atom in the list) to move in the relaxation, we use
Code
ix = range(0,20)
ix.remove(12)
You can make various, complex combinations of lists this way. We can also use numpy's arange, if we want to select, say, every second atom:
Code
import numpy
ix = numpy.arange(0,20,2)
To avoid mistakes, by counting the number of atoms by hand, you can also extract the number of atoms directly from the two-probe configuration. Let's say we have a two-probe configuration where all atoms except the 15th (index 14) should be fixed:
Code
twoprobe_configuration = TwoProbeConfiguration()
...
N = len(twoprobe_configuration.cartesianCoordinates())
ix = range(N)    # range(N) = range(0,N)
ix.remove(14)
For a more advanced example, imagine we wish to relax a structure, keeping all Carbon atoms fixed.
Code
twoprobe_configuration = TwoProbeConfiguration()
...
import numpy
ix = range(len(twoprobe_configuration.cartesianCoordinates()))
elements = numpy.array(twoprobe_configuration.elements())
for r in numpy.where(elements!=Carbon)[0]:
    ix.remove(r)
Note the [ 0 ] after "where"! The "where" command is very powerful. It also supports set unions, which is useful in case we want to keep all Gold and Carbon atoms fixed:
Code
twoprobe_configuration = TwoProbeConfiguration()
...
import numpy
ix = range(len(twoprobe_configuration.cartesianCoordinates()))
elements = numpy.array(twoprobe_configuration.elements())
for r in numpy.where((elements!=Carbon) & (elements!=Gold))[0]:
    ix.remove(r)
Here the extra set of parenthesis around the != statements are crucial! All of this applies, of course, equally to relaxations of molecules and bulk systems, and it's also the same when you select atoms for MPSH projection. NOTE: Normally in Python you can use negative indices to count backwards in a list. ATK does, however, not support that notation for the constrained atoms. If you specify negative indices in the list, they will simply be ignored (actually that's a small design flaw, it should raise an error or count backwards, not just silently ignore the negative values...).
« Last Edit: February 14, 2009, 00:00 by Anders Blom »