Source code for armi.utils.tests.test_mathematics

# Copyright 2022 TerraPower, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Testing mathematics utilities."""
from math import sqrt
import unittest

import numpy as np

from armi.utils.mathematics import (
    average1DWithinTolerance,
    convertToSlice,
    efmt,
    expandRepeatedFloats,
    findClosest,
    findNearestValue,
    fixThreeDigitExp,
    getFloat,
    getStepsFromValues,
    isMonotonic,
    linearInterpolation,
    minimizeScalarFunc,
    newtonsMethod,
    parabolaFromPoints,
    parabolicInterpolation,
    relErr,
    resampleStepwise,
    rotateXY,
)


[docs]class TestMath(unittest.TestCase): """Tests for various math utilities."""
[docs] def test_average1DWithinTolerance(self): vals = np.array([np.array([1, 2, 3]), np.array([4, 5, 6]), np.array([7, 8, 9])]) result = average1DWithinTolerance(vals, 0.1) self.assertEqual(len(result), 3) self.assertEqual(result[0], 4.0) self.assertEqual(result[1], 5.0) self.assertEqual(result[2], 6.0)
[docs] def test_average1DWithinToleranceInvalid(self): vals = np.array( [np.array([1, -2, 3]), np.array([4, -5, 6]), np.array([7, -8, 9])] ) with self.assertRaises(ValueError): average1DWithinTolerance(vals, 0.1)
[docs] def test_convertToSlice(self): slice1 = convertToSlice(2) self.assertEqual(slice1, slice(2, 3, None)) slice1 = convertToSlice(2.0, increment=-1) self.assertEqual(slice1, slice(1, 2, None)) slice1 = convertToSlice(None) self.assertEqual(slice1, slice(None, None, None)) slice1 = convertToSlice([1, 2, 3]) self.assertTrue(np.allclose(slice1, np.array([1, 2, 3]))) slice1 = convertToSlice(slice(2, 3, None)) self.assertEqual(slice1, slice(2, 3, None)) slice1 = convertToSlice(np.array([1, 2, 3])) self.assertTrue(np.allclose(slice1, np.array([1, 2, 3]))) with self.assertRaises(Exception): slice1 = convertToSlice("slice")
[docs] def test_efmt(self): self.assertAlmostEqual(efmt("1.0e+001"), "1.0E+01") self.assertAlmostEqual(efmt("1.0E+01"), "1.0E+01")
[docs] def test_expandRepeatedFloats(self): repeatedFloats = ["150", "2R", 200.0, 175, "4r", 180.0, "0R"] expectedFloats = [150] * 3 + [200] + [175] * 5 + [180] self.assertEqual(expandRepeatedFloats(repeatedFloats), expectedFloats)
[docs] def test_findClosest(self): l1 = range(10) self.assertEqual(findClosest(l1, 5.6), 6) self.assertEqual(findClosest(l1, 10.1), 9) self.assertEqual(findClosest(l1, -200), 0) # with index self.assertEqual(findClosest(l1, 5.6, indx=True), (6, 6))
[docs] def test_findNearestValue(self): searchList = [0.1, 0.2, 0.25, 0.35, 0.4] searchValue = 0.225 self.assertEqual(findNearestValue(searchList, searchValue), 0.2) searchValue = 0.226 self.assertEqual(findNearestValue(searchList, searchValue), 0.25) searchValue = 0.0 self.assertEqual(findNearestValue(searchList, searchValue), 0.1) searchValue = 10 self.assertEqual(findNearestValue(searchList, searchValue), 0.4)
[docs] def test_fixThreeDigitExp(self): fixed = fixThreeDigitExp("-9.03231714805651E+101") self.assertEqual(-9.03231714805651e101, fixed) fixed = fixThreeDigitExp("9.03231714805651-101") self.assertEqual(9.03231714805651e-101, fixed) fixed = fixThreeDigitExp("-2.4594981981654+101") self.assertEqual(-2.4594981981654e101, fixed) fixed = fixThreeDigitExp("-2.4594981981654-101") self.assertEqual(-2.4594981981654e-101, fixed)
[docs] def test_getFloat(self): self.assertEqual(getFloat(1.0), 1.0) self.assertEqual(getFloat("1.0"), 1.0) self.assertIsNone(getFloat("word"))
[docs] def test_getStepsFromValues(self): steps = getStepsFromValues([1.0, 3.0, 6.0, 10.0], prevValue=0.0) self.assertListEqual(steps, [1.0, 2.0, 3.0, 4.0])
[docs] def test_isMonotonic(self): self.assertEqual(True, isMonotonic([1, 2, 2, 3], "<=")) self.assertEqual(False, isMonotonic([1, 2, 2, 1], "<=")) self.assertEqual(True, isMonotonic([1, 2, 3], "<")) self.assertEqual(False, isMonotonic([1, 2, 2], "<")) self.assertEqual(True, isMonotonic([3, 2, 1, 1], ">=")) self.assertEqual(False, isMonotonic([3, 2, 1, 2], ">=")) self.assertEqual(True, isMonotonic([3, 2, 1], ">")) self.assertEqual(False, isMonotonic([3, 2, 2], ">")) with self.assertRaises(ValueError): isMonotonic([1, 2, 3, 2], "invalidRelation")
[docs] def test_linearInterpolation(self): y = linearInterpolation(1.0, 2.0, 3.0, 4.0, targetX=20.0) x = linearInterpolation(1.0, 2.0, 3.0, 4.0, targetY=y) x2 = linearInterpolation(1.0, 1.0, 2.0, 2.0, targetY=50) self.assertEqual(x, 20.0) self.assertEqual(x2, 50.0) with self.assertRaises(ZeroDivisionError): _ = linearInterpolation(1.0, 1.0, 1.0, 2.0)
[docs] def test_minimizeScalarFunc(self): f = lambda x: (x + 1) ** 2 minimum = minimizeScalarFunc(f, -3.0, 10.0, maxIterations=10) self.assertAlmostEqual(minimum, -1.0, places=3) minimum = minimizeScalarFunc( f, -3.0, 10.0, maxIterations=10, positiveGuesses=True ) self.assertAlmostEqual(minimum, 0.0, places=3)
[docs] def test_newtonsMethod(self): f = lambda x: (x + 2) * (x - 1) root = newtonsMethod(f, 0.0, 5.0, maxIterations=10, positiveGuesses=True) self.assertAlmostEqual(root, 1.0, places=3) root = newtonsMethod(f, 0.0, -10.0, maxIterations=10) self.assertAlmostEqual(root, -2.0, places=3)
[docs] def test_parabola(self): # test the parabola function a, b, c = parabolaFromPoints((0, 1), (1, 2), (-1, 2)) self.assertEqual(a, 1.0) self.assertEqual(b, 0.0) self.assertEqual(c, 1.0) with self.assertRaises(Exception): a, b, c = parabolaFromPoints((0, 1), (0, 1), (-1, 2))
[docs] def test_parabolicInterpolation(self): realRoots = parabolicInterpolation(2.0e-6, -5.0e-4, 1.02, 1.0) self.assertAlmostEqual(realRoots[0][0], 200.0) self.assertAlmostEqual(realRoots[0][1], 3.0e-4) self.assertAlmostEqual(realRoots[1][0], 50.0) self.assertAlmostEqual(realRoots[1][1], -3.0e-4) noRoots = parabolicInterpolation(2.0e-6, -4.0e-4, 1.03, 1.0) self.assertAlmostEqual(noRoots[0][0], -100.0) self.assertAlmostEqual(noRoots[0][1], 0.0) # 3. run time error with self.assertRaises(RuntimeError): _ = parabolicInterpolation(2.0e-6, 4.0e-4, 1.02, 1.0)
[docs] def test_relErr(self): self.assertAlmostEqual(relErr(1.00, 1.01), 0.01) self.assertAlmostEqual(relErr(100.0, 97.0), -0.03) self.assertAlmostEqual(relErr(0.00, 1.00), -1e99)
[docs] def test_resampleStepwiseAvg0(self): """Test resampleStepwise() averaging when in and out bins match.""" xin = [0, 1, 2, 13.3] yin = [4.76, 9.99, -123.456] xout = [0, 1, 2, 13.3] yout = resampleStepwise(xin, yin, xout) self.assertEqual(len(yout), len(xout) - 1) self.assertAlmostEqual(yout[0], 4.76) self.assertAlmostEqual(yout[1], 9.99) self.assertAlmostEqual(yout[2], -123.456)
[docs] def test_resampleStepwiseAvg1(self): """Test resampleStepwise() averaging for one arbitrary case.""" xin = [0, 1, 2, 3, 4] yin = [3, 2, 5, 3] xout = [0, 2, 3.5, 4] yout = resampleStepwise(xin, yin, xout) self.assertEqual(len(yout), len(xout) - 1) self.assertEqual(yout[0], 2.5) self.assertAlmostEqual(yout[1], 4.333333333333333) self.assertEqual(yout[2], 3)
[docs] def test_resampleStepwiseAvg2(self): """Test resampleStepwise() averaging for another arbitrary case.""" xin = [0, 1, 2, 3, 4, 5] yin = [3, 2, 5, 3, 4] xout = [0, 2, 3.5, 5] yout = resampleStepwise(xin, yin, xout) self.assertEqual(len(yout), len(xout) - 1) self.assertEqual(yout[0], 2.5) self.assertAlmostEqual(yout[1], 4.333333333333333) self.assertAlmostEqual(yout[2], 3.6666666666666665)
[docs] def test_resampleStepwiseAvg3(self): """Test resampleStepwise() averaging for another arbitrary case.""" xin = [0, 1, 2, 3, 4, 6] yin = [3, 2, 5, 3, 4] xout = [0, 2, 3.5, 6] yout = resampleStepwise(xin, yin, xout) self.assertEqual(len(yout), len(xout) - 1) self.assertEqual(yout[0], 2.5) self.assertAlmostEqual(yout[1], 4.333333333333333) self.assertEqual(yout[2], 3.8)
[docs] def test_resampleStepwiseAvg4(self): """Test resampleStepwise() averaging for matching, but uneven intervals.""" xin = [0, 3, 5, 6.777, 9.123] yin = [3.1, 2.2, 5.3, 3.4] xout = [0, 3, 5, 6.777, 9.123] yout = resampleStepwise(xin, yin, xout) self.assertEqual(len(yout), len(xout) - 1) self.assertEqual(yout[0], 3.1) self.assertEqual(yout[1], 2.2) self.assertEqual(yout[2], 5.3) self.assertEqual(yout[3], 3.4)
[docs] def test_resampleStepwiseAvg5(self): """Test resampleStepwise() averaging for almost matching intervals.""" xin = [0, 3, 5, 6.777, 9.123] yin = [3.1, 2.2, 5.3, 3.4] xout = [0, 5, 9.123] yout = resampleStepwise(xin, yin, xout) self.assertEqual(len(yout), len(xout) - 1) self.assertEqual(yout[0], 2.74) self.assertAlmostEqual(yout[1], 4.21889400921659)
[docs] def test_resampleStepwiseAvg6(self): """Test resampleStepwise() averaging when the intervals don't line up.""" xin = [0, 1, 2, 3, 4] yin = [11, 22, 33, 44] xout = [2, 3, 4, 5, 6] yout = resampleStepwise(xin, yin, xout) self.assertEqual(len(yout), len(xout) - 1) self.assertEqual(yout[0], 33) self.assertEqual(yout[1], 44) self.assertEqual(yout[2], 0) self.assertEqual(yout[3], 0)
[docs] def test_resampleStepwiseAvg7(self): """Test resampleStepwise() averaging when the intervals don't line up.""" xin = [2, 4, 6, 8, 10] yin = [11, 22, 33, 44] xout = [-1, 0, 1, 2, 3, 4] yout = resampleStepwise(xin, yin, xout) self.assertEqual(len(yout), len(xout) - 1) self.assertEqual(yout[0], 0) self.assertEqual(yout[1], 0) self.assertEqual(yout[2], 0) self.assertEqual(yout[3], 11) self.assertEqual(yout[4], 11)
[docs] def test_resampleStepwiseSum0(self): """Test resampleStepwise() summing when in and out bins match.""" xin = [0, 1, 2, 13.3] yin = [4.76, 9.99, -123.456] xout = [0, 1, 2, 13.3] yout = resampleStepwise(xin, yin, xout, avg=False) self.assertEqual(len(yout), len(xout) - 1) self.assertAlmostEqual(yout[0], 4.76) self.assertAlmostEqual(yout[1], 9.99) self.assertAlmostEqual(yout[2], -123.456) self.assertAlmostEqual(sum(yin), sum(yout))
[docs] def test_resampleStepwiseSum1(self): """Test resampleStepwise() summing for one arbitrary case.""" xin = [0, 1, 2, 3, 4] yin = [3, 2, 5, 3] xout = [0, 2, 3.5, 4] yout = resampleStepwise(xin, yin, xout, avg=False) self.assertEqual(len(yout), len(xout) - 1) self.assertEqual(yout[0], 5) self.assertEqual(yout[1], 6.5) self.assertEqual(yout[2], 1.5) self.assertEqual(sum(yin), sum(yout))
[docs] def test_resampleStepwiseSum2(self): """Test resampleStepwise() summing for another arbitrary case.""" xin = [0, 1, 2, 3, 4, 5] yin = [3, 2, 5, 3, 4] xout = [0, 2, 3.5, 5] yout = resampleStepwise(xin, yin, xout, avg=False) self.assertEqual(len(yout), len(xout) - 1) self.assertEqual(yout[0], 5) self.assertEqual(yout[1], 6.5) self.assertEqual(yout[2], 5.5) self.assertEqual(sum(yin), sum(yout))
[docs] def test_resampleStepwiseSum3(self): """Test resampleStepwise() summing for another arbitrary case.""" xin = [0, 1, 2, 3, 4, 6] yin = [3, 2, 5, 3, 4] xout = [0, 2, 3.5, 6] yout = resampleStepwise(xin, yin, xout, avg=False) self.assertEqual(len(yout), len(xout) - 1) self.assertEqual(yout[0], 5) self.assertEqual(yout[1], 6.5) self.assertEqual(yout[2], 5.5) self.assertEqual(sum(yin), sum(yout))
[docs] def test_resampleStepwiseSum4(self): """Test resampleStepwise() summing for matching, but uneven intervals.""" xin = [0, 3, 5, 6.777, 9.123] yin = [3.1, 2.2, 5.3, 3.4] xout = [0, 3, 5, 6.777, 9.123] yout = resampleStepwise(xin, yin, xout, avg=False) self.assertEqual(len(yout), len(xout) - 1) self.assertEqual(yout[0], 3.1) self.assertEqual(yout[1], 2.2) self.assertEqual(yout[2], 5.3) self.assertEqual(yout[3], 3.4) self.assertEqual(sum(yin), sum(yout))
[docs] def test_resampleStepwiseSum5(self): """Test resampleStepwise() summing for almost matching intervals.""" xin = [0, 3, 5, 6.777, 9.123] yin = [3.1, 2.2, 5.3, 3.4] xout = [0, 5, 9.123] yout = resampleStepwise(xin, yin, xout, avg=False) self.assertEqual(len(yout), len(xout) - 1) self.assertAlmostEqual(yout[0], 5.3) self.assertAlmostEqual(yout[1], 8.7) self.assertAlmostEqual(sum(yin), sum(yout))
[docs] def test_resampleStepwiseSum6(self): """Test resampleStepwise() summing when the intervals don't line up.""" xin = [0, 1, 2, 3, 4] yin = [11, 22, 33, 44] xout = [2, 3, 4, 5, 6] yout = resampleStepwise(xin, yin, xout, avg=False) self.assertEqual(len(yout), len(xout) - 1) self.assertEqual(yout[0], 33) self.assertEqual(yout[1], 44) self.assertEqual(yout[2], 0) self.assertEqual(yout[3], 0)
[docs] def test_resampleStepwiseSum7(self): """Test resampleStepwise() summing when the intervals don't line up.""" xin = [2, 4, 6, 8, 10] yin = [11, 22, 33, 44] xout = [-1, 0, 1, 2, 3, 4] yout = resampleStepwise(xin, yin, xout, avg=False) self.assertEqual(len(yout), len(xout) - 1) self.assertEqual(yout[0], 0) self.assertEqual(yout[1], 0) self.assertEqual(yout[2], 0) self.assertAlmostEqual(yout[3], 11 / 2) self.assertAlmostEqual(yout[4], 11 / 2)
[docs] def test_resampleStepwiseAvgAllNones(self): """Test resampleStepwise() averaging when the inputs are all None.""" xin = [0, 1, 2, 13.3] yin = [None, None, None] xout = [0, 1, 2, 13.3] yout = resampleStepwise(xin, yin, xout) self.assertEqual(len(yout), len(xout) - 1) self.assertIsNone(yout[0]) self.assertIsNone(yout[1]) self.assertIsNone(yout[2])
[docs] def test_resampleStepwiseAvgOneNone(self): """Test resampleStepwise() averaging when one input is None.""" xin = [0, 1, 2, 13.3] yin = [None, 1, 2] xout = [0, 1, 2, 13.3] yout = resampleStepwise(xin, yin, xout) self.assertEqual(len(yout), len(xout) - 1) self.assertIsNone(yout[0]) self.assertEqual(yout[1], 1) self.assertEqual(yout[2], 2)
[docs] def test_resampleStepwiseSumAllNones(self): """Test resampleStepwise() summing when the inputs are all None.""" xin = [0, 1, 2, 13.3] yin = [None, None, None] xout = [0, 1, 2, 13.3] yout = resampleStepwise(xin, yin, xout, avg=False) self.assertEqual(len(yout), len(xout) - 1) self.assertIsNone(yout[0]) self.assertIsNone(yout[1]) self.assertIsNone(yout[2])
[docs] def test_resampleStepwiseSumOneNone(self): """Test resampleStepwise() summing when one inputs is None.""" xin = [0, 1, 2, 13.3] yin = [None, 1, 2] xout = [0, 1, 2, 13.3] yout = resampleStepwise(xin, yin, xout, avg=False) self.assertEqual(len(yout), len(xout) - 1) self.assertIsNone(yout[0]) self.assertEqual(yout[1], 1) self.assertEqual(yout[2], 2)
[docs] def test_resampleStepwiseAvgComplicatedNone(self): """Test resampleStepwise() averaging with a None value, when the intervals don't line up.""" xin = [2, 4, 6, 8, 10] yin = [11, None, 33, 44] xout = [-1, 0, 1, 2, 4, 7, 9] yout = resampleStepwise(xin, yin, xout) self.assertEqual(len(yout), len(xout) - 1) self.assertEqual(yout[0], 0) self.assertEqual(yout[1], 0) self.assertEqual(yout[2], 0) self.assertEqual(yout[3], 11) self.assertIsNone(yout[4]) self.assertEqual(yout[5], 38.5)
[docs] def test_resampleStepwiseAvgNpArray(self): """Test resampleStepwise() averaging when some of the values are arrays.""" xin = [0, 1, 2, 3, 4] yin = [11, np.array([1, 1]), np.array([2, 2]), 44] xout = [2, 4, 5, 6, 7] yout = resampleStepwise(xin, yin, xout, avg=True) self.assertEqual(len(yout), len(xout) - 1) self.assertTrue(isinstance(yout[0], type(yin[1]))) self.assertEqual(yout[0][0], 23.0) self.assertEqual(yout[0][1], 23.0) self.assertEqual(yout[1], 0) self.assertEqual(yout[2], 0) self.assertEqual(yout[3], 0)
[docs] def test_resampleStepwiseAvgNpArrayAverage(self): """Test resampleStepwise() summing when some of the values are arrays.""" xin = [0, 1, 2, 3, 4] yin = [11, np.array([1, 1]), np.array([2, 2]), 44] xout = [2, 4, 5, 6, 7] yout = resampleStepwise(xin, yin, xout, avg=False) self.assertEqual(len(yout), len(xout) - 1) self.assertTrue(isinstance(yout[0], type(yin[1]))) self.assertEqual(yout[0][0], 46.0) self.assertEqual(yout[0][1], 46.0) self.assertEqual(yout[1], 0) self.assertEqual(yout[2], 0) self.assertEqual(yout[3], 0)
[docs] def test_rotateXY(self): x = [1.0, -1.0] y = [1.0, 1.0] # test operation on scalar xr, yr = rotateXY(x[0], y[0], 45.0) self.assertAlmostEqual(xr, 0.0) self.assertAlmostEqual(yr, sqrt(2)) xr, yr = rotateXY(x[1], y[1], 45.0) self.assertAlmostEqual(xr, -sqrt(2)) self.assertAlmostEqual(yr, 0.0) # test operation on list xr, yr = rotateXY(x, y, 45.0) self.assertAlmostEqual(xr[0], 0.0) self.assertAlmostEqual(yr[0], sqrt(2)) self.assertAlmostEqual(xr[1], -sqrt(2)) self.assertAlmostEqual(yr[1], 0.0)