SpinW / spinw

SpinW Matlab library for spin wave calculation
http://www.spinw.org
GNU General Public License v3.0
35 stars 15 forks source link

Add vispy plotting of crystal structure to pyspinw #161

Closed RichardWaiteSTFC closed 7 months ago

RichardWaiteSTFC commented 9 months ago

Class to plot supercells with atoms, bonds and magnetic structures (in rotating frame representation only - i.e. from spinw.magstr) instantiated with a spinw object

To Test

Test the following systems with multiple and non-integer unit cells along different direction.

(1) Plot magnetic structure (and rotation plane of moment) of a triangular AFM over multiple unit cells

import numpy as np
from pyspinw import Matlab
from pyspinw.plotting import *

m = Matlab(matlab_version='R2022b', matlab_path=r'C:\Program Files\MATLAB\R2022b')

# Create a spinw model, in this case a triangular antiferromagnet
s = m.sw_model('triAF', 1)

super_cell = SuperCell(m, s, extent=(2,1,1), plot_mag=True, plot_bonds=True, plot_atoms=True, plot_cell=True, plot_axes=True, plot_plane=True, ion_type="aniso")
super_cell.plot()

image

(2) Plot single-ion anisotropy ellipsoid (example from tutorial 32)

s=m.spinw();
s.genlattice('sym','P 4','lat_const',[8, 8, 6])
s.addatom('r',[1/4, 1/4, 0],'S',1)
s.gencoupling()
s.addmatrix('label','A','value',1-np.eye(3))
s.addaniso('A')

super_cell = SuperCell(m, s, extent=(2,1,1), plot_mag=True, plot_bonds=True, plot_atoms=True, plot_cell=True, plot_axes=True, plot_plane=True, ion_type="aniso")

super_cell.plot()

image

(3) Plot multiple DM bonds (example taken from tutorial 32)

s = m.spinw();
s.genlattice('lat_const',[6, 4, 4],'sym','-x,y,z','label','m_x') # 'angled',[90 90 120],
s.addatom('r',[0.3, 0.5, 0.5],'S',1)  # [3/8, 1/2, 1/2]
s.gencoupling('maxDistance', 6)
s.addmatrix('label','DM1','value',[0, 0, 1],'color','blue')
s.addmatrix('label','DM2','value',[0, 1, 0],'color','purple')
s.addcoupling('mat','DM1','bond',1)
s.addcoupling('mat','DM2','bond',1)
super_cell = SuperCell(m, s, extent=(1,1,1), plot_mag=True, plot_bonds=True, plot_atoms=True, plot_cell=True, plot_axes=True, plot_plane=True, ion_type=None)
super_cell.arrow_head_size += 4
super_cell.plot()

image

(4) Plot unit cell with no bonds, but different sized atoms (and atoms of same type with different labels)

luvo = m.spinw();
luvo.genlattice('lat_const',[5.2821, 5.6144, 7.5283], 'spgr','x+1/2,-y+1/2,-z; -x,-y,z+1/2; -x,-y,-z','label','P n m a')
luvo.addatom('r',[0.003, 0.031, 1/4],'label','Lu1 Lu3+','color',[0, 171, 36])
luvo.addatom('r',[1/2, 0, 0],'label','V1 V3+','S',1,'color',[166, 166, 171])
luvo.addatom('r',[0.082, 0.487, 1/4],'label','O1 O2-','color',[255, 13, 13])
luvo.addatom('r',[0.223, 0.216, 0.534],'label','O2 O2-','color',[255, 13, 13])
super_cell = SuperCell(m, luvo, extent=(1,1,1), plot_mag=True, plot_bonds=True, plot_atoms=True, plot_cell=True, plot_axes=True, plot_plane=True, ion_type=None)
super_cell.plot()

image

(5) Add polyhedra to luvo example above like so

polyhedra_args = PolyhedraArgs(atom1_idx=2, atom2_idx=[3,4], color="yellow", n_nearest=6)
super_cell = SuperCell(m, luvo, extent=(1,1,1), plot_mag=True, plot_bonds=True, plot_atoms=True, plot_cell=True, plot_axes=True, plot_plane=True, ion_type=None, polyhedra_args=polyhedra_args)

image

(6) Plot luvo with a complicated-ish magnetic structure (and compare to existing MATLAB)

