Files
tensor/integrate/budget_pins_test.go
T

76 lines
2.6 KiB
Go
Raw Normal View History

2026-09-03 10:00:00 +02:00
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: MIT
package integrate
import (
"math"
"strings"
"testing"
"sourcedock.dev/petrbalvin/tensor/internal/core"
)
// Regression pins: budgets that did not bound what they
// promised, and non-finite states that integrated to no error.
// TestIntegrateNDDimensionBudget: in 10 dimensions the root box alone
// costs 5^10 + 3^10 evaluations, about five times the default budget,
// before the first budget check could fire.
func TestIntegrateNDDimensionBudget(t *testing.T) {
lower := make([]float64, 10)
upper := make([]float64, 10)
for i := range upper {
upper[i] = 1
}
f := func(x []float64) float64 { return 1 }
_, err := IntegrateND(f, lower, upper, CubatureOptions{})
if err == nil || !strings.Contains(err.Error(), "budget") {
t.Fatalf("IntegrateND in 10 dimensions under the default budget: err = %v", err)
}
}
// TestPDEStepCountBound: a dt far below tFinal/1e12 wrapped the step
// count conversion, and the silently larger step ran past the wave
// equation's CFL check.
func TestPDEStepCountBound(t *testing.T) {
u0, err := core.FromFloats([]float64{0, 1, 0, 1, 0}, 5)
if err != nil {
t.Fatal(err)
}
if _, err := IntegrateHeat1D(u0, 1, 0.1, 1, 1e-300, 2, 0, 0); err == nil || !strings.Contains(err.Error(), "1e12") {
t.Fatalf("Heat1D with an unhonourable dt: err = %v", err)
}
u2, err := core.FromFloats([]float64{1, 2, 3, 4, 5, 6, 7, 8, 9}, 3, 3)
if err != nil {
t.Fatal(err)
}
if _, err := IntegrateHeat2D(u2, 1, 0.1, 0.1, 1, 1e-300, 2, 0, 0, 0, 0); err == nil || !strings.Contains(err.Error(), "1e12") {
t.Fatalf("Heat2D with an unhonourable dt: err = %v", err)
}
}
// TestPDEVerletRejectNonFinite: a NaN or Inf initial state flowed
// through the stencils and published an all-NaN history with no error.
func TestPDEVerletRejectNonFinite(t *testing.T) {
bad, err := core.FromFloats([]float64{1, math.NaN(), 0, 1, 0}, 5)
if err != nil {
t.Fatal(err)
}
if _, err := IntegrateHeat1D(bad, 1, 0.1, 1, 0.1, 2, 0, 0); err == nil || !strings.Contains(err.Error(), "non-finite") {
t.Fatalf("Heat1D on a NaN state: err = %v", err)
}
q, err := core.FromFloats([]float64{1, math.Inf(1)}, 2)
if err != nil {
t.Fatal(err)
}
p, err := core.FromFloats([]float64{0, 0}, 2)
if err != nil {
t.Fatal(err)
}
accel := func(x *core.Array) (*core.Array, error) { return core.Copy(x), nil }
if _, _, err := IntegrateVerlet(accel, 0, 1, q, p, 2); err == nil || !strings.Contains(err.Error(), "non-finite") {
t.Fatalf("Verlet on an Inf state: err = %v", err)
}
}