Note
Go to the end to download the full example code.
Crystal structure¶
Exercises
Create a crystal structure for the material of your choosing. Create a cell and a set of atoms. Specify all mentioned properties for each atom.
(extra) Visualize your structure using
magnopy.PlotlyEngine(extra) Compute conventional and primitive cell for your structure (see
wulfric.crystal.get_primitive()andwulfric.crystal.get_conventional()). Visualize them. Are they they the same for your crystal? Shall they always be the same or not?
We will use the fictitious crystal with the lattice vectors
\(\boldsymbol{a}_1 = (5, 0, 0)\)
\(\boldsymbol{a}_2 = (0, 5, 0)\)
\(\boldsymbol{a}_3 = (0, 0, 5)\)
and a set of eight atoms
"Fe1" at (0, 0, 0) with spin value 5/2 and g-factor 2.
"Fe2" at (0.5, 0.5, 0) with spin value 5/2 and g-factor 2.
"Fe3" at (0, 0.5, 0.5) with spin value 5/2 and g-factor 2.
"Fe4" at (0.5, 0, 0.5) with spin value 5/2 and g-factor 2.
"O1" at (0.5, 0, 0) with undefined spin value and g-factor.
"O2" at (0, 0.5, 0) with undefined spin value and g-factor.
"O3" at (0, 0, 0.5) with undefined spin value and g-factor.
"O4" at (0.5, 0.5, 0.5) with undefined spin value and g-factor.
import magnopy
import wulfric
Exercise 1¶
Simple syntax¶
# Create a unit cell
cell = [
[5.0, 0.0, 0.0],
[0.0, 5.0, 0.0],
[0.0, 0.0, 5.0],
]
# Create a set of atoms
atoms = {
"names": ["Fe1", "Fe2", "Fe3", "Fe4", "O1", "O2", "O3", "O4"],
"positions": [
[0.0, 0.0, 0.0],
[0.5, 0.5, 0.0],
[0.0, 0.5, 0.5],
[0.5, 0.0, 0.5],
[0.5, 0.0, 0.0],
[0.0, 0.5, 0.0],
[0.0, 0.0, 0.5],
[0.5, 0.5, 0.5],
],
"spins": [5 / 2, 5 / 2, 5 / 2, 5 / 2, None, None, None, None],
"g_factors": [2, 2, 2, 2, None, None, None, None],
}
# Display properties of each atom
for i in range(8):
name = atoms["names"][i]
position = atoms["positions"][i]
spin = atoms["spins"][i]
g_factor = atoms["g_factors"][i]
if spin is None:
spin = "None"
if g_factor is None:
g_factor = "None"
print(f"Atom '{name}' at {position} with spin value {spin} and g-factor {g_factor}")
Atom 'Fe1' at [0.0, 0.0, 0.0] with spin value 2.5 and g-factor 2
Atom 'Fe2' at [0.5, 0.5, 0.0] with spin value 2.5 and g-factor 2
Atom 'Fe3' at [0.0, 0.5, 0.5] with spin value 2.5 and g-factor 2
Atom 'Fe4' at [0.5, 0.0, 0.5] with spin value 2.5 and g-factor 2
Atom 'O1' at [0.5, 0.0, 0.0] with spin value None and g-factor None
Atom 'O2' at [0.0, 0.5, 0.0] with spin value None and g-factor None
Atom 'O3' at [0.0, 0.0, 0.5] with spin value None and g-factor None
Atom 'O4' at [0.5, 0.5, 0.5] with spin value None and g-factor None
Advanced syntax¶
# Create a unit cell
cell = [
[5.0, 0.0, 0.0],
[0.0, 5.0, 0.0],
[0.0, 0.0, 5.0],
]
# Create a set of atoms
atoms = {
"names": [f"Fe{_ + 1}" for _ in range(4)] + [f"O{_ + 1}" for _ in range(4)],
"positions": [
[0.0, 0.0, 0.0],
[0.5, 0.5, 0.0],
[0.0, 0.5, 0.5],
[0.5, 0.0, 0.5],
[0.5, 0.0, 0.0],
[0.0, 0.5, 0.0],
[0.0, 0.0, 0.5],
[0.5, 0.5, 0.5],
],
"spins": [5 / 2 for _ in range(4)] + [None for _ in range(4)],
"g_factors": [2 for _ in range(4)] + [None for _ in range(4)],
}
# Display properties of each atom
for name, position, spin, g_factor in zip(
atoms["names"], atoms["positions"], atoms["spins"], atoms["g_factors"]
):
if spin is None:
spin = "None"
if g_factor is None:
g_factor = "None"
print(
f"Atom {f'"{name}"':>5} at {position} with spin value {spin:>4} and g-factor {g_factor:>2}"
)
Atom "Fe1" at [0.0, 0.0, 0.0] with spin value 2.5 and g-factor 2
Atom "Fe2" at [0.5, 0.5, 0.0] with spin value 2.5 and g-factor 2
Atom "Fe3" at [0.0, 0.5, 0.5] with spin value 2.5 and g-factor 2
Atom "Fe4" at [0.5, 0.0, 0.5] with spin value 2.5 and g-factor 2
Atom "O1" at [0.5, 0.0, 0.0] with spin value None and g-factor None
Atom "O2" at [0.0, 0.5, 0.0] with spin value None and g-factor None
Atom "O3" at [0.0, 0.0, 0.5] with spin value None and g-factor None
Atom "O4" at [0.5, 0.5, 0.5] with spin value None and g-factor None
Exercise 2¶
# Step 1 - create an instance of the engine
# (please ignore _sphinx_gallery_fix)
pe = magnopy.PlotlyEngine(_sphinx_gallery_fix=True)
# Step 2 - plot
pe.plot_cell(cell=cell)
# Note that cell is expected as well, as atom's positions are relative coordinates.
pe.plot_atoms(cell=cell, atoms=atoms)
# Step 3 - show
pe.show()
Exercise 3¶
Simple approach¶
# Note: default convention of HPKOT is used
conv_cell, conv_atoms = wulfric.crystal.get_conventional(cell=cell, atoms=atoms)
prim_cell, prim_atoms = wulfric.crystal.get_primitive(cell=cell, atoms=atoms)
Advanced approach¶
# Explicitly control what atoms are considered to be the same by spglib
atoms["spglib_types"] = [1, 1, 1, 1, 2, 2, 2, 2]
# Explicitly call spglib via wulfric's interface.
# Both get_conventional() and get_primitive() call spglib internally,
# thus doing double work in the simple approach.
spglib_data = wulfric.get_spglib_data(cell=cell, atoms=atoms, spglib_symprec=1e-5)
# Then use the resultto compute conventional and primitive cell
conv_cell, conv_atoms = wulfric.crystal.get_conventional(
cell=cell, atoms=atoms, spglib_data=spglib_data
)
prim_cell, prim_atoms = wulfric.crystal.get_primitive(
cell=cell, atoms=atoms, spglib_data=spglib_data
)
Plotting¶
# Please ignore _sphinx_gallery_fix
pe = magnopy.PlotlyEngine(_sphinx_gallery_fix=True)
pe.plot_cell(cell=cell, legend_label="Original cell", color="#FD4837")
pe.plot_atoms(cell=cell, atoms=atoms, legend_label="Atoms of the original cell")
pe.plot_cell(cell=conv_cell, legend_label="Conventional cell", color="#2F58FE")
pe.plot_atoms(
cell=conv_cell,
atoms=conv_atoms,
legend_label="Atoms of the conventional cell",
colors=["#2F58FE" for _ in range(8)],
)
pe.plot_cell(cell=prim_cell, legend_label="Primitive cell", color="#0E7634")
pe.plot_atoms(
cell=prim_cell,
atoms=prim_atoms,
legend_label="Atoms of the primitive cell",
colors=["#0E7634" for _ in range(8)],
)
pe.show(axes_visible=False, legend_position="left")
No, conventional and primitive cell are not necessarily the same. It will depend on the space group of the crystal and on the convention that is used to define conventional and primitive cell, see wulfric: Bravais lattices for more examples.
Moreover, input unit cell can be different from both conventional and primitive ones (consider a super-cell as an input cell, for example).
Note
Space group is detected via spglib. In general, the result depends on what atoms
are considered to be equivalent. Magnopy guesses spglib_types based on the
atoms["names"] via wulfric (see wulfric.get_spglib_types() to see
how exactly the guess is implemented).
Total running time of the script: (0 minutes 0.186 seconds)