-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add initial fm/afm tests * Small changes: - Use TestMethodSetup so a new spinw object is used in each test - Put default 'F' in properties * Add kbase test * Use multiple kbase vectors * Add symbolic warn test * Error if kbase is incorrect shape The code required for this was already in genmagstr, this has been refactored so it can also be called from optmagk * Fix tests on CI - Increase tolerance in independent kbase test - Add symbolic tags to required tests * Update optmagk docstring * Ensure optmagk args get passed to ndbase.pso Have put varargin last in ndbase.pso call, otherwise user provided varargin is overwritten by the defaults * Update publish-unit-test-result-action to v2 Using v1 gives the following warning: The `set-output` command is deprecated and will be disabled soon. Please upgrade to using Environment Files. For more information see: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
- Loading branch information
1 parent
f2fcb71
commit 91cc80a
Showing
7 changed files
with
178 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
classdef unittest_spinw_optmagk < sw_tests.unit_tests.unittest_super | ||
% Runs through unit test for @spinw/spinwave.m | ||
|
||
properties | ||
swobj = []; | ||
% output from optmagk | ||
default_mag_str = struct('nExt', int32([1 1 1]), ... | ||
'F', [sqrt(1/3) + 1i*sqrt(1/2); ... | ||
sqrt(1/3); ... | ||
sqrt(1/3) - 1i*sqrt(1/2)], ... | ||
'k', [1; 0; 0]); | ||
end | ||
properties (TestParameter) | ||
kbase_opts = {[1; 1; 0], [1 0; 0 1; 0 0]}; | ||
end | ||
methods (TestMethodSetup) | ||
function setup_chain_model(testCase) | ||
testCase.swobj = spinw(); | ||
testCase.swobj.genlattice('lat_const', [3 8 8]) | ||
testCase.swobj.addatom('r',[0; 0; 0],'S',1) | ||
testCase.swobj.gencoupling(); | ||
end | ||
end | ||
methods (Test, TestTags = {'Symbolic'}) | ||
function test_symbolic_warns_returns_nothing(testCase) | ||
testCase.swobj.addmatrix('label', 'J1', 'value', 1); | ||
testCase.swobj.addcoupling('mat', 'J1', 'bond', 1); | ||
testCase.swobj.symbolic(true) | ||
testCase.verifyWarning(... | ||
@() testCase.swobj.optmagk, ... | ||
'spinw:optmagk:NoSymbolic'); | ||
testCase.verifyEmpty(testCase.swobj.mag_str.k); | ||
testCase.verifyEmpty(testCase.swobj.mag_str.F); | ||
testCase.verify_val(testCase.swobj.mag_str.nExt, ... | ||
int32([1 1 1])); | ||
end | ||
end | ||
methods (Test) | ||
function test_wrong_shape_kbase_raises_error(testCase) | ||
testCase.verifyError(... | ||
@() testCase.swobj.optmagk('kbase', [1 1 0]), ... | ||
'spinw:optmagk:WrongInput'); | ||
end | ||
function test_fm_chain_optk(testCase) | ||
testCase.swobj.addmatrix('label', 'J1', 'value', -1); | ||
testCase.swobj.addcoupling('mat', 'J1', 'bond', 1); | ||
out = testCase.swobj.optmagk; | ||
out.stat = rmfield(out.stat, 'nFunEvals'); | ||
|
||
expected_mag_str = testCase.default_mag_str; | ||
expected_out = struct('k', expected_mag_str.k, ... | ||
'E', -1, .... | ||
'F', expected_mag_str.F, ... | ||
'stat', struct('S', 0, ... | ||
'exitflag', -1)); | ||
% Test struct output by optmagk | ||
testCase.verify_val(out, expected_out, 'abs_tol', 1e-4); | ||
% Also test spinw attributes have been set | ||
expected_mag_str = testCase.default_mag_str; | ||
testCase.verify_val(testCase.swobj.mag_str, expected_mag_str, ... | ||
'abs_tol', 1e-4); | ||
end | ||
function test_afm_chain_optk(testCase) | ||
testCase.swobj.addmatrix('label', 'J1', 'value', 1); | ||
testCase.swobj.addcoupling('mat', 'J1', 'bond', 1); | ||
testCase.swobj.optmagk; | ||
expected_mag_str = testCase.default_mag_str; | ||
expected_mag_str.k = [0.5; 0; 0]; | ||
testCase.verify_val(testCase.swobj.mag_str, expected_mag_str, ... | ||
'abs_tol', 1e-4); | ||
end | ||
function test_kbase(testCase, kbase_opts) | ||
% See https://doi.org/10.1103/PhysRevB.59.14367 | ||
swobj = spinw(); | ||
swobj.genlattice('lat_const', [3 3 8]) | ||
swobj.addatom('r',[0; 0; 0],'S',1) | ||
swobj.gencoupling(); | ||
J1 = 1.2; | ||
J2 = 1.0; | ||
swobj.addmatrix('label', 'J1', 'value', J1); | ||
swobj.addmatrix('label', 'J2', 'value', J2); | ||
swobj.addcoupling('mat', 'J1', 'bond', 2, 'subidx', 2); | ||
swobj.addcoupling('mat', 'J2', 'bond', 1); | ||
% Use rng seed for reproducible results | ||
swobj.optmagk('kbase', kbase_opts, 'seed', 1); | ||
|
||
expected_k = acos(-J2/(2*J1))/(2*pi); | ||
rel_tol = 1e-5; | ||
if abs(expected_k - swobj.mag_str.k(1)) > rel_tol*expected_k | ||
% If this k doesn't match, try 1-k | ||
expected_k = 1 - expected_k; % k and 1-k are degenerate | ||
end | ||
expected_mag_str = testCase.default_mag_str; | ||
expected_mag_str.k = [expected_k; expected_k; 0]; | ||
testCase.verify_val(swobj.mag_str, expected_mag_str, ... | ||
'rel_tol', 1e-5); | ||
end | ||
function test_afm_chain_ndbase_pso_varargin_passed(testCase) | ||
testCase.swobj.addmatrix('label', 'J1', 'value', 1); | ||
testCase.swobj.addcoupling('mat', 'J1', 'bond', 1); | ||
% Verify in default case there is no warning | ||
testCase.verifyWarningFree(... | ||
@() testCase.swobj.optmagk, ... | ||
'pso:convergence'); | ||
% Test that MaxIter gets passed through to ndbase.pso, triggers | ||
% convergence warning | ||
testCase.verifyWarning(... | ||
@() testCase.swobj.optmagk('MaxIter', 1), ... | ||
'pso:convergence'); | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
function softparamcheck(params_to_check, func_name, param, varargin) | ||
% Checks if any parameters have been provided in varargin, but set to | ||
% empty, and raises an error if so. This function is needed because by | ||
% default 'soft' params will silently be set to empty if their shape is | ||
% incorrect, causing unexpected behaviour for users. | ||
% | ||
% Input: | ||
% | ||
% params_to_check A list of strings of the parameters to check e.g. | ||
% ["S", "k"] | ||
% func_name The name of the function this is being called from | ||
% to be used in the error identifier text | ||
% param The output of sw_readparam. If an argument exists in | ||
% varargin, but has been set to empty in param, we know | ||
% it has been silently ignored so raise an error | ||
% varargin Varargin that was used as input to sw_readparam to | ||
% create param, this should be name-value pairs or a | ||
% struct | ||
% | ||
if isempty(varargin) | ||
return | ||
end | ||
names = vararginnames(varargin{:}); | ||
err_str = []; | ||
for i = 1:length(params_to_check) | ||
if any(strcmpi(names, params_to_check(i))) ... | ||
&& isempty(param.(params_to_check(i))) | ||
err_str = [err_str params_to_check(i)]; | ||
end | ||
end | ||
if ~isempty(err_str) > 0 | ||
error(['spinw:' char(func_name) ':WrongInput'], ... | ||
'Incorrect input size for ' + join(err_str, ', ')); | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
function names = vararginnames(varargin) | ||
% Given varargin, returns a list of the given | ||
% argument names (so we know which arguments a user has passed to a function). | ||
% Note that inputs to SpinW functions can either be name-value pairs or a | ||
% struct | ||
% | ||
% Input: | ||
% | ||
% varargin Variable-length argument list (name value pairs) or struct | ||
if isstruct(varargin{1}) | ||
varargin_struct = varargin{1}; | ||
else | ||
varargin_struct = struct(varargin{:}); | ||
end | ||
names = fields(varargin_struct); | ||
end |