-
Notifications
You must be signed in to change notification settings - Fork 0
Create unit tests for the refactored spinwave calculation function #9
Description
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
cellarrays 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*nMagExtnumber of modes, an incommensurate structure should have three times this, so6*nMagExtnumber 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
hklvector (pick any 3 values) ->orig_singleoutput spectra - Run the calculation again with the transformed
rotmat * hklvector ->transformed_singleoutput spectra - Run the calculation with the original
hklbut with the twins set ->twinnedoutput spectra - Check the output
omegafield of thetwinnedoutput spectra is a cell with two elements (one for each twin, the first being the identity) - Compare the first element of the output
omegafield oftwinnedwith theomegaoforig_single. - Compare the second element of the output
omegafield oftwinnedwith theomegaoftransformed_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
hklwithout the formfactor option set tofalse->spec_no_ff - Run the calculation with the formfactor option set to
true->spec_ff - Compare
spec_no_ff.swConv * ffandspec_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.