luvo.genmagstr('mode', 'helical', 'S', np.array([1.0,0,0])[:,None], 'k',[0.5,0,0.5], 'n', [0, 0, 1])

super_cell = SuperCell(m, luvo, extent=(2,1,1), plot_mag=True, plot_bonds=True, plot_atoms=True, plot_cell=True, plot_axes=True, plot_plane=False, ion_type=None)

image

(7) Plot 2D polygons in 3D

s = m.spinw();
s.genlattice('lat_const',[4, 4, 8],'sym','I 4')
s.addatom('r',[0, 0, 0],'label','atom1','color',[0, 171, 36]);
s.addatom('r', [0.5, 0 , 0],'label','atom2', 'color',[255, 13, 13])
polyhedra_args = PolyhedraArgs(atom1_idx=1, atom2_idx=2, color="yellow", n_nearest=4)
super_cell = SuperCell(m, s, extent=(1,1,1), plot_mag=True, plot_bonds=True, plot_atoms=True, plot_cell=True, plot_axes=True, plot_plane=True, ion_type=None, polyhedra_args=polyhedra_args)
super_cell.plot()

image

(8) Any other systems you can think of!

Fixes #150

codecov-commenter commented 9 months ago

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Comparison is base (ea5ea33) 40.48% compared to head (be98824) 40.51%. Report is 4 commits behind head on master.

Additional details and impacted files ```diff @@ Coverage Diff @@ ## master #161 +/- ## ========================================== + Coverage 40.48% 40.51% +0.02% ========================================== Files 240 240 Lines 15979 15981 +2 ========================================== + Hits 6469 6474 +5 + Misses 9510 9507 -3 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

github-actions[bot] commented 9 months ago

Test Results

    4 files  ±0    106 suites  ±0   14m 18s :stopwatch: + 1m 9s   619 tests ±0    619 :white_check_mark: +1  0 :zzz: ±0  0 :x:  - 1  1 766 runs  ±0  1 766 :white_check_mark: +2  0 :zzz: ±0  0 :x:  - 2 

Results for commit be988244. ± Comparison against base commit 735d30a0.

:recycle: This comment has been updated with latest results.

RichardWaiteSTFC commented 8 months ago

Can now plot single-ion ellipsoids - this example is adapted from tutorial 32

s=m.spinw();
s.genlattice('sym','P 4','lat_const',[8, 8, 6])
s.addatom('r',[1/4, 1/4, 0],'S',1)
s.gencoupling()
s.addmatrix('label','A','value',1-np.eye(3))
s.addaniso('A')

super_cell = SuperCellSimple(s, extent=(2,1,1), plot_mag=True, plot_bonds=True, plot_atoms=True, plot_cell=True, plot_axes=True, plot_plane=True, ion_type="aniso")

super_cell.plot()

image

There is a small difference compared to the current MATLAB plotting image which scales the eigenvalues such that hard-axis is squashed to 0 - I can do this if required but it seems misleading?

RichardWaiteSTFC commented 8 months ago

Supports DM bonds now - but think I need to get the arrows to terminate before entering the atom marker. Example adapted from tutorial 32

s = m.spinw();
s.genlattice('lat_const',[6, 4, 4],'sym','-x,y,z','label','m_x') # 'angled',[90 90 120],
s.addatom('r',[0.3, 0.5, 0.5],'S',1)  # [3/8, 1/2, 1/2]
s.gencoupling('maxDistance', 6)
s.addmatrix('label','DM1','value',[0, 0, 1],'color','blue')
s.addmatrix('label','DM2','value',[0, 1, 0],'color','purple')
s.addcoupling('mat','DM1','bond',1)
s.addcoupling('mat','DM2','bond',1)
super_cell = SuperCellSimple(s, extent=(2,1,1), plot_mag=True, plot_bonds=True, plot_atoms=True, plot_cell=True, plot_axes=True, plot_plane=True, ion_type=None)
super_cell.plot()

image

Compared to existing MATLAB image

RichardWaiteSTFC commented 8 months ago

Have now put arrow along DM bond at mid-point for now image

mducle commented 8 months ago

Thanks. Plotting things as a single mesh seems to have speed up by a factor of 2-3x. Plotting a 5x5x5 supercell of the triAF model used to take ~15s with the original code, ~10s with the code which eliminated the UnitCellSimple copies and now takes ~5s with the single mesh.