@@ -563,6 +563,69 @@ def g(X):
563563 assert np .allclose (X_posterior_highlevel_API , X_posterior_lowlevel_API )
564564
565565
566+ @pytest .mark .parametrize ("inversion" , ESMDA ._inversion_methods .keys ())
567+ def test_row_by_row_assimilation_order (inversion ):
568+ """A regression test for issue #232.
569+
570+ The problem was that in a SVD call we had
571+
572+ sp.linalg.svd(a, overwrite_a=True, ...)
573+
574+ but the array a was used later on in the function. This bug was not spotted
575+ because when the input array is contiguous (C-order), then no actual overwrite
576+ is done by the SVD. However, in F-order it does overwrite the input array,
577+ which does lead to the wrong values being used later on in the function.
578+
579+ The fix is to carefully review all usage of 'overwrite_a' and only keep
580+ overwriting if the input array is not used later on, and is not part
581+ of the input arguments to a function.
582+ """
583+ rng = np .random .default_rng (42 )
584+
585+ num_outputs = 4
586+ num_inputs = 5
587+ num_ensemble = 3
588+
589+ A = rng .normal (size = (num_outputs , num_inputs ))
590+
591+ def g (X ):
592+ return A @ X
593+
594+ X_prior = rng .normal (size = (num_inputs , num_ensemble ))
595+ covariance = np .exp (rng .normal (size = num_outputs ))
596+ observations = A @ np .linspace (0 , 1 , num = num_inputs ) + rng .normal (
597+ size = num_outputs , scale = 0.01
598+ )
599+
600+ # We need two instances because each call to 'compute_transition_matrix'
601+ # increments the random number generator.
602+ smoother1 = ESMDA (
603+ covariance = covariance ,
604+ observations = observations ,
605+ alpha = 2 ,
606+ inversion = inversion ,
607+ seed = 1 ,
608+ )
609+
610+ smoother2 = ESMDA (
611+ covariance = covariance ,
612+ observations = observations ,
613+ alpha = 2 ,
614+ inversion = inversion ,
615+ seed = 1 ,
616+ )
617+
618+ X = np .copy (X_prior )
619+ alpha_i = 2.5
620+
621+ # Test that no matter which order the input is in, the output is equal
622+ K1 = smoother1 .compute_transition_matrix (
623+ Y = np .ascontiguousarray (g (X )), alpha = alpha_i
624+ )
625+ K2 = smoother2 .compute_transition_matrix (Y = np .asfortranarray (g (X )), alpha = alpha_i )
626+ assert np .allclose (K1 , K2 )
627+
628+
566629if __name__ == "__main__" :
567630 import pytest
568631
0 commit comments