Complete when there are unit tests that covers 80% of the core calculation code.
There should be several tests which checks the code flow within the spin_wave_calculator
class dependent on input.
Object setup
For the tests, a very simple model should be used. I recommend using a linear spin chain with the spin magnitude set to 1 (e.g. like in tutorial 1:
model = spinw;
model.genlattice('lat_const', [3 8 8], 'angled', [90 90 90]);
model.addatom('r', [0 0 0],'S', 1, 'label', 'MCu1', 'color', 'blue');
model.gencoupling('maxDistance', 7);
model.addmatrix('value', -eye(3), 'label', 'Ja', 'color', 'green');
model.addcoupling('mat', 'Ja', 'bond', 1);
model.genmagstr('mode', 'direct', 'k', [0 0 0], 'n', [1 0 0], 'S', [0; 1; 0]);
This model has a particularly simple dispersion - a single mode with energy omega = 2*(1-cos(2*pi*qh))
(see Kittel, chapter 12, eq 22, but note that Kittel defines the Hamiltonian in eq 12 as -2Jsum_ij(Si.Sj) whereas in SpinW the prefactor of 2 is not included; also note that we've set the exchange integral to be 1
in the addmatrix
command).
A non-Hermitian model can be setup by changing the magnetic structure to be antiferromagnetic instead:
model.genmagstr('mode', 'direct', 'nExt', [2 0 0], 'S', [0 0; 1 -1; 0 0]);
An incommensurate model can be setup by using the fourier
mode
and changing the k
parameter:
k_incomm = 0.123;
model.genmagstr('mode', 'fourier', 'k', [k_incomm 0 0], 'n', [1 0 0], 'S', [0; 1; 0]);
Note that this would also give a non-Hermitian Hamiltonian because we have a ferromagnetic exchange interaction which would prefer all the spins to be parallel and this structure does not have that.
Possible tests
General tests for twins and incommensurate cases
- Test that twined input structures give
cell
arrays as output and number of cells match number of twins
- Test that incommensurate input structures give the correct number of output modes (6 times the number of atoms in the unit cell; a normal (commensurate) structures has
2*nMagExt
number of modes, an incommensurate structure should have three times this, so 6*nMagExt
number of modes)
More specific test for the twins case
For each twin, the user gives a 3x3 transformation matrix which is applied to the input hkl
q-vectors. A test could do something like this:
- Run through the calculation with only a single
hkl
vector (pick any 3 values) -> orig_single
output spectra
- Run the calculation again with the transformed
rotmat * hkl
vector -> transformed_single
output spectra
- Run the calculation with the original
hkl
but with the twins set -> twinned
output spectra
- Check the output
omega
field of the twinned
output spectra is a cell with two elements (one for each twin, the first being the identity)
- Compare the first element of the output
omega
field of twinned
with the omega
of orig_single
.
- Compare the second element of the output
omega
field of twinned
with the omega
of transformed_single
.
Test for the form factor option
The magnetic form factor is a hkl
-vector dependent scaling factor on the output neutron intensity. The test here would be to:
- Run the calculation with a range of
hkl
without the formfactor option set to false
-> spec_no_ff
- Run the calculation with the formfactor option set to
true
-> spec_ff
- Compare
spec_no_ff.swConv * ff
and spec_ff.swConv
.
Note, the swConv
property is only generated after running sw_egrid(sw_neutron(spectra))
.
Test that the correct calculation is run for the hermit
option
There are two different matrix diagonalisation algorithms in SpinW - one which explicit requires a positive definite matrix which is used when hermit
is true (that is, the Hamiltonian matrix must not be hermitian but its eigenvalues must also be strictly positive); and a second algorithm which works for any matrix but can give imaginary eigenvalues (e.g. unphysical spin wave energies) when the hermit
option is set to false
.
The test here is to define the input such that we are sure that Hamiltonian matrix would not be Hermitian and run the calculation with hermit
set to true
and check that it gives an error. Then run the test with hermit
set to false
and check that no error is thrown and that omega
has imaginary values.