# Internal data structure of SpinW

Import the LiCrO2 crystal structure from a web link. It has space group R-3m, rhombohedrl crystal structure in hexagonal settings. What is the density? Where does all the data comes from? edit atom.dat

## Get the lattice

```licro = spinw('https://raw.githubusercontent.com/SpinW/Models/master/cif/licro2.cif');

licro.formula
```
```     Chemical formula:  Cr1Li1O2
Formula mass:        90.936 g/mol
Formula in cell:          3 units
Cell volume:        105.178 Å³
Density:              4.307 g/cm³
```

## Check out internal data structure of SpinW

What do you see?

```properties(spinw)

licro.lattice
```
```Properties for class spinw:

lattice
unit_cell
twin
matrix
single_ion
coupling
mag_str
unit
cache

ans =

struct with fields:

angle: [1.5708 1.5708 2.0944]
lat_const: [2.9010 2.9010 14.4311]
sym: [3×4×36 double]
origin: [0 0 0]
label: 'R -3 m H'

```

## Test cordinate transformations

Convert (1,1,0) in the reciprocal lattice of LiCrO2 to A^-1 and convert (1,0,0) in lattice units to the crystal Descartes coordinate system (denoted by xyz in SpinW).

How are Trl and Tr related?

```Trl = licro.rl;
Q = [0 1 0];
QinvA = Q*Trl

Tl = licro.basisvector;
pos = [1;0;0];
RA = Tl*pos
```
```QinvA =

0    2.5009   -0.0000

RA =

2.9010
0
0

```

## Rotate a vector

Using the rotation axis and Rotation angle in degree, the sw_rotmatd can generate the corresponding rotation matrix.

```R = sw_rotmatd([0 0 1],60);

% Rotate polar vector
R*pos
```
```ans =

0.5000
0.8660
0

```

## Magnetic atoms

Can you find the magnetic atom positions on the plot and connect them to the list in mAtom and in licro.unit_cell?

```plot(licro)
mAtom = licro.matom
```
```mAtom =

struct with fields:

r: [3×3 double]
idx: [2 2 2]
S: [1.5000 1.5000 1.5000]

```

## Space groups

Check out symmetry.dat: What does it mean P0~=P1? In case P0 the equivalent bonds are determined based on length, while for P1 (or any other space group), the equivalent bonds are determined based on the symmetry operators.

```edit symmetry.dat
```

## Bond symmetry

Generate the bond list of LiCrO2. Are the bonds generated usign the space group? What does it mean?

```licro.gencoupling

% The first neighbor bonds
licro.table('bond',1)
```
```ans =

9×10 table

idx    subidx          dl                dr          length      matom1      idx1      matom2      idx2        matrix
___    ______    ______________    ______________    ______    __________    ____    __________    ____    ______________

1       1       -1    -1     0    -1    -1     0    2.901     'Cr1 Cr3+'     2      'Cr1 Cr3+'     2      ''    ''    ''
1       2        0     1     0     0     1     0    2.901     'Cr1 Cr3+'     2      'Cr1 Cr3+'     2      ''    ''    ''
1       3        1     0     0     1     0     0    2.901     'Cr1 Cr3+'     2      'Cr1 Cr3+'     2      ''    ''    ''
1       4        1     1     0     1     1     0    2.901     'Cr1 Cr3+'     3      'Cr1 Cr3+'     3      ''    ''    ''
1       5        0    -1     0     0    -1     0    2.901     'Cr1 Cr3+'     3      'Cr1 Cr3+'     3      ''    ''    ''
1       6       -1     0     0    -1     0     0    2.901     'Cr1 Cr3+'     3      'Cr1 Cr3+'     3      ''    ''    ''
1       7        1     1     0     1     1     0    2.901     'Cr1 Cr3+'     1      'Cr1 Cr3+'     1      ''    ''    ''
1       8        0    -1     0     0    -1     0    2.901     'Cr1 Cr3+'     1      'Cr1 Cr3+'     1      ''    ''    ''
1       9       -1     0     0    -1     0     0    2.901     'Cr1 Cr3+'     1      'Cr1 Cr3+'     1      ''    ''    ''

```

## Lets do something crazy

Lets convert the hexagonal cell to the primitive cell and see what happens.

Why copy()? The spinw object is handle object, the copy() command creates a hard copy to avoid modifying the original object. Check spinw.formula() to see how much the new cell is smaller

```licroR = copy(licro);
T = licroR.newcell('bvect',{[-1 1 1]/3 [2 1 1]/3 [-1 -2 1]/3})
plot(licroR,'cellMode','outside')
swplot.zoom(1.5)
```
```T =

-0.3333    0.3333    0.3333
0.6667    0.3333    0.3333
-0.3333   -0.6667    0.3333

```

## Lets add a few matrices

What does the different input do? Check the result by inspecting the licro.matrix.mat array.

```licro.addmatrix('label','J','value',1)
```

## Lets add some matrices and plot

Do both for the primitive and the hexagonal cell Are they the same?

