Skip to content

Commit

Permalink
Test the full state instead of the final state
Browse files Browse the repository at this point in the history
  • Loading branch information
David Contreras committed May 29, 2023
1 parent b4cac47 commit ca78866
Showing 1 changed file with 33 additions and 30 deletions.
63 changes: 33 additions & 30 deletions test/unit-tests/function/numeric/solveODE.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,30 @@ const smaller = math.smaller
const smallerEq = math.smallerEq
const largerEq = math.largerEq
const multiply = math.multiply
const dotMultiply = math.dotMultiply
const divide = math.divide
const diff = math.diff
const unit = math.unit
const map = math.map
const transpose = math.transpose

function withinTolerance (A, B, tol) {
const maxAbsError = abs(subtract(A, B))
const maxAbsError = max(abs(subtract(A, B)))
return smaller(maxAbsError, tol)
}

describe('solveODE', function () {
function f (t, y) { return y }
function exactSol (T, y0) { return dotMultiply(y0, map(transpose([T]), exp)) } // this is only valid for y' = y
const tspan = [0, 4]
const y0 = [1, 2]
const exactSol = multiply(y0, exp(tspan[1])) // this is only valid for y' = y

it('should throw an error if the first argument is not a function', function () {
assert.throws(function () {
const sol = solveODE('notAFunction', tspan, y0)
assert.deepStrictEqual(
withinTolerance(sol.y[sol.y.length - 1], exactSol, tol),
[true, true]
withinTolerance(sol.y, exactSol(sol.t, y0), tol),
true
)
}, /TypeError: Unexpected type of argument in function solveODE \(expected: function.*/)
})
Expand All @@ -42,8 +45,8 @@ describe('solveODE', function () {
assert.throws(function () {
const sol = solveODE(f, 'NotAnArrayLike', y0)
assert.deepStrictEqual(
withinTolerance(sol.y[sol.y.length - 1], exactSol, tol),
[true, true]
withinTolerance(sol.y, exactSol(sol.t, y0), tol),
true
)
}, /TypeError: Unexpected type of argument in function solveODE \(expected: Array or Matrix,.*/)
})
Expand All @@ -53,8 +56,8 @@ describe('solveODE', function () {
const wrongTSpan = [tspan[0]]
const sol = solveODE(f, wrongTSpan, y0)
assert.deepStrictEqual(
withinTolerance(sol.y[sol.y.length - 1], exactSol, tol),
[true, true]
withinTolerance(sol.y, exactSol(sol.t, y0), tol),
true
)
}, /TypeError: Unexpected type of argument in function.*/)
})
Expand All @@ -64,49 +67,50 @@ describe('solveODE', function () {
const method = 'wrongMethodName'
const sol = solveODE(f, tspan, y0, { method })
assert.deepStrictEqual(
withinTolerance(sol.y[sol.y.length - 1], exactSol, tol),
[true, true]
withinTolerance(sol.y, exactSol(sol.t, y0), tol),
true
)
}, /TypeError: .* is not a function/)
})

it('should solve close to the analytical solution', function () {
const sol = solveODE(f, tspan, y0)
assert.deepStrictEqual(
withinTolerance(sol.y[sol.y.length - 1], exactSol, tol),
[true, true]
withinTolerance(sol.y, exactSol(sol.t, y0), tol),
true
)
})

it('should solve backwards', function () {
const sol = solveODE(f, [tspan[1], tspan[0]], exactSol)
const exactSolEnd = exactSol([4], y0)[0]
const sol = solveODE(f, [tspan[1], tspan[0]], exactSolEnd)
assert.deepStrictEqual(
withinTolerance(sol.y[sol.y.length - 1], y0, tol),
[true, true]
withinTolerance(sol.y, exactSol(sol.t, sol.y[sol.y.length - 1]), tol),
true
)
})

it('should solve if the arguments are matrices', function () {
const sol = solveODE(f, matrix(tspan), matrix(y0))
assert.deepStrictEqual(
withinTolerance(sol.y[sol.y.length - 1], exactSol, tol),
[true, true]
withinTolerance(sol.y, exactSol(sol.t, y0), tol),
true
)
})

it('should solve if with options even if they are empty', function () {
const options = {}
const sol = solveODE(f, matrix(tspan), matrix(y0), options)
assert.deepStrictEqual(
withinTolerance(sol.y[sol.y.length - 1], exactSol, tol),
[true, true]
withinTolerance(sol.y, exactSol(sol.t, y0), tol),
true
)
})

it('should solve when y0 is a scalar', function () {
const sol = solveODE(f, tspan, y0[0])
assert.deepStrictEqual(
withinTolerance(sol.y[sol.y.length - 1], exactSol[0], tol),
withinTolerance(sol.y, exactSol(sol.t, [y0[0]]).map(x => x[0]), 2 * tol),
true
)
})
Expand All @@ -116,41 +120,40 @@ describe('solveODE', function () {
function fWithUnits (t, y) { return divide(y, seconds) }
const tspanWithUnits = multiply(tspan, seconds)
const sol = solveODE(fWithUnits, tspanWithUnits, y0)

assert.deepStrictEqual(
withinTolerance(sol.y[sol.y.length - 1], exactSol, tol),
[true, true]
withinTolerance(sol.y, exactSol(divide(sol.t, seconds), y0), tol),
true
)
})

it('should solve close to the analytical solution with RK23 method', function () {
const sol = solveODE(f, tspan, y0, { method: 'RK23' })
assert.deepStrictEqual(
withinTolerance(sol.y[sol.y.length - 1], exactSol, tol),
[true, true]
withinTolerance(sol.y, exactSol(sol.t, y0), tol),
true
)
})

it('should solve close to the analytical solution with RK45 method', function () {
const sol = solveODE(f, tspan, y0, { method: 'RK45' })
assert.deepStrictEqual(
withinTolerance(sol.y[sol.y.length - 1], exactSol, tol),
[true, true]
withinTolerance(sol.y, exactSol(sol.t, y0), tol),
true
)
})

it('should solve with method name in lower case', function () {
const sol = solveODE(f, tspan, y0, { method: 'rk45' })
assert.deepStrictEqual(
withinTolerance(sol.y[sol.y.length - 1], exactSol, tol),
[true, true]
withinTolerance(sol.y, exactSol(sol.t, y0), tol),
true
)
})

it('should solve with less steps if a higher tolerance is specified', function () {
const sol = solveODE(f, tspan, y0, { method: 'RK45', tol: 1e-2 })
assert.deepStrictEqual(
smaller(sol.y.length - 1, 6),
smallerEq(sol.y.length, 6),
true
)
})
Expand Down

0 comments on commit ca78866

Please sign in to comment.