def test_ChebyMapDM10496(self): """Test for a segfault when simplifying a SeriesMap We saw an intermittent segfault when simplifying a SeriesMap consisting of the inverse of PolyMap with 2 inputs and one output followed by its inverse (which should simplify to a UnitMap with one input and one output). David Berry fixed this bug in AST 2017-05-10. I tried this test on an older version of astshim and found that it triggering a segfault nearly every time. """ coeff_f = np.array([ [-1.1, 1, 2, 0], [1.3, 1, 3, 1], ]) coeff_i = np.array([ [1.6, 1, 3], [-3.6, 2, 1], ]) lbnd_f = [-2.0, -2.5] ubnd_f = [1.5, -0.5] lbnd_i = [-3.0] ubnd_i = [-1.0] # execute many times to increase the odds of a segfault for i in range(1000): amap = ast.ChebyMap(coeff_f, coeff_i, lbnd_f, ubnd_f, lbnd_i, ubnd_i) amapinv = amap.getInverse() cmp2 = amapinv.then(amap) result = cmp2.simplify() self.assertIsInstance(result, ast.UnitMap)
def test_chebyGetDomain(self): """Test ChebyMap.getDomain's ability to estimate values This occurs when there is only one map and you want the inverse """ nout = 2 lbnd_f = [-2.0, -2.5] ubnd_f = [1.5, 2.5] # Coefficients for the following not-gently-varying polynomial: # y1 = 2.0 T2(x1') T0(x2') - 2.0 T0(x1') T2(x2') # y2 = 1.0 T3(x1') T0(x2') - 2.0 T0(x1') T3(x2') coeff_f = np.array([ [2.0, 1, 2, 0], [-2.0, 1, 0, 2], [1.0, 2, 3, 0], [-2.0, 2, 0, 3], ]) chebyMap1 = ast.ChebyMap(coeff_f, nout, lbnd_f, ubnd_f) # compute indata as a grid of points that cover the input range x1Edge = np.linspace(lbnd_f[0], ubnd_f[0], 1000) x2Edge = np.linspace(lbnd_f[1], ubnd_f[1], 1000) x1Grid, x2Grid = np.meshgrid(x1Edge, x2Edge) indata = np.array([x1Grid.ravel(), x2Grid.ravel()]) outdata = chebyMap1.applyForward(indata) pred_lbnd = outdata.min(1) pred_ubnd = outdata.max(1) domain = chebyMap1.getDomain(forward=False) npt.assert_allclose(domain.lbnd, pred_lbnd, atol=0.0001) npt.assert_allclose(domain.ubnd, pred_ubnd, atol=0.0001)
def test_ChebyMapChebyMapUnivertible(self): """Test polyTran on a ChebyMap without a single-valued inverse """ nin = 2 nout = 2 lbnd_f = [-2.0, -2.5] ubnd_f = [1.5, 2.5] # arbitrary points that cover the input range indata = np.array([ [-2.0, -1.0, 0.1, 1.5, 1.0], [0.0, -2.5, -0.2, 2.5, 2.5], ]) # Coefficients for the following not-gently-varying polynomial: # y1 = 2.0 T2(x1') T0(x2') - 2.0 T0(x1') T2(x2') # y2 = 1.0 T3(x1') T0(x2') - 2.0 T0(x1') T3(x2') coeff_f = np.array([ [2.0, 1, 2, 0], [-2.0, 1, 0, 2], [1.0, 2, 3, 0], [-2.0, 2, 0, 3], ]) self.assertEqual(nin, coeff_f.shape[1] - 2) def referenceFunc(point): """Reference implementation; point must be in range [-1, 1] """ c1 = np.zeros((3, 3)) c1[2, 0] = 2.0 c1[0, 2] = -2.0 c2 = np.zeros((4, 4)) c2[3, 0] = 1.0 c2[0, 3] = -2.0 x1, x2 = point return ( chebval2d(x1, x2, c1), chebval2d(x1, x2, c2), ) chebyMap1 = ast.ChebyMap(coeff_f, nout, lbnd_f, ubnd_f) self.checkBasicSimplify(chebyMap1) self.assertTrue(chebyMap1.hasForward) self.assertFalse(chebyMap1.hasInverse) outdata = chebyMap1.applyForward(indata) referenceCheby = ReferenceCheby(referenceFunc, lbnd_f, ubnd_f) des_outdata = referenceCheby.transform(indata) npt.assert_allclose(outdata, des_outdata) with self.assertRaises(RuntimeError): chebyMap1.polyTran(forward=False, acc=0.0001, maxacc=0.001, maxorder=6, lbnd=lbnd_f, ubnd=ubnd_f)
def test_chebyMapUnidirectional_2_2(self): """Test one-directional ChebyMap with 2 inputs and 2 outputs This is a long test because it is a bit of a nuisance setting up the reference transform, so once I have it, I use it for three different ChebyMaps (forward-only, forward with no inverse, and inverse with no forward). """ nin = 2 nout = 2 lbnd_f = [-2.0, -2.5] ubnd_f = [1.5, 2.5] # Coefficients for the following polynomial: # y1 = 1.2 T2(x1') T0(x2') - 0.5 T1(x1') T1(x2') # y2 = 1.0 T0(x1') T1(x2') coeff_f = np.array([ [1.2, 1, 2, 0], [-0.5, 1, 1, 1], [1.0, 2, 0, 1], ]) self.assertEqual(nin, coeff_f.shape[1] - 2) def referenceFunc(point): """Reference implementation; point must be in range [-1, 1] """ c1 = np.zeros((3, 3)) c1[2, 0] = 1.2 c1[1, 1] = -0.5 c2 = np.zeros((3, 3)) c2[0, 1] = 1.0 x1, x2 = point return ( chebval2d(x1, x2, c1), chebval2d(x1, x2, c2), ) null_coeff = np.zeros(shape=(0, 4)) self.assertEqual(nin, null_coeff.shape[1] - 2) # arbitary input points that cover the full domain indata = np.array([ [-2.0, -0.5, 0.5, 1.5], [-2.5, 1.5, -0.5, 2.5], ]) refCheby = ReferenceCheby(referenceFunc, lbnd_f, ubnd_f) # forward-only constructor chebyMap1 = ast.ChebyMap(coeff_f, nout, lbnd_f, ubnd_f) self.assertIsInstance(chebyMap1, ast.Object) self.assertIsInstance(chebyMap1, ast.Mapping) self.assertIsInstance(chebyMap1, ast.ChebyMap) self.assertEqual(chebyMap1.nIn, nin) self.assertEqual(chebyMap1.nOut, nout) self.assertTrue(chebyMap1.hasForward) self.assertFalse(chebyMap1.hasInverse) self.checkBasicSimplify(chebyMap1) self.checkCopy(chebyMap1) self.checkMappingPersistence(chebyMap1, indata) domain1 = chebyMap1.getDomain(forward=True) npt.assert_allclose(domain1.lbnd, lbnd_f) npt.assert_allclose(domain1.ubnd, ubnd_f) outdata = chebyMap1.applyForward(indata) with self.assertRaises(RuntimeError): chebyMap1.applyInverse(indata) pred_outdata = refCheby.transform(indata) npt.assert_allclose(outdata, pred_outdata) # bidirectional constructor, forward only specified chebyMap2 = ast.ChebyMap(coeff_f, null_coeff, lbnd_f, ubnd_f, [], []) self.assertIsInstance(chebyMap2, ast.Object) self.assertIsInstance(chebyMap2, ast.Mapping) self.assertIsInstance(chebyMap2, ast.ChebyMap) self.assertEqual(chebyMap2.nIn, nin) self.assertEqual(chebyMap2.nOut, nout) self.assertTrue(chebyMap2.hasForward) self.assertFalse(chebyMap2.hasInverse) self.checkBasicSimplify(chebyMap2) self.checkCopy(chebyMap2) self.checkMappingPersistence(chebyMap1, indata) domain2 = chebyMap2.getDomain(forward=True) npt.assert_allclose(domain2.lbnd, lbnd_f) npt.assert_allclose(domain2.ubnd, ubnd_f) outdata2 = chebyMap2.applyForward(indata) npt.assert_allclose(outdata2, outdata) with self.assertRaises(RuntimeError): chebyMap2.applyInverse(indata) # bidirectional constructor, inverse only specified chebyMap3 = ast.ChebyMap(null_coeff, coeff_f, [], [], lbnd_f, ubnd_f) self.assertIsInstance(chebyMap3, ast.Object) self.assertIsInstance(chebyMap3, ast.Mapping) self.assertIsInstance(chebyMap3, ast.ChebyMap) self.assertEqual(chebyMap3.nIn, nin) self.assertEqual(chebyMap3.nOut, nout) self.assertFalse(chebyMap3.hasForward) self.assertTrue(chebyMap3.hasInverse) domain3 = chebyMap3.getDomain(forward=False) npt.assert_allclose(domain3.lbnd, lbnd_f) npt.assert_allclose(domain3.ubnd, ubnd_f) outdata3 = chebyMap3.applyInverse(indata) npt.assert_allclose(outdata3, outdata) with self.assertRaises(RuntimeError): chebyMap3.applyForward(indata)
def test_ChebyMapPolyTran(self): nin = 2 nout = 2 lbnd_f = [-2.0, -2.5] ubnd_f = [1.5, 2.5] # arbitrary points that cover the input range indata = np.array([ [-2.0, -1.0, 0.1, 1.5, 1.0], [0.0, -2.5, -0.2, 2.5, 2.5], ]) # Coefficients for the following gently varying polynomial: # y1 = -2.0 T0(x1') T0(x2') + 0.11 T1(x1') T0(x2') - 0.2 T0(x1') T1(x2') + 0.001 T2(x1') T1(x2') # y2 = 5.1 T0(x1') T0(x2') - 0.55 T1(x1') T0(x2') + 0.13 T0(x1') T1(x2') - 0.002 T1(x1') T2(x2') coeff_f = np.array([[-2.0, 1, 0, 0], [0.11, 1, 1, 0], [-0.2, 1, 0, 1], [0.001, 1, 2, 1], [5.1, 2, 0, 0], [-0.55, 2, 1, 0], [0.13, 2, 0, 1], [-0.002, 2, 1, 2]]) self.assertEqual(nin, coeff_f.shape[1] - 2) def referenceFunc(point): """Reference implementation; point must be in range [-1, 1] """ c1 = np.zeros((3, 3)) c1[0, 0] = -2 c1[1, 0] = 0.11 c1[0, 1] = -0.2 c1[2, 1] = 0.001 c2 = np.zeros((3, 3)) c2[0, 0] = 5.1 c2[1, 0] = -0.55 c2[0, 1] = 0.13 c2[1, 2] = -0.002 x1, x2 = point return ( chebval2d(x1, x2, c1), chebval2d(x1, x2, c2), ) chebyMap1 = ast.ChebyMap(coeff_f, nout, lbnd_f, ubnd_f) self.checkBasicSimplify(chebyMap1) self.assertTrue(chebyMap1.hasForward) self.assertFalse(chebyMap1.hasInverse) outdata = chebyMap1.applyForward(indata) referenceCheby = ReferenceCheby(referenceFunc, lbnd_f, ubnd_f) des_outdata = referenceCheby.transform(indata) npt.assert_allclose(outdata, des_outdata) # fit an inverse transform chebyMap2 = chebyMap1.polyTran(forward=False, acc=0.0001, maxacc=0.001, maxorder=6, lbnd=lbnd_f, ubnd=ubnd_f) self.assertTrue(chebyMap2.hasForward) self.assertTrue(chebyMap2.hasInverse) # forward should be identical to the original npt.assert_equal(chebyMap2.applyForward(indata), outdata) roundTripIn2 = chebyMap2.applyInverse(outdata) npt.assert_allclose(roundTripIn2, indata, atol=0.0002) # fit an inverse transform with default bounds (which are the same bounds # used for fitting chebyMap2, so the results should be the same) chebyMap3 = chebyMap1.polyTran(forward=False, acc=0.0001, maxacc=0.001, maxorder=6) self.assertTrue(chebyMap2.hasForward) self.assertTrue(chebyMap2.hasInverse) # forward should be identical to the original npt.assert_equal(chebyMap3.applyForward(indata), outdata) # inverse should be basically the same roundTripIn3 = chebyMap3.applyInverse(outdata) npt.assert_allclose(roundTripIn3, roundTripIn2)
def test_ChebyMapBidirectional(self): """Test a ChebyMap with separate forward and inverse mappings For simplicity, they are not the inverse of each other. """ nin = 2 nout = 1 lbnd_f = [-2.0, -2.5] ubnd_f = [1.5, -0.5] # cover the domain indata_f = np.array([ [-2.0, -1.5, 0.1, 1.5], [-1.0, -2.5, -0.5, -0.5], ]) lbnd_i = [-3.0] ubnd_i = [-1.0] # cover the domain indata_i = np.array([ [-3.0, -1.1, -1.5, -2.3, -1.0], ]) # Coefficients for the following polynomial: # y1 = -1.1 T2(x1') T0(x2') + 1.3 T3(x1') T1(x2') coeff_f = np.array([ [-1.1, 1, 2, 0], [1.3, 1, 3, 1], ]) self.assertEqual(nin, coeff_f.shape[1] - 2) def referenceFunc_f(point): """Reference forward implementation; point must be in range [-1, 1] """ c1 = np.zeros((4, 4)) c1[2, 0] = -1.1 c1[3, 1] = 1.3 x1, x2 = point return (chebval2d(x1, x2, c1), ) # Coefficients for the following polynomial: # y1 = 1.6 T3(x1') # y2 = -3.6 T1(x1') coeff_i = np.array([ [1.6, 1, 3], [-3.6, 2, 1], ]) self.assertEqual(nout, coeff_i.shape[1] - 2) def referenceFunc_i(point): """Reference inverse implementation; point must be in range [-1, 1] """ c1 = np.array([0, 0, 0, 1.6], dtype=float) c2 = np.array([0, -3.6], dtype=float) x1 = point return ( chebval(x1, c1), chebval(x1, c2), ) refCheby_f = ReferenceCheby(referenceFunc_f, lbnd_f, ubnd_f) refCheby_i = ReferenceCheby(referenceFunc_i, lbnd_i, ubnd_i) chebyMap = ast.ChebyMap(coeff_f, coeff_i, lbnd_f, ubnd_f, lbnd_i, ubnd_i) self.assertEqual(chebyMap.nIn, 2) self.assertEqual(chebyMap.nOut, 1) self.checkBasicSimplify(chebyMap) self.checkCopy(chebyMap) self.checkMappingPersistence(chebyMap, indata_f) outdata_f = chebyMap.applyForward(indata_f) des_outdata_f = refCheby_f.transform(indata_f) npt.assert_allclose(outdata_f, des_outdata_f) outdata_i = chebyMap.applyInverse(indata_i) des_outdata_i = refCheby_i.transform(indata_i) npt.assert_allclose(outdata_i, des_outdata_i)