def test_depth_kwarg(self): nz = 20 zin = 0.5 * nz**-1 + np.arange(nz, dtype=np.float64) / nz N2 = np.full(nz, 1.) f0 = 1. with self.assertRaises(ValueError): z, def_radius, bc_modes = modes.neutral_modes_from_N2_profile( zin, N2, f0, depth=zin[-5]) # no error expected z, def_radius, bc_modes = modes.neutral_modes_from_N2_profile( zin, N2, f0, depth=1.1)
def test_depth_kwarg(self): nz = 20 zin = 0.5*nz**-1 + np.arange(nz, dtype=np.float64)/nz N2 = np.full(nz, 1.) f0 = 1. with self.assertRaises(ValueError): z, def_radius, bc_modes = modes.neutral_modes_from_N2_profile( zin, N2, f0, depth=zin[-5] ) # no error expected z, def_radius, bc_modes = modes.neutral_modes_from_N2_profile( zin, N2, f0, depth=1.1 )
def test_N2_const_equal_spacing(self): # prepare a test N^2 profile nz = 20 depth = 0.5*nz**-1 + np.arange(nz, dtype=np.float64)/nz N2 = np.full(nz, 1.) f0 = 1. z, def_radius, bc_modes = modes.neutral_modes_from_N2_profile( depth, N2, f0 ) # make sure we got the right number of modes # NOPE! don't want all the modes and scipy.sparse.linalg.eigs won't # compute them #self.assertEqual(nz, len(def_radius)) # make sure the modes themselves have the right structure self.assertEqual(nz+1, bc_modes.shape[0], msg='modes array must the right shape') self.assertTrue(np.all(np.diff(def_radius[1:]) < 0), msg='modes should be sorted in order of decreasing deformation radius') nmodes = len(def_radius) zero_crossings = np.abs(np.diff(np.sign(bc_modes), axis=0)/2).sum(axis=0) self.assertListEqual(list(range(nmodes)), list(zero_crossings), msg='modes should have the correct number of zero crossings') mode_amplitudes = (bc_modes**2).sum(axis=0) self.assertTrue(np.allclose(np.ones(nmodes), mode_amplitudes), msg='modes should be normalized to amplitude of 1')
def test_N2_const_equal_spacing(self): # prepare a test N^2 profile nz = 20 depth = 0.5 * nz**-1 + np.arange(nz, dtype=np.float64) / nz N2 = np.full(nz, 1.) f0 = 1. z, def_radius, bc_modes = modes.neutral_modes_from_N2_profile( depth, N2, f0) self.assertEqual(nz + 1, bc_modes.shape[0], msg='modes array must the right shape') self.assertTrue( np.all(np.diff(def_radius[1:]) < 0), msg= 'modes should be sorted in order of decreasing deformation radius') nmodes = len(def_radius) zero_crossings = np.abs(np.diff(np.sign(bc_modes), axis=0) / 2).sum(axis=0) self.assertListEqual( list(range(nmodes)), list(zero_crossings), msg='modes should have the correct number of zero crossings') mode_amplitudes = (bc_modes**2).sum(axis=0) self.assertTrue(np.allclose(np.ones(nmodes), mode_amplitudes), msg='modes should be normalized to amplitude of 1')
def test_neutral_mode_args(self): nz = 10 N2 = np.zeros(nz) depth = np.arange(nz) # check for unequal lengths of arrays with self.assertRaises(ValueError): _, _, _ = modes.neutral_modes_from_N2_profile(depth[1:], N2, 1.) with self.assertRaises(ValueError): _, _, _ = modes.neutral_modes_from_N2_profile(depth, N2[1:], 1.) depth_non_monotonic = depth depth_non_monotonic[0] = 5 # check for non-monotonic profile with self.assertRaises(ValueError) as cm: _, _, _ = modes.neutral_modes_from_N2_profile( depth_non_monotonic, N2, 1.)
def test_neutral_mode_OCCA_GulfStream(self): """ Test profile in the Gulf Stream in the OCCA data set """ zN2 = np.array([ -10.00006115, -20.00006114, -30.00006113, -40.00006112, -50.0000611 , -60.00006109, -70.00256358, -80.01506451, -90.06006328, -100.20256308, -110.5900682 , -121.51007976, -133.44509256, -147.10512803, -163.43519352, -183.5678012 , -208.72298023, -240.09073926, -278.70109317, -325.30655719, -380.30712264, -443.70276088, -515.09343642, -593.72659767, -678.57216844, -768.44015906, -862.11055267, -958.45325725, -1056.53586028, -1155.72595435, -1255.87608991, -1357.68378579, -1463.12934261, -1575.64299213, -1699.66489761, -1839.65538686, -1999.10931291, -2180.15155508, -2383.76440293, -2610.28273438, -2859.78914881, -3132.29607118, -3427.80347989, -3746.3113517 , -4087.81966191, -4452.32838443, -4839.83749199, -5250.34695635, -5683.85674858]) N2 = np.array([ 4.49013733e-05, 1.32619531e-04, 1.67213349e-04, 1.39980381e-04, 1.08620176e-04, 8.89353316e-05, 7.59696940e-05, 6.85660114e-05, 6.13053056e-05, 4.96623307e-05, 4.26153730e-05, 3.83933836e-05, 3.33244718e-05, 3.14573673e-05, 2.74780120e-05, 2.50869570e-05, 2.35907064e-05, 2.26047540e-05, 2.06309696e-05, 1.93499569e-05, 1.85802260e-05, 1.73887368e-05, 1.49995125e-05, 1.25945779e-05, 1.06210281e-05, 9.69791903e-06, 9.18845407e-06, 7.56655382e-06, 5.00383224e-06, 2.83633215e-06, 1.67170878e-06, 1.19350982e-06, 9.87252978e-07, 9.54096555e-07, 1.05979705e-06, 1.18957478e-06, 1.23432375e-06, 1.22190029e-06, 1.20084648e-06, 1.18287498e-06, 1.14801849e-06, 1.08643614e-06, 9.36511867e-07, 6.17342678e-07, 3.35507108e-07, 3.19646379e-07, 2.60733349e-07, np.nan, np.nan]) f0 = 9.276710625272244e-05 nz = len(zN2) kwargs = {'num_eigen': 2, 'init_vector': None, 'num_Lanczos': nz*10, 'iteration': nz*100, 'tolerance': 0} zphi, Rd, v = modes.neutral_modes_from_N2_profile( -zN2, N2, f0, **kwargs) self.assertTrue(np.isclose(Rd[1], 25787.38588731), msg='Rossby radius should be exact to the solution') self.assertTrue(np.allclose(np.diff(v[:, 0]), 0.), msg='The barotropic vertical mode should have all same value') v1 = np.array([ 0.2287108, 0.22844163, 0.22738221, 0.22538205, 0.22315635, 0.22100572, 0.21890111, 0.21681132, 0.21466035, 0.21249153, 0.21051281, 0.20857709, 0.20653185, 0.20436013, 0.20172795, 0.19864415, 0.19475028, 0.18960952, 0.18268901, 0.17391394, 0.16270843, 0.14845062, 0.13133273, 0.11305419, 0.09473064, 0.07691331, 0.05874788, 0.04009015, 0.02387257, 0.01278873, 0.00637754, 0.00253038, -0.00029387, -0.00275014, -0.00532013, -0.00849032, -0.01248929, -0.01713441, -0.02220176, -0.02756655, -0.0331077, -0.03857259, -0.04363333, -0.04770119, -0.05004272, -0.05105026, -0.05168191, -0.05185931]) self.assertTrue(np.allclose(np.absolute(v[:, 1]), np.absolute(v1)), msg='The amplitude of vertical modes should have the exact elements')
def test_neutral_mode_args(self): nz = 10 N2 = np.zeros(nz) depth = np.arange(nz) # check for unequal lengths of arrays with self.assertRaises(ValueError): _, _, _ = modes.neutral_modes_from_N2_profile( depth[1:], N2, 1. ) with self.assertRaises(ValueError): _, _, _ = modes.neutral_modes_from_N2_profile( depth, N2[1:], 1. ) depth_non_monotonic = depth depth_non_monotonic[0] = 5 # check for non-monotonic profile with self.assertRaises(ValueError) as cm: _, _, _ = modes.neutral_modes_from_N2_profile( depth_non_monotonic, N2, 1. )
def test_neutral_mode_OCCA_GulfStream(self): """ Test profile in the Gulf Stream in the OCCA data set """ zN2 = np.array([ -10.00006115, -20.00006114, -30.00006113, -40.00006112, -50.0000611, -60.00006109, -70.00256358, -80.01506451, -90.06006328, -100.20256308, -110.5900682, -121.51007976, -133.44509256, -147.10512803, -163.43519352, -183.5678012, -208.72298023, -240.09073926, -278.70109317, -325.30655719, -380.30712264, -443.70276088, -515.09343642, -593.72659767, -678.57216844, -768.44015906, -862.11055267, -958.45325725, -1056.53586028, -1155.72595435, -1255.87608991, -1357.68378579, -1463.12934261, -1575.64299213, -1699.66489761, -1839.65538686, -1999.10931291, -2180.15155508, -2383.76440293, -2610.28273438, -2859.78914881, -3132.29607118, -3427.80347989, -3746.3113517, -4087.81966191, -4452.32838443, -4839.83749199, -5250.34695635, -5683.85674858 ]) N2 = np.array([ 4.49013733e-05, 1.32619531e-04, 1.67213349e-04, 1.39980381e-04, 1.08620176e-04, 8.89353316e-05, 7.59696940e-05, 6.85660114e-05, 6.13053056e-05, 4.96623307e-05, 4.26153730e-05, 3.83933836e-05, 3.33244718e-05, 3.14573673e-05, 2.74780120e-05, 2.50869570e-05, 2.35907064e-05, 2.26047540e-05, 2.06309696e-05, 1.93499569e-05, 1.85802260e-05, 1.73887368e-05, 1.49995125e-05, 1.25945779e-05, 1.06210281e-05, 9.69791903e-06, 9.18845407e-06, 7.56655382e-06, 5.00383224e-06, 2.83633215e-06, 1.67170878e-06, 1.19350982e-06, 9.87252978e-07, 9.54096555e-07, 1.05979705e-06, 1.18957478e-06, 1.23432375e-06, 1.22190029e-06, 1.20084648e-06, 1.18287498e-06, 1.14801849e-06, 1.08643614e-06, 9.36511867e-07, 6.17342678e-07, 3.35507108e-07, 3.19646379e-07, 2.60733349e-07, np.nan, np.nan ]) f0 = 9.276710625272244e-05 nz = len(zN2) kwargs = { 'num_eigen': 2, 'init_vector': None, 'num_Lanczos': nz * 10, 'iteration': nz * 100, 'tolerance': 0 } zphi, Rd, v = modes.neutral_modes_from_N2_profile( -zN2, N2, f0, **kwargs) self.assertTrue(np.isclose(Rd[1], 25787.38588731), msg='Rossby radius should be exact to the solution') self.assertTrue( np.allclose(np.diff(v[:, 0]), 0.), msg='The barotropic vertical mode should have all same value') v1 = np.array([ 0.2287108, 0.22844163, 0.22738221, 0.22538205, 0.22315635, 0.22100572, 0.21890111, 0.21681132, 0.21466035, 0.21249153, 0.21051281, 0.20857709, 0.20653185, 0.20436013, 0.20172795, 0.19864415, 0.19475028, 0.18960952, 0.18268901, 0.17391394, 0.16270843, 0.14845062, 0.13133273, 0.11305419, 0.09473064, 0.07691331, 0.05874788, 0.04009015, 0.02387257, 0.01278873, 0.00637754, 0.00253038, -0.00029387, -0.00275014, -0.00532013, -0.00849032, -0.01248929, -0.01713441, -0.02220176, -0.02756655, -0.0331077, -0.03857259, -0.04363333, -0.04770119, -0.05004272, -0.05105026, -0.05168191, -0.05185931 ]) self.assertTrue( np.allclose(np.absolute(v[:, 1]), np.absolute(v1)), msg='The amplitude of vertical modes should have the exact elements' )