diff --git a/+sw_tests/+system_tests/systemtest_spinwave.m b/+sw_tests/+system_tests/systemtest_spinwave.m index 58e65187..60908b8b 100644 --- a/+sw_tests/+system_tests/systemtest_spinwave.m +++ b/+sw_tests/+system_tests/systemtest_spinwave.m @@ -4,10 +4,11 @@ properties generate_reference_data = false; reference_data = []; - reference_data_dir = fullfile('.', 'test_data'); + reference_data_dir = fullfile('.', 'test_data', 'system_tests'); relToll = 0.01; absToll = 1e-6; swobj = []; + cleanup_warnings = {}; end methods (TestClassSetup) @@ -183,6 +184,11 @@ function generate_or_verify_generic(testCase, data, fieldname) testCase.verify_test_data(data, testCase.reference_data.(fieldname)); end end + function disable_warnings(testCase, varargin) + testCase.cleanup_warnings = [testCase.cleanup_warnings, ... + {onCleanup(@(c) cellfun(@(c) warning('on', c), varargin))}]; + cellfun(@(c) warning('off', c), varargin); + end end end diff --git a/+sw_tests/+system_tests/systemtest_spinwave_incommensurate_and_supercell_consistency.m b/+sw_tests/+system_tests/systemtest_spinwave_incommensurate_and_supercell_consistency.m index 2fe55e88..2ce7ec5b 100644 --- a/+sw_tests/+system_tests/systemtest_spinwave_incommensurate_and_supercell_consistency.m +++ b/+sw_tests/+system_tests/systemtest_spinwave_incommensurate_and_supercell_consistency.m @@ -48,6 +48,7 @@ function test_AFM_kagome(testCase) % use structural unit cell with incommensurate k AF33kagome.genmagstr('mode','helical','unit','lu', 'k', k,... 'n',n, 'S', S, 'nExt',[1 1 1]); + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); spec_incom = AF33kagome.spinwave(qarg, 'hermit', true); spec_incom = sw_egrid(spec_incom, 'component','Sperp', 'Evect',evec); % use supercell k=0 structure @@ -64,7 +65,7 @@ function test_AFM_kagome(testCase) function test_two_matom_per_unit_cell(testCase) % setup structure (taken from tutorial 19) FeCuChain = spinw; - FeCuChain.genlattice('lat_const',[3 8 4],'spgr','P 1') + FeCuChain.genlattice('lat_const',[3 8 4],'sym','P 1') FeCuChain.addatom('label','MCu2','r',[0 0 0]) FeCuChain.addatom('label','MFe2','r',[0 1/2 0]) @@ -84,6 +85,9 @@ function test_two_matom_per_unit_cell(testCase) evec = 0:1.5:5; % use structural unit cell with incommensurate k + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian', ... + 'spinw:magstr:NotExact', ... + 'spinw:spinwave:Twokm'); FeCuChain.genmagstr('mode','helical','k', k,... 'S', S, 'nExt',[1 1 1]); spec_incom = FeCuChain.spinwave(qarg, 'hermit', true); @@ -101,7 +105,7 @@ function test_two_matom_per_unit_cell(testCase) function test_two_sym_equiv_matoms_per_unit_cell(testCase) sw = spinw; - sw.genlattice('lat_const',[4,5,12],'spgr','I m m m') + sw.genlattice('lat_const',[4,5,12],'sym','I m m m') sw.addatom('S', 1, 'r',[0 0 0]); sw.addmatrix('label', 'J', 'value', 1); sw.addmatrix('label', 'A', 'value', diag([0 0 -0.1])) @@ -116,6 +120,7 @@ function test_two_sym_equiv_matoms_per_unit_cell(testCase) evec = 0:0.5:1.5; % use structural unit cell with incommensurate k + testCase.disable_warnings('spinw:genmagstr:SnParallel'); sw.genmagstr('mode','helical','k', k,... 'S', S, 'nExt',[1 1 1]); spec_incom = sw.spinwave(qarg, 'hermit', true); diff --git a/+sw_tests/+system_tests/systemtest_spinwave_pcsmo.m b/+sw_tests/+system_tests/systemtest_spinwave_pcsmo.m index bfd63669..a8d042f2 100644 --- a/+sw_tests/+system_tests/systemtest_spinwave_pcsmo.m +++ b/+sw_tests/+system_tests/systemtest_spinwave_pcsmo.m @@ -90,6 +90,8 @@ function test_pcsmo(testCase, usehorace) testCase.verify_test_data({w0(1:numel(w1)) s0(1:numel(w1))}, {w1 s1}); testCase.generate_or_verify_generic({w0 s0}, 'data_horace'); else + testCase.swobj.twin.rotc(3,3,2) = 0; % Changed in code #85, but not in test .mat file + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); spec = testCase.swobj.spinwave(qln, 'formfact', true, 'saveV', true, 'saveH', true, 'optmem', 2); spec = sw_egrid(spec, 'Evect', linspace(0, 100, 200)); spec = sw_neutron(spec); diff --git a/+sw_tests/+unit_tests/unittest_spinw_addatom.m b/+sw_tests/+unit_tests/unittest_spinw_addatom.m index e76ec1d3..85bd2ee8 100644 --- a/+sw_tests/+unit_tests/unittest_spinw_addatom.m +++ b/+sw_tests/+unit_tests/unittest_spinw_addatom.m @@ -102,6 +102,7 @@ function test_add_single_atom_custom_parameters(testCase, property_value) function test_add_atom_with_custom_scatt_length(testCase, b_name) b = 2; + testCase.disable_warnings('spinw:addatom:DeprecationWarning'); testCase.swobj.addatom('r', [0;0;0], b_name, b) expected_unit_cell = testCase.default_unit_cell; expected_unit_cell.b = [b; 1]; diff --git a/+sw_tests/+unit_tests/unittest_spinw_genlattice.m b/+sw_tests/+unit_tests/unittest_spinw_genlattice.m index 369f56ec..66b1c12a 100644 --- a/+sw_tests/+unit_tests/unittest_spinw_genlattice.m +++ b/+sw_tests/+unit_tests/unittest_spinw_genlattice.m @@ -65,12 +65,14 @@ function test_spgr_throws_deprecation_warning(testCase) end function test_spgr_and_sym_throws_error(testCase) + testCase.disable_warnings('spinw:genlattice:DeprecationWarning'); testCase.verifyError(... @() testCase.swobj.genlattice('spgr', 3, 'sym', 3), ... 'spinw:genlattice:WrongInput'); end function test_spacegroup_property(testCase, sym_param_name, spgr) + testCase.disable_warnings('spinw:genlattice:DeprecationWarning'); testCase.swobj.genlattice(sym_param_name, spgr); expected_latt = testCase.default_latt; expected_latt.sym = testCase.P2_sym; @@ -79,6 +81,7 @@ function test_spacegroup_property(testCase, sym_param_name, spgr) end function test_label_always_used(testCase, sym_param_name, spgr_type) + testCase.disable_warnings('spinw:genlattice:DeprecationWarning'); label = 'label'; testCase.swobj.genlattice(sym_param_name, spgr_type, ... 'label', label); @@ -86,6 +89,7 @@ function test_label_always_used(testCase, sym_param_name, spgr_type) end function test_spacegroup_with_sym_operation_matrix(testCase, sym_param_name) + testCase.disable_warnings('spinw:genlattice:DeprecationWarning'); testCase.swobj.genlattice(sym_param_name, testCase.P2_sym); expected_latt = testCase.default_latt; expected_latt.sym = testCase.P2_sym; @@ -166,6 +170,7 @@ function test_basis_vector_and_rotation_matrix(testCase, basis_vecs) function test_spacegroup_with_cell_input(testCase, sym_param_name) spgr_str = '-x,y,-z'; label = 'label'; + testCase.disable_warnings('spinw:genlattice:DeprecationWarning'); testCase.swobj.genlattice(sym_param_name, {spgr_str, label}); expected_latt = testCase.default_latt; expected_latt.sym = testCase.P2_sym; diff --git a/+sw_tests/+unit_tests/unittest_spinw_genmagstr.m b/+sw_tests/+unit_tests/unittest_spinw_genmagstr.m index aa217c07..04e70d78 100644 --- a/+sw_tests/+unit_tests/unittest_spinw_genmagstr.m +++ b/+sw_tests/+unit_tests/unittest_spinw_genmagstr.m @@ -392,7 +392,7 @@ function test_helical_multiatom_nExt_nMagExt_spins(testCase) 'k', k', ... 'nExt', nExt, ... 'F', [-1i 2 0 -2; 1 2i 0 -2i; 0 0 1 0]); - testCase.verify_obj(swobj.mag_str, expected_mag_str); + testCase.verify_obj(swobj.mag_str, expected_mag_str); end function test_helical_multiatom_multik_multin(testCase) swobj = copy(testCase.swobj); @@ -536,8 +536,9 @@ function test_tile_multik_provided_k_set_to_zero(testCase) swobj.addatom('r', [0.5 0.5 0], 'S', 1); S = cat(3, [1 0; 0 1; 0 0], [0 1; 0 0; 1 0]); k = 0.5*ones(size(S, 3), 3); - swobj.genmagstr('mode', 'tile', ... - 'S', S, 'k', k); + testCase.assertWarning(... + @() swobj.genmagstr('mode', 'tile', 'S', S, 'k', k), ... + 'spinw:genmagstr:UnreadInput'); expected_mag_str = testCase.default_mag_str; expected_mag_str.F = sqrt(2)/2*[1 1; 0 1; 1 0]; testCase.verify_obj(swobj.mag_str, expected_mag_str); @@ -652,4 +653,4 @@ function test_func_custom_symbolic(testCase) testCase.verify_obj(swobj.mag_str, expected_mag_str); end end -end \ No newline at end of file +end diff --git a/+sw_tests/+unit_tests/unittest_spinw_intmatrix.m b/+sw_tests/+unit_tests/unittest_spinw_intmatrix.m index 39fa0f7e..c8f5ac56 100644 --- a/+sw_tests/+unit_tests/unittest_spinw_intmatrix.m +++ b/+sw_tests/+unit_tests/unittest_spinw_intmatrix.m @@ -128,7 +128,9 @@ function test_intmatrix_fitmode_true_plotmode_true(testCase) end function test_intmatrix_fitmode_true_DM_interaction(testCase) - testCase.swobj.addcoupling('mat', 'D', 'bond', 3, 'subIdx', 1); + testCase.verifyWarning( ... + @() testCase.swobj.addcoupling('mat', 'D', 'bond', 3, 'subIdx', 1), ... + 'spinw:addcoupling:SymetryLowered'); [SS, SI, RR] = testCase.swobj.intmatrix('fitmode', true); @@ -142,6 +144,7 @@ function test_intmatrix_fitmode_true_DM_interaction(testCase) function test_intmatrix_fitmode_false(testCase) % add all different types of interaction + testCase.disable_warnings('spinw:addcoupling:SymetryLowered'); testCase.swobj.addmatrix('label','Janiso','value', ... diag([1,2,3])) for mat_name = {'D', 'gen', 'Janiso'} @@ -171,7 +174,9 @@ function test_intmatrix_zeroC_false_removes_zero_matrices(testCase) function test_intmatrix_conjugate(testCase) % add coupling between two different atoms - testCase.swobj.addcoupling('mat', 'gen', 'bond', 3, 'subIdx', 1); + testCase.verifyWarning( ... + @() testCase.swobj.addcoupling('mat', 'gen', 'bond', 3, 'subIdx', 1), ... + 'spinw:addcoupling:SymetryLowered'); % zero other couplings for brevity (will be omitted by zeroC) testCase.swobj.addmatrix('label', 'J1', 'value', 0) testCase.swobj.addmatrix('label', 'J2', 'value', 0) @@ -234,6 +239,7 @@ function test_extend_true_with_supercell(testCase) end function test_sortDM_reorders_bonds(testCase) + testCase.disable_warnings('spinw:addcoupling:SymetryLowered'); testCase.swobj.addmatrix('label', 'J2', 'value', 0); % make face-centred to have bond order depend on sortDM testCase.swobj.genlattice('sym', 'F m m m'); @@ -287,6 +293,7 @@ function symbolic_obj_with_fitmode_true(testCase) function symbolic_obj_with_fitmode_false(testCase) % add all different types of interaction + testCase.disable_warnings('spinw:addcoupling:SymetryLowered'); testCase.swobj.addmatrix('label','Janiso','value', ... diag([1,2,3])) for mat_name = {'D', 'gen', 'Janiso'} diff --git a/+sw_tests/+unit_tests/unittest_spinw_optmagk.m b/+sw_tests/+unit_tests/unittest_spinw_optmagk.m index 8f61888c..4d184cf2 100644 --- a/+sw_tests/+unit_tests/unittest_spinw_optmagk.m +++ b/+sw_tests/+unit_tests/unittest_spinw_optmagk.m @@ -74,7 +74,8 @@ function test_fm_chain_optk(testCase) function test_afm_chain_optk(testCase) testCase.swobj.addmatrix('label', 'J1', 'value', 1); testCase.swobj.addcoupling('mat', 'J1', 'bond', 1); - testCase.swobj.optmagk; + % Use seed for reproducibility + testCase.swobj.optmagk('seed', 1); 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, ... diff --git a/+sw_tests/+unit_tests/unittest_spinw_optmagsteep.m b/+sw_tests/+unit_tests/unittest_spinw_optmagsteep.m index a1bd212f..29dd8f88 100644 --- a/+sw_tests/+unit_tests/unittest_spinw_optmagsteep.m +++ b/+sw_tests/+unit_tests/unittest_spinw_optmagsteep.m @@ -169,6 +169,7 @@ function test_output_to_fid(testCase) end function test_plot_moment_each_iteration(testCase, existing_plot) + testCase.disable_warnings('MATLAB:dispatcher:nameConflict'); if existing_plot existing_fig = testCase.swobj.plot(); end @@ -217,10 +218,10 @@ function test_not_move_moments_in_field_more_than_Hmin(testCase) function test_multiple_atoms_in_unit_cell(testCase) testCase.swobj.addatom('r',[0.5; 0.5; 0.5],'S',1) - testCase.swobj.gencoupling('maxDistance', 6); + testCase.swobj.gencoupling('maxDistance', 6, 'dMin', 0.1); testCase.swobj.addaniso('A'); % add again as cleared above % add AFM coupling of spins in same unit cell - testCase.swobj.addcoupling('mat', 'J1', 'bond', 3, 'dMin', 0.1); + testCase.swobj.addcoupling('mat', 'J1', 'bond', 3); testCase.swobj.genmagstr('mode', 'direct', 'S', [0 0; 0 0; 1 1], ... 'k',[0, 0, 0]); % FM initial state diff --git a/+sw_tests/+unit_tests/unittest_spinw_optmagstr.m b/+sw_tests/+unit_tests/unittest_spinw_optmagstr.m index be38aeee..df947af5 100644 --- a/+sw_tests/+unit_tests/unittest_spinw_optmagstr.m +++ b/+sw_tests/+unit_tests/unittest_spinw_optmagstr.m @@ -125,6 +125,7 @@ function test_optmagstr_tri_af_out_planar_xmin_xmax(testCase) function test_optmagstr_tri_af_nExt_init(testCase) % Test that if a magnetic structure is initialised with nExt, % it is used in optmagstr + testCase.disable_warnings('spinw:genmagstr:SnParallel'); testCase.tri.genmagstr('mode', 'random', 'nExt', [3 1 1]); testCase.tri.optmagstr('func', @gm_planar, ... 'xmin', [0 pi/2 pi 0 0 0 0 0], ... @@ -195,6 +196,7 @@ function test_optmagstr_tri_af_custom_func_wrong_number_of_inputs(testCase) end function test_optmagstr_tri_af_epsilon(testCase) + testCase.disable_warnings('spinw:genmagstr:SnParallel'); % Test that large epsilon doesn't rotate spins testCase.tri.optmagstr('epsilon', 1.); expected_mag_str = testCase.opt_tri_mag_str; @@ -235,19 +237,18 @@ function test_optmagstr_tri_tid(testCase) end function test_optmagstr_optimisation_params(testCase, optparams) - % We could just mock optimset and check correct args are passed - % through, but Matlab doesn't allow mocking functions, and our - % mock_function doesn't support complex return values such as - % structs. So just check the output struct. O. - % We could also check for non-convergence but this is a bit - % flaky on different systems. xmin = [0 0 0 0 0 0 0]; xmax = [pi/2 0 1/2 0 0 0 0]; - out = testCase.afc.optmagstr('xmin', xmin, 'xmax', xmax, ... - optparams{:}); - % Test that params are in output struct - for i=1:2:length(optparams) - testCase.verifyEqual(out.param.(optparams{i}), optparams{i+1}) + mock_optimset = sw_tests.utilities.mock_function('optimset', ... + optimset('Display', 'off', optparams{:})); + testCase.disable_warnings('spinw:genmagstr:SnParallel'); + testCase.afc.optmagstr('xmin', xmin, 'xmax', xmax, ... + optparams{:}); + testCase.assertEqual(mock_optimset.n_calls, 1); + argslower = cellfun(@(c) lower(c), mock_optimset.arguments{1}(1:2:end), 'UniformOutput', false); + for ii = find(ismember(argslower, optparams(1:2:end))) + jj = find(ismember(optparams(1:2:end), argslower{ii})); + testCase.verifyEqual(mock_optimset.arguments{1}{2*ii}, optparams{2*jj}); end end @@ -280,6 +281,7 @@ function test_dm_multiatom_spherical3d(testCase) sq.addcoupling('mat', 'DM', 'bond', 1); sq.addmatrix('value', 1, 'label', 'J1'); sq.addcoupling('mat', 'J1', 'bond', 2); + testCase.disable_warnings('spinw:genmagstr:SnParallel'); % Sometimes fails to find min, run multiple times sq.optmagstr('func', @gm_spherical3d, ... 'xmin', [-pi/2 -pi -pi/2 -pi, 0 0 0, 0 0], ... @@ -298,4 +300,4 @@ function test_dm_multiatom_spherical3d(testCase) end -end \ No newline at end of file +end diff --git a/+sw_tests/+unit_tests/unittest_spinw_spinwave.m b/+sw_tests/+unit_tests/unittest_spinw_spinwave.m index 10510c2b..5f8adeeb 100644 --- a/+sw_tests/+unit_tests/unittest_spinw_spinwave.m +++ b/+sw_tests/+unit_tests/unittest_spinw_spinwave.m @@ -37,8 +37,7 @@ function setup_chain_model(testCase) testCase.swobj.gencoupling('maxDistance', 7); testCase.swobj.addmatrix('value', -eye(3), 'label', 'Ja'); testCase.swobj.addcoupling('mat', 'Ja', 'bond', 1); - testCase.swobj.genmagstr('mode', 'direct', 'k', [0 0 0], ... - 'n', [1 0 0], 'S', [0; 1; 0]); + testCase.swobj.genmagstr('mode', 'direct', 'k', [0 0 0], 'S', [0; 1; 0]); end function setup_tri_model(testCase) % Create a simple triangular lattice model @@ -106,6 +105,7 @@ function test_sw_qh5_optmem(testCase) % target function, number of calls, or not check at all if % spinwave is refactored sw_timeit_mock = sw_tests.utilities.mock_function('sw_timeit'); + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = testCase.swobj.spinwave(qpts, 'optmem', optmem); testCase.assertEqual(sw_timeit_mock.n_calls, optmem + 2); % Test that with optmem gives the same result as without @@ -125,12 +125,14 @@ function test_sw_qh5_low_freemem(testCase) % Check with low free memory calculation still attempted sw_freemem_mock = sw_tests.utilities.mock_function( ... 'sw_freemem', 100); + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = testCase.swobj.spinwave(testCase.qh5); testCase.verify_spinwave(sw_out, testCase.get_expected_sw_qh5); end function test_sw_qh5_fid(testCase) fprintf_mock = sw_tests.utilities.mock_function('fprintf0'); fid = 3; + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = testCase.swobj.spinwave(testCase.qh5, 'fid', fid); % check fid used to write file for irow = 1:fprintf_mock.n_calls @@ -142,6 +144,7 @@ function test_sw_qh5_fid(testCase) function test_sw_qh5_tid(testCase) sw_timeit_mock = sw_tests.utilities.mock_function('sw_timeit'); tid = 2; + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = testCase.swobj.spinwave(testCase.qh5, 'tid', tid); % check tid used in timing for irow = 1:sw_timeit_mock.n_calls @@ -154,12 +157,14 @@ function test_sw_qh5_tid(testCase) methods (Test) function test_sw_qh5(testCase, qpts_h5, mex) swpref.setpref('usemex', mex); + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = testCase.swobj.spinwave(qpts_h5); expected_sw = testCase.get_expected_sw_qh5(); testCase.verify_spinwave(sw_out, expected_sw); end function test_sw_qh5_sortmode(testCase, mex) swpref.setpref('usemex', mex); + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = testCase.swobj.spinwave(testCase.qh5, 'sortMode', false); expected_sw = testCase.get_expected_sw_qh5(); % Sortmode swaps the last 2 modes @@ -174,6 +179,7 @@ function test_sw_qh5_nformula(testCase, mex) swobj = copy(testCase.swobj); nformula = int32(2); swobj.unit.nformula = nformula; + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out_nformula = swobj.spinwave(testCase.qh5); expected_sw = testCase.swobj.spinwave(testCase.qh5); expected_sw.Sab = expected_sw.Sab/2; @@ -185,6 +191,7 @@ function test_sw_qh5_periodic(testCase, mex) swpref.setpref('usemex', mex); % Test qpts in different BZ give same omega, Sab qpts = testCase.qh5 + 1; + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = testCase.swobj.spinwave(qpts); expected_sw = testCase.get_expected_sw_qh5(); expected_sw.hkl = qpts; @@ -195,6 +202,7 @@ function test_sw_qh5_perpendicular(testCase, mex) swpref.setpref('usemex', mex); % Test qpts in perpendicular direction give flat modes qpts = [zeros(1, 5); 0:0.25:1; 0:0.25:1]; + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = testCase.swobj.spinwave(qpts); expected_sw = testCase.get_expected_sw_qh5(); expected_sw.hkl = qpts; @@ -206,6 +214,7 @@ function test_sw_qh5_perpendicular(testCase, mex) end function test_sw_qh5_saveH_saveV(testCase, mex) swpref.setpref('usemex', mex); + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = testCase.swobj.spinwave(testCase.qh5, ... 'saveV', true, 'saveH', true); expected_V = repmat(eye(2), 1, 1, 5); @@ -221,6 +230,7 @@ function test_sw_qh5_saveH_saveV(testCase, mex) function test_sw_qh5_title(testCase, mex) swpref.setpref('usemex', mex); title = 'Example title'; + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = testCase.swobj.spinwave(testCase.qh5, 'title', title); expected_sw = testCase.get_expected_sw_qh5(); expected_sw.title = title; @@ -232,8 +242,7 @@ function test_sw_with_nExt(testCase, mex) afm_chain = copy(testCase.swobj); afm_chain.matrix.mat = eye(3); afm_chain.genmagstr('mode', 'direct', 'k',[1/2 0 0], ... - 'n',[1 0 0],'S',[0 0; 1 -1;0 0], ... - 'nExt',[2 1 1]); + 'S',[0 0; 1 -1;0 0], 'nExt',[2 1 1]); sw_afm = afm_chain.spinwave(testCase.qh5); omega_vals = [0 2. 0 -2. 0]; expected_omega = [omega_vals; omega_vals; -omega_vals; -omega_vals]; @@ -254,6 +263,7 @@ function test_sw_with_multiple_matom(testCase, mex) fe_cu_chain.addcoupling('mat','J_{Cu-Fe}','bond',[4 5]); fe_cu_chain.genmagstr('mode','helical','S',[0 0;1 1;0 0],'k',[1/2 0 0]) + testCase.disable_warnings('spinw:magstr:NotExact', 'spinw:spinwave:Twokm'); sw_out = fe_cu_chain.spinwave(testCase.qh5, 'sortMode', false, 'omega_tol', 1e-12); om1 = 4.11473; om2 = 1.36015; @@ -281,35 +291,38 @@ function test_sw_incom_in_supercell_warns(testCase, mex) cycloid.addcoupling('mat','J2','bond',2); % modulation of [1/4 0 0] gets transformed in genmagstr to % [0.5 0 0] for nExt = [2 1 1] + testCase.disable_warnings('spinw:genmagstr:UCExtNonSuff'); cycloid.genmagstr('mode', 'helical', ... 'S', [1 0; 0 1; 0 0], 'n', [0 0 1], ... 'nExt', [2 1 1], 'k', [0.25, 0, 0]); - testCase.verifyWarning(@() cycloid.spinwave({[0 0 0], [1 0 0], ... - 30}), ... - 'spinw:spinwave:IncommKinSupercell'); + testCase.verifyWarning(@() cycloid.spinwave({[0 0 0], [1 0 0], 30}), ... + {'spinw:spinwave:IncommKinSupercell', ... + 'spinw:spinwave:Twokm'}); end function test_sw_qh5_saveSabp_incommensurate(testCase, mex) swpref.setpref('usemex', mex); - qpts = testCase.qh5; - sw_out = testCase.swobj_tri.spinwave(qpts, ... - 'saveSabp', true); - expected_Sabp = zeros(3, 3, 2, 5); - expected_Sabp(:, :, :, [1 5]) = repmat( ... - diag([435.71079, 435.71079, 6.45497e-4]), 1, 1, 2, 2); - expected_Sabp(:, :, :, [2 4]) = repmat( ... - diag([0.59293, 0.59293, 0.47434]), 1, 1, 2, 2); - expected_Sabp(:, :, :, 3) = repmat( ... - diag([0.1875, 0.1875, 1.5]), 1, 1, 2, 1); - omegap_vals = [1.16190e-2 4.74342 3]; - expected_omegap = [ omegap_vals omegap_vals(2:-1:1); ... - -omegap_vals -omegap_vals(2:-1:1)]; + qpts = testCase.qh5; + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); + sw_out = testCase.swobj_tri.spinwave(qpts, ... + 'saveSabp', true); + expected_Sabp = zeros(3, 3, 2, 5); + expected_Sabp(:, :, :, [1 5]) = repmat( ... + diag([435.71079, 435.71079, 6.45497e-4]), 1, 1, 2, 2); + expected_Sabp(:, :, :, [2 4]) = repmat( ... + diag([0.59293, 0.59293, 0.47434]), 1, 1, 2, 2); + expected_Sabp(:, :, :, 3) = repmat( ... + diag([0.1875, 0.1875, 1.5]), 1, 1, 2, 1); + omegap_vals = [1.16190e-2 4.74342 3]; + expected_omegap = [ omegap_vals omegap_vals(2:-1:1); ... + -omegap_vals -omegap_vals(2:-1:1)]; - testCase.verify_val(sw_out.Sabp, expected_Sabp, 'rel_tol', 1e-5); - testCase.verify_val(sw_out.omegap, expected_omegap, 'rel_tol', 1e-5); + testCase.verify_val(sw_out.Sabp, expected_Sabp, 'rel_tol', 1e-5); + testCase.verify_val(sw_out.omegap, expected_omegap, 'rel_tol', 1e-5); end function test_sw_qh5_fitmode(testCase, mex) swpref.setpref('usemex', mex); qpts = testCase.qh5; + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = testCase.swobj.spinwave(qpts, 'fitmode', true); % fitmode automatically turns off sortMode expected_sw = testCase.swobj.spinwave(qpts, 'sortMode', false); @@ -323,6 +336,7 @@ function test_incommensurate(testCase, mex) else err= 'spinw:spinwave:NonPosDefHamiltonian'; end + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); % Tests that incommensurate calculation is ok hkl = {[0 0 0] [0 1 0] [1 0 0] 5}; % Create copy to avoid changing obj for other tests @@ -350,6 +364,7 @@ function test_twin(testCase, mex) swobj_twin.addtwin('axis', [0 0 1], 'phid', [60 120], 'vol', [1 2]); rotc = swobj_twin.twin.rotc; hkl = [1 2; 3 4; 5 6]; + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = swobj_twin.spinwave(hkl); expected_sw = testCase.default_spinwave; @@ -382,6 +397,7 @@ function test_notwin(testCase, mex) swobj_twin = copy(testCase.swobj); swobj_twin.addtwin('axis', [0 0 1], 'phid', [60 120], 'vol', [1 2]); qpts = testCase.qh5; + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = swobj_twin.spinwave(qpts, 'notwin', true); % Test even if twin is added to structure it is not actually % calculated if notwin is specified @@ -394,6 +410,7 @@ function test_cmplxBase_equivalent_with_tri(testCase, mex) % For this structure, both cmplxBase true and false give the % same e-vectors so should give the same result qpts = {[0 0 0], [1 0 0], 5}; + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = testCase.swobj_tri.spinwave(qpts, 'cmplxBase', false); sw_out_cmplx = testCase.swobj_tri.spinwave(qpts, 'cmplxBase', true); testCase.verify_spinwave(sw_out_cmplx, sw_out); @@ -415,6 +432,7 @@ function test_cmplxBase_fails_with_chain(testCase, mex) function test_formfact(testCase, mex) swpref.setpref('usemex', mex); qpts = {[0 0 0] [10 5 1] 19}; + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_ff = testCase.swobj.spinwave(qpts, 'formfact', true); % Test that Sab with the form factor (ff) is explicitly the % same as Sab with no ff multiplied by ff @@ -432,6 +450,7 @@ function test_formfactfun(testCase, mex) F = sum(Q, 1); end qpts = {[0 0 0] [10 5 1] 19}; + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_ff = testCase.swobj.spinwave(qpts, 'formfact', true, ... 'formfactfun', @formfactfun); % Test that Sab with the form factor (ff) is explicitly the @@ -451,6 +470,7 @@ function test_gtensor(testCase, mex) swobj_g = copy(testCase.swobj); swobj_g.addmatrix('label','g_1','value', gmat) swobj_g.addg('g_1') + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_g = swobj_g.spinwave(qpts, 'gtensor', true); % Also check that it warns that gtensor is not being used expected_sw = testCase.verifyWarning(... @@ -468,6 +488,7 @@ function test_gtensor_incomm(testCase, mex) swobj_g = copy(testCase.swobj_tri); swobj_g.addmatrix('label','g_1','value', gmat) swobj_g.addg('g_1') + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_g = swobj_g.spinwave(qpts, 'gtensor', true); % Check that Sab with g is same as Sab without g but multiplied % by g in each direction @@ -508,6 +529,7 @@ function test_sw_qh5_tol(testCase, mex) 'spinw:spinwave:NonPosDefHamiltonian'); end % Check that with tol is approximated to commensurate + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = swobj_tol.spinwave(qpts, 'tol', tol); expected_sw = testCase.get_expected_sw_qh5; expected_sw.obj = swobj_tol; @@ -529,6 +551,7 @@ function test_sw_qh5_omega_tol(testCase, mex) err); % Check with omega_tol the omega is changed appropriately omega_tol = 1; + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); sw_out = testCase.swobj.spinwave(qpts, 'omega_tol', omega_tol); expected_sw = testCase.get_expected_sw_qh5; expected_sw.omega(:, 1) = [omega_tol -omega_tol]; @@ -557,7 +580,8 @@ function test_no_magstr_causes_error(testCase) function test_sw_symbolic_no_qpts(testCase) swobj = copy(testCase.swobj); swobj.symbolic(true); - sw_out = swobj.spinwave(); + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); + sw_out = testCase.verifyWarning(@() swobj.spinwave(), 'spinw:spinwave:MissingInput'); symstr = '-Ja*exp(-pi*h*2i)*(exp(pi*h*2i) - 1)^2'; expected_sw.ham = [str2sym(symstr) sym(0); ... diff --git a/+sw_tests/+unit_tests/unittest_super.m b/+sw_tests/+unit_tests/unittest_super.m index 2505a088..7d40536d 100644 --- a/+sw_tests/+unit_tests/unittest_super.m +++ b/+sw_tests/+unit_tests/unittest_super.m @@ -1,4 +1,7 @@ classdef unittest_super < matlab.mock.TestCase + properties + cleanup_warnings = {}; + end methods (Static) function udir = get_unit_test_dir() udir = fullfile('.', 'test_data', 'unit_tests'); @@ -100,5 +103,10 @@ function verify_spinwave(testCase, actual_spinwave, ... varargin{:}); end end + function disable_warnings(testCase, varargin) + testCase.cleanup_warnings = [testCase.cleanup_warnings, ... + {onCleanup(@(c) cellfun(@(c) warning('on', c), varargin))}]; + cellfun(@(c) warning('off', c), varargin); + end end end diff --git a/+sw_tests/+unit_tests/unittest_sw_neutron.m b/+sw_tests/+unit_tests/unittest_sw_neutron.m index 8164e02b..de4ae718 100644 --- a/+sw_tests/+unit_tests/unittest_sw_neutron.m +++ b/+sw_tests/+unit_tests/unittest_sw_neutron.m @@ -14,13 +14,14 @@ function setup_spinw_model(testCase) testCase.swobj.gencoupling('maxDistance', 7); testCase.swobj.addmatrix('value', -eye(3), 'label', 'Ja'); testCase.swobj.addcoupling('mat', 'Ja', 'bond', 1); - testCase.swobj.genmagstr('mode', 'direct', 'k', [0 0 0], 'n', [1 0 0], 'S', [0; 1; 0]); + testCase.swobj.genmagstr('mode', 'direct', 'k', [0 0 0], 'S', [0; 1; 0]); end end methods (Test) function test_formfact(testCase) % Tests that the form factor calculation is applied correctly hkl = {[0 0 0] [10 0 0] 100}; + testCase.disable_warnings('spinw:spinwave:NonPosDefHamiltonian'); % Runs calculation with/without formfactor spec_no_ff = sw_neutron(testCase.swobj.spinwave(hkl, 'formfact', false)); spec_ff = sw_neutron(testCase.swobj.spinwave(hkl, 'formfact', true)); diff --git a/external/chol_omp/chol_omp.cpp b/external/chol_omp/chol_omp.cpp index 60dc7443..83075afc 100644 --- a/external/chol_omp/chol_omp.cpp +++ b/external/chol_omp/chol_omp.cpp @@ -203,9 +203,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) } delete[]blkid; - if(err_code==1) + if(err_code==1) mexErrMsgIdAndTxt("chol_omp:notposdef","The input matrix is not positive definite."); - else if(err_code==2) + else if(err_code==2) mexErrMsgIdAndTxt("chol_omp:singular","The input matrix is singular."); } @@ -213,7 +213,7 @@ template int do_loop(mxArray *plhs[], const mxArray *prhs[], int nthread, mwSignedIndex m, int nlhs, int *blkid, char uplo, T tol, bool do_Colpa) { - int err_code = 0, ib=0; + int err_nonpos = 0, err_singular = 0; T* lhs0 = (T*)mxGetData(plhs[0]); T* lhs1 = (T*)mxGetData(plhs[1]); T* rhs0 = (T*)mxGetData(prhs[0]); @@ -221,9 +221,8 @@ int do_loop(mxArray *plhs[], const mxArray *prhs[], int nthread, mwSignedIndex m T* ilhs0 = (T*)mxGetImagData(plhs[0]); T* ilhs1 = (T*)mxGetImagData(plhs[1]); bool is_complex = mxIsComplex(prhs[0]); -#pragma omp parallel default(none) shared(err_code) \ - firstprivate(nthread, m, nlhs, ib, blkid, uplo, tol, do_Colpa, \ - lhs0, lhs1, rhs0, irhs0, ilhs0, ilhs1, is_complex) +#pragma omp parallel default(none) shared(err_nonpos, err_singular) \ + firstprivate(nthread, m, nlhs, blkid, uplo, tol, do_Colpa, lhs0, lhs1, rhs0, irhs0, ilhs0, ilhs1, is_complex) { #pragma omp for for(int nt=0; nt0?2:1); kk++) { // Populate the matrix input array (which will be overwritten by the Lapack function) @@ -296,10 +295,9 @@ int do_loop(mxArray *plhs[], const mxArray *prhs[], int nthread, mwSignedIndex m } if(info>0) { if(nlhs<=1 || do_Colpa) { - #pragma omp critical - { - err_code = 1; - } + // Have to use this becase VSC only supports OpenMP 2.0, allowing only {op}=, ++, -- in atomic + #pragma omp atomic + err_nonpos++; break; } else { @@ -347,10 +345,8 @@ int do_loop(mxArray *plhs[], const mxArray *prhs[], int nthread, mwSignedIndex m trtri(&uplo, &diag, &m, M, &lda, &info, false); } if(info>0) { - #pragma omp critical - { - err_code = 2; - } + #pragma omp atomic + err_singular++; break; } if(is_complex) { @@ -392,7 +388,7 @@ int do_loop(mxArray *plhs[], const mxArray *prhs[], int nthread, mwSignedIndex m } } } - if(err_code!=0) + if((err_nonpos + err_singular) > 0) break; // One of the threads got a singular or not pos def error - break loop here. } // Free memory... @@ -402,10 +398,10 @@ int do_loop(mxArray *plhs[], const mxArray *prhs[], int nthread, mwSignedIndex m delete[]Mp; delete[]alpha; } #ifndef _OPENMP - if(err_code!=0) + if((err_nonpos + err_singular) > 0) break; #endif } } - return err_code; + return err_nonpos > 0 ? 1 : (err_singular > 0 ? 2 : 0); } diff --git a/external/eig_omp/eig_omp.cpp b/external/eig_omp/eig_omp.cpp index 2a0c86c0..89ca5b73 100644 --- a/external/eig_omp/eig_omp.cpp +++ b/external/eig_omp/eig_omp.cpp @@ -672,7 +672,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) } delete[]blkid; delete[]issym; - if(err_code==1) + if(err_code > 0) mexErrMsgIdAndTxt("eig_omp:defectivematrix","Eigenvectors of defective eigenvalues cannot be orthogonalised."); } @@ -768,10 +768,8 @@ int do_loop(T *mat, T *mat_i, mxArray *plhs[], int nthread, mwSignedIndex m, int sort(m, D, (T*)NULL, work, do_sort); if(nlhs>1 && do_orth) if(orth(m, D, V, work, 0)==1) { - #pragma omp critical - { - err_code = 1; - } + #pragma omp atomic + err_code++; break; } } @@ -819,10 +817,8 @@ int do_loop(T *mat, T *mat_i, mxArray *plhs[], int nthread, mwSignedIndex m, int sort(m, D, Di, (T*)NULL, work, do_sort); if(nlhs>1 && do_orth) if(orth(m, D, Di, V, lhs0+ib*m2, work, 1)==1) { - #pragma omp critical - { - err_code = 1; - } + #pragma omp atomic + err_code++; break; } } diff --git a/run_tests.m b/run_tests.m index 0d915485..e3ac05fa 100644 --- a/run_tests.m +++ b/run_tests.m @@ -25,6 +25,9 @@ import matlab.unittest.selectors.HasTag import matlab.unittest.plugins.XMLPlugin + % Suppress printing to make test output less verbose + pref = swpref; + pref.fid = 0; suite = TestSuite.fromPackage('sw_tests', 'IncludingSubpackages', true); if ~sw_hassymtoolbox() diff --git a/swfiles/@spinw/genmagstr.m b/swfiles/@spinw/genmagstr.m index 27ea7d89..ac241e60 100644 --- a/swfiles/@spinw/genmagstr.m +++ b/swfiles/@spinw/genmagstr.m @@ -438,7 +438,7 @@ function genmagstr(obj, varargin) if strcmpi(param.mode, 'helical') for ik=1:size(k, 1) Sk = real(param.S(:, :, ik)); - if any(dot(repmat(n(ik, :), size(Sk, 2), 1)', Sk)) + if any(dot(repmat(n(ik, :), size(Sk, 2), 1)', Sk) > 1e-4) warning('spinw:genmagstr:SnParallel', ... ['There are spin components parallel to n, the ' ... 'amplitude of these components will be modulated']); diff --git a/swfiles/@swpref/private/datastruct.m b/swfiles/@swpref/private/datastruct.m index d756d7a1..97ba5fc1 100644 --- a/swfiles/@swpref/private/datastruct.m +++ b/swfiles/@swpref/private/datastruct.m @@ -138,15 +138,6 @@ return end - % TODO - % MEX is currently broken on >R2017b, so make a check - if ~verLessThan('matlab','9.4') - warning('swpref:MexError','Mex is currently unsuported on your version of MATLAB.\nWe are working on it...') - out = 0; - return - end - - if ~(exist('chol_omp','file')==3 && exist('eig_omp','file')==3) % There is a path error for < R2017a if (exist('chol_omp','file')==2 && exist('eig_omp','file')==2) @@ -264,4 +255,4 @@ function mustBeLessThanOrEqual(A, B) throwAsCaller(ME) end end -end \ No newline at end of file +end diff --git a/swfiles/sw_cartesian.m b/swfiles/sw_cartesian.m index 14528ac3..c34a3b97 100644 --- a/swfiles/sw_cartesian.m +++ b/swfiles/sw_cartesian.m @@ -51,7 +51,7 @@ end if opt - vy = cross(n,z); + vy = c; else vy = cross(n,y); end diff --git a/swfiles/sw_timeit.m b/swfiles/sw_timeit.m index c0abda0e..736f3f0e 100644 --- a/swfiles/sw_timeit.m +++ b/swfiles/sw_timeit.m @@ -40,20 +40,28 @@ function sw_timeit(percent,varargin) % global sw_time +persistent pref; +if isempty(pref) + pref = swpref; +end if nargin == 0 swhelp sw_timeit return end +if pref.fid == 0 + % Users wants to suppress output + return +end + if nargin > 2 && ~isempty(varargin{2}) && ~ischar(varargin{2}) - fid = varargin{2}; + tid = varargin{2}; else - pref = swpref; - fid = pref.tid; + tid = pref.tid; end -if fid == 0 +if tid == 0 % do nothing return end @@ -64,21 +72,21 @@ function sw_timeit(percent,varargin) title0 = 'sw_timeit'; end -if ~ismember(fid,[1 2]) +if ~ismember(tid,[1 2]) return end if nargin > 1 - start = varargin{1}; + mode = varargin{1}; else - start = 0; + mode = 0; end -switch start +switch mode case 1 - % start the time estimation + % mode the time estimation sw_time = tic; - switch fid + switch tid case 1 fprintf([repmat(' ',[1 40]) '\n']); case 2 @@ -99,7 +107,7 @@ function sw_timeit(percent,varargin) rtime = rtime-hou*60^2; min = floor(rtime/60); sec = floor(rtime - min*60); - switch fid + switch tid case 1 fprintf([repmat('\b',[1 41]) '%6.2f%%, remained: %03d:%02d:%02d (HH:MM:SS).\n'],... percent,hou,min,sec); @@ -121,7 +129,7 @@ function sw_timeit(percent,varargin) sec = floor(etime); %tho = floor((etime-sec)*1000); %fprintf('Finished in %02d:%02d:%02d.%03d (HH:MM:SS.FFF).\n',hou,min,sec,tho); - switch fid + switch tid case 1 fprintf(repmat('\b',1,40+1)); fprintf('Calculation is finished in %02d:%02d:%02d (hh:mm:ss).\n',hou,min,sec); @@ -151,4 +159,4 @@ function extended_waitbar() 'Position', pauseBtnPos,... 'Callback', 'dbstop in sw_timeit.m at 23'); -end \ No newline at end of file +end