```licroR.gencoupling
plot(licroR,'range',[3 3 3],'unit','lu','atomMode','mag','cellMode','none','atomLegend',false)
swplot.zoom(1.5)
```

## Plot a single triangular layer from LiCrO2

```licro.addcoupling('bond',1,'mat','J')
plot(licro,'range',[15 15 5],'unit','xyz','atomMode','mag','cellMode','none','atomLegend',false)
```

## Single ion properties

Assing the A matrix to single ion anisotropy.

```licro.addaniso('A')
plot(licro)
```

## Magnetic structure

Lets start with a simpler lattice: square lattice. Define a (1/2,1/2,0) magnetic structure using complex magnetization vectors.

What does [1-1i;1+1i;0] vector means? These are the complex magnetization vectors. SpinW 3.0 stores complex magnetization vectors internally and generates the real magnetic structure on the fly.

How is this stored in the spinw object? check spinw.mag_str and check spinw.magstr for the generated real structure.

Let's create a magnetic supercell! 2x2x1 cell What will be the k-vector now? (1/2,1/2,0) or (1,1,0)? They are indeed equivalent.

To check that we are doing the right thing, we will keep track of the enrgy of the system, after adding a J=1 meV Heisenberg exchange on the square lattice. To create Heisenberg Hamiltonian quickly we use square.quickham(1.25), to create the first neighbor bonds with J=1.25 meV.

What was the energy/spin for the original magnetic structure? S=1, J = 1.25 meV?

```square = sw_model('squareAF');
plot(square,'range',[2 2 1/2])

square.genmagstr('mode','direct','S',[1-1i;1+1i;0],'k',[1/2 1/2 0],'nExt',[1 1 1])
plot(square,'range',[2 2 1/2])

square.quickham(1)

square.energy

% Create supercell, which k-vector is right? k is always in the units of
% the crystal reciprocal lattice!

square.genmagstr('mode','direct','S',[1 -1 -1 1;0 0 0 0;0 0 0 0],'nExt',[2 2 1],'k',[0 0 0])
square.energy

square.genmagstr('mode','direct','S',[1 -1 -1 1;0 0 0 0;0 0 0 0],'nExt',[2 2 1],'k',[1/2 1/2 0])
square.energy
```
```Ground state energy: -2.000 meV/spin.
Ground state energy: -2.000 meV/spin.
Ground state energy: -2.000 meV/spin.
```

## Rotating frame representation

Let's generate a spiral using the J1-J2 model of a zig-zag chain. Check the spinw.mag_str and spinw.magstr and compare them.

```ch = spinw;
ch.genlattice('lat_const',[3 5 4])
ch.quickham([1 1/2])

ch.optmagk
ch.optmagsteep
ch.energy

plot(ch,'range',[5 1 1/2])
```
```ans =

struct with fields:

k: [3×1 double]
E: -0.7500
F: [3×2 double]
stat: [1×1 struct]

Warning: Some spins are coupled to themselves in the present magnetic cell!
Ground state energy: -0.750 meV/spin.
```

## Let's do some animation by rotating the moments

```for ii = 1:100
ch.genmagstr('mode','rotate','n',[0 0 1],'phid',1)
swplot.plotmag('range',[5 1 1/2])
drawnow
end
```

## Check the spin wave dispersion

```spec = ch.spinwave({[0 0 0] [1 0 0] 501});
spec = sw_egrid(spec);
spec = sw_instrument(spec,'dE',0.1);
figure
sw_plotspec(spec,'mode','color')
legend off

% Plot the neutron scattering cross section per spin wave mode.
figure
spec = sw_omegasum(spec,'zeroint',1e-5,'tol',1e-3);
sw_plotspec(spec,'mode','int','axLim',[0 5],'colormap',[0 0 0])
```
```Warning: To make the Hamiltonian positive definite, a small omega_tol value was
```

## Case when the rotating frame representation fails

We show here what happens when there are counterrotating spirals.

```ch = spinw;
ch.genlattice('lat_const',[3 7 4])

ch.gencoupling

optRes = ch.optmagk;
plot(ch,'range',[5 1 1/2])

% Rotating frame representation fails!
ch.magstr

% Lets check how the structure would look like in a magnetic supercell.
ch.magstr('nExt',[4 1 1])

% Let's generate this supercell and keep it.
ch.genmagstr('mode','helical','nExt',[4 1 1])

% Let's check the energy if we are right, -1 meV/spin looks fine.
ch.energy
```
```Warning: Convergence is not reached!
Warning: The stored magnetic structure does not have an exact representation in
the rotating frame formalism!

ans =

struct with fields:

S: [3×2 double]
k: [0.7501 0 0]
n: [0 1 0]
N_ext: [1 1 1]
exact: 0

Warning: The stored magnetic structure does not have an exact representation in
the rotating frame formalism!

ans =

struct with fields:

S: [3×8 double]
k: [0.7501 0 0]
n: [0 1 0]
N_ext: [4 1 1]
exact: 0

Warning: In the extended unit cell k is still larger than epsilon!
Warning: The stored magnetic structure does not have an exact representation in
the rotating frame formalism!
Ground state energy: -1.000 meV/spin.
```