@@ -657,6 +657,84 @@ def test_mode_solver_data_interp_extrapolation_warning():
657657 mode_data .interp_in_freq (freqs = freqs_extrap , method = "linear" )
658658
659659
660+ # ============================================================================
661+ # assume_sorted Tests (for source frequencies)
662+ # ============================================================================
663+
664+
665+ @pytest .mark .parametrize ("method" , ["linear" , "cubic" , "cheb" ])
666+ def test_interp_assume_sorted_source_frequencies (method ):
667+ """Test that assume_sorted correctly handles sorted vs unsorted source frequencies.
668+
669+ This test verifies that:
670+ - assume_sorted=True works correctly when source frequencies are sorted
671+ - assume_sorted=False correctly handles unsorted source frequencies
672+ - Both approaches produce identical interpolation results
673+
674+ Parameters
675+ ----------
676+ method : str
677+ Interpolation method to test: "linear", "cubic", or "cheb"
678+ """
679+ from tidy3d .components .data .data_array import ModeIndexDataArray
680+ from tidy3d .components .data .dataset import FreqDataset
681+
682+ # Define number of source frequencies based on method requirements
683+ num_source_points = {"linear" : 5 , "cubic" : 5 , "cheb" : 5 }[method ]
684+
685+ # Generate sorted source frequencies using ModeInterpSpec.sampling_points
686+ interp_spec = td .ModeInterpSpec (num_points = num_source_points , method = method )
687+ freqs_full_range = np .linspace (1e14 , 2e14 , 100 ) # Full frequency range
688+ freqs_source_sorted = interp_spec .sampling_points (freqs_full_range )
689+
690+ # Create unsorted version by shuffling
691+ rng = np .random .RandomState (42 ) # Fixed seed for reproducibility
692+ shuffle_indices = np .arange (len (freqs_source_sorted ))
693+ rng .shuffle (shuffle_indices )
694+ freqs_source_unsorted = freqs_source_sorted [shuffle_indices ]
695+
696+ # Create test data values
697+ mode_indices = np .arange (2 )
698+ data_values = (1.5 + 0.1j ) * np .random .random ((num_source_points , 2 ))
699+
700+ # Create dataset with SORTED source frequencies
701+ data_sorted = ModeIndexDataArray (
702+ data_values .copy (), coords = {"f" : freqs_source_sorted , "mode_index" : mode_indices }
703+ )
704+
705+ # Create dataset with UNSORTED source frequencies
706+ # Need to reorder data values to match the shuffled frequencies
707+ data_unsorted = ModeIndexDataArray (
708+ data_values [shuffle_indices ],
709+ coords = {"f" : freqs_source_unsorted , "mode_index" : mode_indices },
710+ )
711+
712+ # Define target frequencies for interpolation
713+ freqs_target = np .linspace (1e14 , 2e14 , 50 )
714+
715+ # Interpolate with sorted source frequencies and assume_sorted=True
716+ result_sorted = FreqDataset ._interp_dataarray_in_freq (
717+ data_sorted , freqs_target , method = method , assume_sorted = True
718+ )
719+
720+ # Interpolate with unsorted source frequencies and assume_sorted=False
721+ # This should internally sort the data before interpolating
722+ result_unsorted = FreqDataset ._interp_dataarray_in_freq (
723+ data_unsorted , freqs_target , method = method , assume_sorted = False
724+ )
725+
726+ # Both approaches should produce identical results
727+ assert np .allclose (result_sorted .values , result_unsorted .values , rtol = 1e-10 ), (
728+ f"{ method } interpolation: sorted and unsorted source frequencies "
729+ "should produce identical results"
730+ )
731+
732+ # Verify the interpolation actually happened correctly
733+ assert result_sorted .shape == (50 , 2 )
734+ assert len (result_sorted .coords ["f" ]) == 50
735+ assert np .allclose (result_sorted .coords ["f" ].values , freqs_target )
736+
737+
660738# ============================================================================
661739# ModeSolver Integration Tests (Phase 5)
662740# ============================================================================
0 commit comments