Setup magnetic entites and pairs
There are many different systems, where the magnetic entities can be very different. Sometimes it is just one atom from the cell, sometimes it is one element and sometimes it is a cluster of atoms, a quasi-molecule. grogupy can handle all these different systems and provide a hopefully intuitive way to autoamtically generate the pairs.
[10]:
import grogupy
import grogupy.viz
################################################################################
# this is just for the html export of interactive figures, but it is not part of
# grogupy
import plotly
plotly.offline.init_notebook_mode()
################################################################################
Simple systems, with one magnetic element
Let’s start by setting up a Builder instance from the CrI3 benchmark as shown in the Calculate Magnetic Parameters tutorial.
[11]:
CrI3_path = "./../../../benchmarks/CrI3/CrI3.fdf"
CrI3 = grogupy.Builder()
CrI3.add_kspace(grogupy.Kspace(kset=[21, 21, 1]))
CrI3.add_contour(grogupy.Contour(eset=100, eigfile=CrI3_path))
CrI3.add_hamiltonian(grogupy.Hamiltonian(CrI3_path))
CrI3
Setting up Hamiltonian: 100%|██████████| 147/147 [00:00<00:00, 1170.90it/s]
[11]:
<grogupy.Builder npairs=0, numk=441, kset=[21 21 1], eset=100>
In case of a simple system like this, where only the Cr atoms are magnetic we can set up the magnetic entities and pairs automatically, by defining a range for the pairs and the subset of atoms we want to use.
[12]:
CrI3.setup_from_range(R=20, subset="Cr")
print(CrI3.magnetic_entities)
print(CrI3.pairs[:2])
Add magnetic entities: 100%|██████████| 2/2 [00:00<00:00, 32.97it/s]
Add pairs: 100%|██████████| 114/114 [00:00<00:00, 13500.98it/s]
[<grogupy.MagneticEntity tag=0Cr(l:All), SBS=30>
<grogupy.MagneticEntity tag=1Cr(l:All), SBS=30>]
[<grogupy.Pair tag1=0Cr(l:All), tag2=0Cr(l:All), Ruc=[-3 -2 0]>
<grogupy.Pair tag1=0Cr(l:All), tag2=0Cr(l:All), Ruc=[-3 -1 0]>]
We have to take into account, that some orbitals are more localized, than others and the approximation of the Heisenberg model works better, if we only take into account these localized orbitals. we can define them by indexing directly from the atom, but this needs an in depth knowledge about the basis of the Hamiltonian. Instead we could simply choose the shell of orbitals, in this case the d orbitals.
[13]:
CrI3.setup_from_range(R=20, subset="Cr", l=2)
print(CrI3.magnetic_entities)
print(CrI3.pairs[:2])
Add magnetic entities: 100%|██████████| 2/2 [00:00<00:00, 69.87it/s]
Add pairs: 100%|██████████| 114/114 [00:00<00:00, 5591.03it/s]
[<grogupy.MagneticEntity tag=0Cr(l:2), SBS=20>
<grogupy.MagneticEntity tag=1Cr(l:2), SBS=20>]
[<grogupy.Pair tag1=0Cr(l:2), tag2=0Cr(l:2), Ruc=[-3 -2 0]>
<grogupy.Pair tag1=0Cr(l:2), tag2=0Cr(l:2), Ruc=[-3 -1 0]>]
The setup_from_range method takes keyword arguments, when it defines the magnetic entities. For more information on what is possible take a look at the MagneticEntity class in the API reference. Let’s take a look at the final system.
[14]:
CrI3.plot_pairs()
Complicated systems, with molecule like magnetic entities
Triangulene are coming soon…
Defining magnetic entities and pairs by hand
If you are only interested in some specific magnetic entities and pairs, in this case the first-, second- and third neighbour, then you can define these using dictionaries. Internally all the above methods first create these dictionaries, then use them to create the MagneticEntityList and PairList of the Builder instance.
[15]:
# clear magnetic entities and pairs
CrI3.magnetic_entities = grogupy.MagneticEntityList()
CrI3.pairs = grogupy.PairList()
# use the same atoms as in the first example
magnetic_entities = [
dict(atom=[0], l=[2]),
dict(orb=[15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]),
]
pairs = [
dict(ai=0, aj=1, Ruc=[0, 0, 0]),
dict(ai=0, aj=0, Ruc=[1, 0, 0]),
dict(ai=0, aj=1, Ruc=[1, 0, 0]),
dict(ai=1, aj=0, Ruc=[0, 0, 0]),
dict(ai=1, aj=1, Ruc=[-1, 0, 0]),
dict(ai=1, aj=0, Ruc=[-1, 0, 0]),
]
CrI3.add_magnetic_entities(magnetic_entities)
CrI3.add_pairs(pairs)
Add magnetic entities: 100%|██████████| 2/2 [00:00<00:00, 67.47it/s]
Add pairs: 100%|██████████| 6/6 [00:00<00:00, 4298.18it/s]
[16]:
CrI3.plot_pairs(group=False)
The firs magnetic entity is the same as in the first example, but the second is defined by taking all the orbitals, not just the d orbitlas, from the second atom. As you can see the ‘atom’ and ‘l’ keys in the dictionary are list, so, for more complicated systems, you can define quasi-molecules with different shells. A not so physically meaningful example, where we combine a cromium, with a neighbouring iodine would look something like this.
[17]:
# clear magnetic entities and pairs
CrI3.magnetic_entities = grogupy.MagneticEntityList()
CrI3.pairs = grogupy.PairList()
# use the same atoms as in the first example
magnetic_entities = [
dict(atom=[0, 2], l=[[None], [2]]),
dict(atom=[1]),
]
pairs = [
dict(ai=0, aj=1, Ruc=[1, 0, 0]),
dict(ai=0, aj=1, Ruc=[1, 1, 0]),
dict(ai=0, aj=1, Ruc=[0, 1, 0]),
dict(ai=0, aj=1, Ruc=[-1, 1, 0]),
dict(ai=0, aj=1, Ruc=[-1, 0, 0]),
dict(ai=0, aj=1, Ruc=[-1, -1, 0]),
dict(ai=0, aj=1, Ruc=[0, -1, 0]),
dict(ai=0, aj=1, Ruc=[1, -1, 0]),
]
CrI3.add_magnetic_entities(magnetic_entities)
CrI3.add_pairs(pairs)
Add magnetic entities: 100%|██████████| 2/2 [00:00<00:00, 137.01it/s]
Add pairs: 100%|██████████| 8/8 [00:00<00:00, 24873.56it/s]
[18]:
CrI3.plot_pairs(group=False)
Here we took different shells from the chromium and iodine. If you set the atoms you could also use the ‘orb’ key, but in this case the indexing is not done directly from the Hamiltonian, but from the atomic orbitals.