diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7846ee7..c0eca82 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -36,7 +36,7 @@ set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fPIC")
MESSAGE("Found compiler: ${CMAKE_Fortran_COMPILER_ID}")
if ("${CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU")
set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -cpp -ffree-line-length-none")
- set (CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS} -g -O -Wuninitialized -fbounds-check -finit-local-zero")
+ set (CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS} -g -O -Wuninitialized -fbounds-check -finit-local-zero -Wall")
set (CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS} -O3")
elseif("${CMAKE_Fortran_COMPILER_ID}" MATCHES "Intel")
set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fpp")
diff --git a/build.sh b/build.sh
index dead067..c7f7cca 100755
--- a/build.sh
+++ b/build.sh
@@ -1,10 +1,20 @@
#!/bin/bash
#
# Define how to build the libraries and executables:
-BUILD_TYPE=Debug
+if [[ -z "${BUILD_TYPE}" ]]; then
+ BUILD_TYPE="Debug"
+fi
+echo "Using BUILD_TYPE = $BUILD_TYPE"
+
+if [[ -z "${ENABLE_PFUNIT}" ]]; then
+ ENABLE_PFUNIT=ON
+fi
+echo "Using ENABLE_PFUNIT = $ENABLE_PFUNIT"
+
Fortran_COMPILER=gfortran
LIBSUFFIX="so"
GENERATOR_FLAGS=""
+
if [[ "$OSTYPE" == "linux-gnu" ]]; then
LIBSUFFIX="so"
elif [[ "$OSTYPE" == "darwin"* ]]; then
@@ -23,24 +33,28 @@ git submodule update --init --recursive
# Build pFUnit #
# #
################################################################################
-cd pFUnit || exit || exit
-# Create the build directory if it does not exist
-if [[ ! -d "build" ]]; then
- mkdir build
+if [[ "$ENABLE_PFUNIT" == "ON" ]]; then
+ cd pFUnit || exit
+ # Create the build directory if it does not exist
+ if [[ ! -d "build" ]]; then
+ mkdir build
+ else
+ rm -rf build/*
+ fi
+ cd build || exit
+ echo "Updating cmake"
+ export PFUNIT_DIR=..//pFUnit/build/installed
+ export FC=$Fortran_COMPILER
+ cmake -DSKIP_MPI=yes "$GENERATOR_FLAGS" ../
+ echo "Building pFUnit"
+ cmake --build .
+ cmake --install .
+ cd ../ || exit
+ echo "Leaving pFUnit"
+ cd ../ || exit
else
- rm -rf build/*
+ echo "ENABLE_PFUNIT is 'OFF'. Skipping. Set to 'ON' to add it."
fi
-cd build || exit || exit
-echo "Updating cmake"
-export PFUNIT_DIR=..//pFUnit/build/installed
-export FC=$Fortran_COMPILER
-cmake -DSKIP_MPI=yes "$GENERATOR_FLAGS" ../
-echo "Building pFUnit"
-cmake --build .
-cmake --install .
-cd ../ || exit || exit
-echo "Leaving pFUnit"
-cd ../ || exit || exit
################################################################################
# #
# Build libslam #
@@ -52,10 +66,10 @@ if [[ ! -d "build" ]]; then
else
rm -rf build/*
fi
-cd build || exit || exit
+cd build || exit
echo "Executing cmake"
-cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_Fortran_COMPILER=$Fortran_COMPILER -DENABLE_OpenMP_SUPPORT=ON -DENABLE_POSTGRESQL_SUPPORT=ON -DENABLE_PFUNIT=ON "$GENERATOR_FLAGS" ../
+cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_Fortran_COMPILER=$Fortran_COMPILER -DENABLE_OpenMP_SUPPORT=ON -DENABLE_POSTGRESQL_SUPPORT=ON -DENABLE_PFUNIT="$ENABLE_PFUNIT" "$GENERATOR_FLAGS" ../
echo "Building libslam"
cmake --build .
cmake --install .
@@ -64,8 +78,8 @@ if [[ $? -ne 0 ]]; then
exit $?
fi
echo "Manually preparing 'lib' and 'include' directories"
-cd ../ || exit || exit
-ln -sf build/include include || exit || exit
-ln -sf build/lib lib || exit || exit
+cd ../ || exit
+ln -sf build/include include || exit
+ln -sf build/lib lib || exit
echo "Leaving libslam"
-echo "Done"
\ No newline at end of file
+echo "Done with $BUILD_TYPE build"
\ No newline at end of file
diff --git a/pFUnittests/CMakeLists.txt b/pFUnittests/CMakeLists.txt
index 1c43dda..c69121d 100644
--- a/pFUnittests/CMakeLists.txt
+++ b/pFUnittests/CMakeLists.txt
@@ -2,24 +2,33 @@
include_directories(${CMAKE_Fortran_MODULE_DIRECTORY})
message("pfunit: ${CMAKE_Fortran_MODULE_DIRECTORY}")
#Build the executables for testing
-add_pfunit_ctest (slamtime_tests
+add_pfunit_ctest (slam_time_test
TEST_SOURCES test_slamtime.pf
LINK_LIBRARIES slam-Fortran)
-
-
-add_pfunit_ctest (slamreduction_tests
+add_pfunit_ctest (slam_reduction_test
TEST_SOURCES test_slamreduction.pf
LINK_LIBRARIES slam-Fortran)
-add_pfunit_ctest (slamlinAlgebra_tests
+add_pfunit_ctest (slam_linAlgebra_test
TEST_SOURCES test_slamlinAlgebra.pf
LINK_LIBRARIES slam-Fortran)
-add_pfunit_ctest (slammath_tests
+add_pfunit_ctest (slam_math_test
TEST_SOURCES test_slammath.pf
LINK_LIBRARIES slam-Fortran)
-add_pfunit_ctest (slamastroconv_tests
+add_pfunit_ctest (slam_astro_conversions_test
TEST_SOURCES test_slamastroconv.pf
LINK_LIBRARIES slam-Fortran)
+
+add_pfunit_ctest (slam_interpolation_test
+TEST_SOURCES test_slamInterpolation.pf
+LINK_LIBRARIES slam-Fortran)
+
+add_pfunit_ctest (slam_randomNumber_test
+TEST_SOURCES test_slamrandomNumber.pf
+LINK_LIBRARIES slam-Fortran)
+add_pfunit_ctest (slam_strings_test
+TEST_SOURCES test_slamstrings.pf
+LINK_LIBRARIES slam-Fortran)
diff --git a/pFUnittests/test_slamInterpolation.pf b/pFUnittests/test_slamInterpolation.pf
new file mode 100644
index 0000000..10718cb
--- /dev/null
+++ b/pFUnittests/test_slamInterpolation.pf
@@ -0,0 +1,1214 @@
+!==============================================================================
+!
+!> @anchor test_slamInterpolation
+!!
+!> @brief Program for testing slam_interpolation
+!!
+!> @author Alex Bush (AB)
+!!
+!> @date
+!! - 21.07.2025 (initial design for cheby test)
+!!
+!!
+!! @details Program for testing Chebyshev polynomial coefficient generation
+!! Reference values : Mathematical definition + simulated ephemerides + public ephemerides
+!------------------------------------------------------------------------
+module test_slamInterpolation
+ use funit
+ use slam_interpolation
+ use iso_fortran_env
+ use slam_error_handling
+ use slam_types
+ use slam_math, only: pi
+
+ implicit none
+
+ contains
+ !=========================================================================
+ !
+ !> @anchor compute_average_error
+ !!
+ !> @brief Determines the average error between inputted ephemeris and interpolated value from Chebyshev polynomials
+ !> @author Alex Bush
+ !!
+ !> @date
+ !! - 21.07.2025 (Added function to test_slamInterpolation)
+ !!
+ !!
+ !> @param[in] ephemerides_state_components A matrix of state components to be converted to chebys
+ !> @param[in] ephemerides_epochs The respective epochs of each state vector component index
+ !> @param[in] test_chebys Matrix of chebys for reconstruction. One for each state vector component
+ !> @param[in] nephem Number of ephemerides
+ !> @param[in] degree Chebyshev degree
+ !> @param[out] avg_error: Average error per state vector component, index 7 is average of Euclidian distance
+ !!
+ !----------------------------------------------------------------------
+ subroutine compute_average_error(ephemerides_state_components, ephemerides_epochs, test_chebys, nephem, degree, avg_error)
+
+ implicit none
+
+ real(dp), intent(in), dimension(nephem, 6) :: ephemerides_state_components ! input ephemerides matrix
+ real(dp), intent(in), dimension(nephem) :: ephemerides_epochs !input ephemerides epochs
+ real(dp), intent(in), dimension(degree, 6) :: test_chebys ! chebys to be used for ephemeris reconstruction
+ integer, intent(in) :: nephem, degree ! input parameters of number of ephemerides and chebyshev degree
+ real(dp), intent(out), dimension(7) :: avg_error ! average error to be computed and output
+
+ real(dp), dimension(nephem, 6) :: reconstructed_ephemerides ! ephemerides reconstructed from chebys
+ real(dp), dimension(nephem, 7) :: error_array ! array to store difference between reconstructed values and original values
+ real(dp) :: start_epoch, end_epoch, epoch_span ! working values for time normalization
+ real(dp) :: state_component, epoch, poly ! working values for state vector component reconstruction
+ real(dp), dimension(degree) :: cheby_values ! Value of chebyshev polynomial coefficients for given state vector component
+ integer :: i, j, k ! iteration integers
+
+ ! Method is largely copied from slam_interpolation.
+ ! Normalization of ephemerides_epochs to span -1,1
+ ! First determine starting and ending epoch
+ start_epoch = ephemerides_epochs(1)
+ end_epoch = ephemerides_epochs(nephem)
+ ! Then determine span
+ epoch_span = end_epoch - start_epoch
+ do i = 1, 6
+ do j = 1, nephem
+ ! Extract state component and epoch for value to be tested
+ state_component = ephemerides_state_components(j,i)
+ epoch = ephemerides_epochs(j)
+ ! normalise epoch to sit between -1,1
+ epoch = epoch - start_epoch
+ epoch = epoch / epoch_span
+ epoch = epoch * 2
+ epoch = epoch - 1
+ ! interpolate cheby polynomial values for the epoch
+ ! ultilising get_chebychev_polynomimal
+ call get_chebyshev_polynomials(degree, epoch, cheby_values)
+ ! sum values of chebyshev polynomials, multiplying by coefficient
+ poly = 0.0
+ do k = 1, degree
+ poly = poly + (cheby_values(k) * test_chebys(k,i))
+ end do
+ ! store interpolated value
+ reconstructed_ephemerides(j,i) = poly
+ end do
+ end do
+ ! For all ephmerides, find error
+ do i = 1, 6
+ do j = 1, nephem
+ error_array(j,i) = ephemerides_state_components(j,i) - reconstructed_ephemerides(j,i)
+ end do
+ end do
+ ! For all ephemerides positions (x,y,z) determine absolute error
+ do j = 1, nephem
+ error_array(j,7) = sqrt((ephemerides_state_components(j,1) - reconstructed_ephemerides(j,1)) ** 2 + &
+ (ephemerides_state_components(j,2) - reconstructed_ephemerides(j,2)) ** 2 + &
+ (ephemerides_state_components(j,3) - reconstructed_ephemerides(j,3)) ** 2)
+ end do
+ ! Initialise error matrix
+ avg_error = (/0.0,0.0,0.0,0.0,0.0,0.0,0.0/)
+ ! For all values of a specified state vector component, determine avg error
+ avg_error(:) = sum(error_array, dim=1)/nephem
+ end subroutine compute_average_error
+
+ !=========================================================================
+ !
+ !> @anchor compute_chebys_and_error
+ !!
+ !> @brief Creates Chebyshev polynomials for input state vector components prior to error computation
+ !> @author Alex Bush
+ !!
+ !> @date
+ !! - 21.07.2025 (Added function to test_slamInterpolation)
+ !!
+ !!
+ !> @param[in] t_vals epochs of ephemerides
+ !> @param[in] x_vals x value of ephemerides
+ !> @param[in] y_vals y value of ephemerides
+ !> @param[in] z_vals z value of ephemerides
+ !> @param[in] vx_vals vx value of ephemerides
+ !> @param[in] vy_vals vy value of ephemerides
+ !> @param[in] vz_vals vz value of ephemerides
+ !> @param[in] test_chebys Matirx of chebys for reconstruction. One for each state vector component
+ !> @param[in] degree Chebyshev degree
+ !> @param[in] nephem Number of ephemerides
+ !> @param[in] n_lag Lagrange Degree
+ !> @param[out] avg_error: Averge error per state vector component, index 7 is average of euclidian distance
+ !!
+ !----------------------------------------------------------------------
+ subroutine compute_chebys_and_error(degree, nephem, n_lag, t_vals, x_vals, y_vals, z_vals,&
+ vx_vals, vy_vals, vz_vals, avg_error)
+
+ integer, intent(in) :: degree ! Chebyshev polynomial degree
+ integer, intent(in) :: n_lag ! Lagrange interpolation degree
+ integer, intent(in) :: nephem ! Number of ephemerides points
+ real(dp), intent(in), dimension(nephem) :: t_vals, x_vals, y_vals, z_vals, vx_vals, vy_vals, vz_vals ! Input values for ephemeris state components
+ real(dp), intent(out), dimension(7) :: avg_error ! output, average error between interpolated value and input value of ephemerides
+
+ real(dp), dimension(nephem, 6) :: ephemerides_state_components ! matrix for ephemerides
+ real(dp), dimension(nephem) :: ephemerides_epochs ! epoch values for ephemerides
+ real(dp), dimension(degree, 6) :: chebys ! chebyshevs to be calculated
+ real(dp), dimension(nephem, 2) :: ephem ! ephem to be passed to chebyshev interpolation
+ real(dp), dimension(degree) :: coeff ! chebyshev coefficients output from chebyshev interpolation
+ integer :: i, j ! iteration integers
+
+ ! repack input values into ephemerides state components and epochs
+ ephemerides_epochs = t_vals
+ do j = 1, nephem
+ ephemerides_state_components(j,1) = x_vals(j)
+ ephemerides_state_components(j,2) = y_vals(j)
+ ephemerides_state_components(j,3) = z_vals(j)
+ ephemerides_state_components(j,4) = vx_vals(j)
+ ephemerides_state_components(j,5) = vy_vals(j)
+ ephemerides_state_components(j,6) = vz_vals(j)
+ end do
+ ! generation of chebys for each ephemeris state vector component
+ do i = 1, 6
+ ! reformat the ephemerides epoch and state component into input for chebyshev interpolation
+ ephem = reshape((/ephemerides_epochs, ephemerides_state_components(:,i)/), (/nephem, 2/))
+ call chebyshev_interpolation(degree, n_lag, nephem, ephem, coeff)
+ ! write output to local array
+ do j = 1, degree
+ chebys(j,i) = coeff(j)
+ end do
+ end do
+ ! call subroutine to compute average error from chebyshev interpolation
+ call compute_average_error(ephemerides_state_components, ephemerides_epochs, chebys, nephem, degree, avg_error)
+ end subroutine compute_chebys_and_error
+
+ @test
+ subroutine test_cheby_generation()
+
+ implicit none
+
+ ! Tests the slam_interpolation/chebyshev_generation subroutine
+ ! Uses Chebyshev polynomials as inputs to check validity
+ ! Reference Data : mathematical definition of chebyshev nodes
+
+ integer :: degree, n_lag, nephem
+ integer :: i
+ real(dp), dimension(72) :: y_unit_zero, y_unit_one, t_unit, y_unit_n_minus_1, y_unit_n, y_unit_n_plus_1
+ real(dp), dimension(72, 2) :: ephem
+ real(dp), dimension(36) :: coeff, expected_zeros, expected
+
+ ! Initialize standard parameters
+ degree = 36
+ nephem = 72
+ n_lag = 5
+
+ ! Unit testing individual chebyshev polynomial encoding.
+ ! Initialize values for t, and y for chebyshev polynomials of order 0 and 1.
+ ! time, -1 to 1 inclusive, 72 steps
+ t_unit = (/-1.0,-0.971830985915493,-0.9436619718309859,-0.9154929577464789,&
+ -0.8873239436619719,-0.8591549295774648,-0.8309859154929577,-0.8028169014084507,&
+ -0.7746478873239436,-0.7464788732394366,-0.7183098591549295,-0.6901408450704225,&
+ -0.6619718309859155,-0.6338028169014085,-0.6056338028169014,-0.5774647887323944,&
+ -0.5492957746478873,-0.5211267605633803,-0.49295774647887325,-0.46478873239436613,&
+ -0.43661971830985913,-0.4084507042253521,-0.380281690140845,-0.352112676056338,&
+ -0.323943661971831,-0.2957746478873239,-0.2676056338028169,-0.23943661971830987,&
+ -0.21126760563380276,-0.18309859154929575,-0.15492957746478875,-0.12676056338028163,&
+ -0.09859154929577463,-0.07042253521126762,-0.04225352112676051,-0.014084507042253502,&
+ 0.014084507042253502,0.04225352112676051,0.07042253521126773,0.09859154929577474,&
+ 0.12676056338028174,0.15492957746478875,0.18309859154929575,0.21126760563380276,&
+ 0.23943661971830998,0.267605633802817,0.295774647887324,0.323943661971831,&
+ 0.352112676056338,0.380281690140845,0.40845070422535223,0.43661971830985924,&
+ 0.46478873239436624,0.49295774647887325,0.5211267605633803,0.5492957746478873,&
+ 0.5774647887323945,0.6056338028169015,0.6338028169014085,0.6619718309859155,&
+ 0.6901408450704225,0.7183098591549295,0.7464788732394367,0.7746478873239437,&
+ 0.8028169014084507,0.8309859154929577,0.8591549295774648,0.887323943661972,&
+ 0.915492957746479,0.943661971830986,0.971830985915493,1.0/)
+ ! 0th order chebyshev polynomial y values. y = 1
+ y_unit_zero = (/1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0,&
+ 1.0,1.0,1.0,1.0/)
+ ! 1st order chebyshev polynomial y values. y = t
+ y_unit_one = (/-1.0,-0.971830985915493,-0.9436619718309859,-0.9154929577464789,&
+ -0.8873239436619719,-0.8591549295774648,-0.8309859154929577,-0.8028169014084507,&
+ -0.7746478873239436,-0.7464788732394366,-0.7183098591549295,-0.6901408450704225,&
+ -0.6619718309859155,-0.6338028169014085,-0.6056338028169014,-0.5774647887323944,&
+ -0.5492957746478873,-0.5211267605633803,-0.49295774647887325,-0.46478873239436613,&
+ -0.43661971830985913,-0.4084507042253521,-0.380281690140845,-0.352112676056338,&
+ -0.323943661971831,-0.2957746478873239,-0.2676056338028169,-0.23943661971830987,&
+ -0.21126760563380276,-0.18309859154929575,-0.15492957746478875,-0.12676056338028163,&
+ -0.09859154929577463,-0.07042253521126762,-0.04225352112676051,-0.014084507042253502,&
+ 0.014084507042253502,0.04225352112676051,0.07042253521126773,0.09859154929577474,&
+ 0.12676056338028174,0.15492957746478875,0.18309859154929575,0.21126760563380276,&
+ 0.23943661971830998,0.267605633802817,0.295774647887324,0.323943661971831,&
+ 0.352112676056338,0.380281690140845,0.40845070422535223,0.43661971830985924,&
+ 0.46478873239436624,0.49295774647887325,0.5211267605633803,0.5492957746478873,&
+ 0.5774647887323945,0.6056338028169015,0.6338028169014085,0.6619718309859155,&
+ 0.6901408450704225,0.7183098591549295,0.7464788732394367,0.7746478873239437,&
+ 0.8028169014084507,0.8309859154929577,0.8591549295774648,0.887323943661972,&
+ 0.915492957746479,0.943661971830986,0.971830985915493,1.0/)
+ ! Initialize an array of 0s, to be changed to include 1.0 for respective polynomial degree
+ ! e.g. when checking 4th order polynomial, index 4 to be replaced with 1.0.
+ expected_zeros = (/0.0,0.0,0.0,0.0,&
+ 0.0,0.0,0.0,0.0,&
+ 0.0,0.0,0.0,0.0,&
+ 0.0,0.0,0.0,0.0,&
+ 0.0,0.0,0.0,0.0,&
+ 0.0,0.0,0.0,0.0,&
+ 0.0,0.0,0.0,0.0,&
+ 0.0,0.0,0.0,0.0,&
+ 0.0,0.0,0.0,0.0/)
+ ! TESTING first 8 coefficients one at a time utilizing recurrence relation.
+ ! First 2 must be checked manually, prior to recurrence relation.
+ ephem = reshape((/t_unit, y_unit_zero/), (/nephem, 2/))
+ ! Call the chebyshev_interpolation subroutine
+ call chebyshev_interpolation(degree, n_lag, nephem, ephem, coeff)
+ ! Initisalize expected array, initially full of zeros
+ expected = expected_zeros
+ ! Replace Order's index with 1.0
+ expected(1) = 1.0
+ ! Check if the computed polynomial coefficients are equal to expected value
+ !(all zeros apart from coefficient 0)
+ @assertEqual(expected, coeff, tolerance = 0.00001)
+ ! Coefficient 1, y = x
+ ! time is between -1 and 1
+ ephem = reshape((/t_unit, y_unit_one/), (/nephem, 2/))
+ ! Call the chebyshev_interpolation subroutine
+ call chebyshev_interpolation(degree, n_lag, nephem, ephem, coeff)
+ expected = expected_zeros
+ expected(2) = 1.0
+ ! Check if the computed polynomial coefficients are equal to expected value
+ ! (all zeros, apart from coefficient 1)
+ @assertEqual(expected, coeff, tolerance = 0.00001)
+ ! Assigning the first two polynomials as n-1 and n respectively
+ ! In preparation for the recursive generation of higher orders
+ y_unit_n_minus_1 = y_unit_zero
+ y_unit_n = y_unit_one
+ ! Begin recurrence relation to calculate order n+1 from n and n-1.
+ do i = 3, 9
+ ! Calculate the n+1 polynomial using the recurrence relation
+ y_unit_n_plus_1 = (2 * y_unit_one)
+ y_unit_n_plus_1 = y_unit_n_plus_1 * y_unit_n
+ y_unit_n_plus_1 = y_unit_n_plus_1 - y_unit_n_minus_1
+ ! Sets ephem to n+1 polynomial, and runs chebyshev interpolation to generate coefficients
+ ephem = reshape((/t_unit, y_unit_n_plus_1/), (/nephem, 2/))
+ call chebyshev_interpolation(degree, n_lag, nephem, ephem, coeff)
+ ! Reset the expected value matrix to zeros, and update index of polynomial to be matched
+ expected = expected_zeros
+ expected(i) = 1.0
+ ! Tests error
+ @assertEqual(expected, coeff, tolerance = 0.00001)
+ ! Assign n polynomial to become new n-1
+ y_unit_n_minus_1 = y_unit_n
+ ! Assign n+1 polynomial to become new n
+ y_unit_n = y_unit_n_plus_1
+ ! repeat the recurrence relation
+ end do
+ ! Test is ended after order 8 due to only having 72 input values per polynomial.
+ end subroutine test_cheby_generation
+
+ !=========================================================================
+ !
+ !> @anchor test_simulated_GEO_cheby_generation
+ !!
+ !> @brief Tests the average error from chebyshev generation and interpolation for simulated GEO
+ !> @author Alex Bush
+ !!
+ !> @date
+ !! - 21.07.2025 (Added function to test_slamInterpolation)
+ !!
+ !!
+ !----------------------------------------------------------------------
+ @test
+ subroutine test_simulated_GEO_cheby_generation()
+
+ implicit none
+ ! Tests the slam_interpolation/chebyshev_generation subroutine
+ ! Uses Known trajectories and chebys to test generation
+ ! Compares generation against original values to calculate error
+
+ ! Reference Data : simulated ephemerides
+ integer :: degree, n_lag, nephem
+ real(dp), dimension(50) :: t_vals, x_vals, y_vals, z_vals, vx_vals, vy_vals, vz_vals
+ real(dp), dimension(7) :: avg_error
+ ! initialization of test data
+ degree = 36
+ nephem = 50
+ n_lag = 5
+ ! initialise ephemeris data 1 orbit of GEO orbit
+
+ t_vals = (/0.000000,1706.038697,3412.077394,5118.116091,6824.154788,&
+ 8530.193485,10236.232181,11942.270878,13648.309575,15354.348272,&
+ 17060.386969,18766.425666,20472.464363,22178.503060,23884.541757,&
+ 25590.580454,27296.619150,29002.657847,30708.696544,32414.735241,&
+ 34120.773938,35826.812635,37532.851332,39238.890029,40944.928726,&
+ 42650.967423,44357.006119,46063.044816,47769.083513,49475.122210,&
+ 51181.160907,52887.199604,54593.238301,56299.276998,58005.315695,&
+ 59711.354392,61417.393088,63123.431785,64829.470482,66535.509179,&
+ 68241.547876,69947.586573,71653.625270,73359.663967,75065.702664,&
+ 76771.741361,78477.780057,80183.818754,81889.857451,83595.896148/)
+
+ x_vals = (/42164.000000,41838.131998,40865.564987,39261.332098,37050.230228,&
+ 34266.436749,30952.981222,27161.080284,22949.345981,18382.879798,&
+ 13532.266364,8472.482424,3281.737906,-1959.732985,-7170.911955,&
+ -12271.248938,-17181.907173,-21826.981793,-26134.673103,-30038.396396,&
+ -33477.811169,-36399.753811,-38759.059367,-40519.259655,-41653.146965,&
+ -42143.194611,-41981.827845,-41171.540939,-39724.858635,-37664.142542,&
+ -35021.245494,-31837.019193,-28160.682758,-24049.061936,-19565.710739,&
+ -14779.929077,-9765.691577,-4600.504148,635.794044,5862.264661,&
+ 10998.121271,15963.978081,20683.077009,25082.474155,29094.167299,&
+ 32656.147030,35713.355231,38218.536123,40132.966706,41427.055305/)
+
+ y_vals = (/0.000000,5231.979258,10383.086936,15373.701502,20126.682191,&
+ 24568.561385,28630.680213,32250.249826,35371.321929,37945.653590,&
+ 39933.452932,41303.994208,42036.092734,42118.432338,41549.740285,&
+ 40338.806942,38504.349909,36074.724695,33087.486423,29588.809337,&
+ 25632.773072,21280.526744,16599.343752,11661.581926,6543.565076,&
+ 1324.403246,-3915.230107,-9094.345093,-14132.887265,-18952.975033,&
+ -23480.103494,-27644.296065,-31381.186125,-34633.011939,-37349.509492,&
+ -39488.689425,-41017.486076,-41912.268581,-42159.206135,-41754.481784,&
+ -40704.351420,-39025.047083,-36742.526062,-33892.069667,-30517.737878,&
+ -26671.688307,-22413.369986,-17808.604454,-12928.568342,-7848.693186/)
+
+ z_vals = (/0.000000,0.000000,0.000000,0.000000,0.000000,&
+ 0.000000,0.000000,0.000000,0.000000,0.000000,&
+ 0.000000,0.000000,0.000000,0.000000,0.000000,&
+ 0.000000,0.000000,0.000000,0.000000,0.000000,&
+ 0.000000,0.000000,0.000000,0.000000,0.000000,&
+ 0.000000,0.000000,0.000000,0.000000,0.000000,&
+ 0.000000,0.000000,0.000000,0.000000,0.000000,&
+ 0.000000,0.000000,0.000000,0.000000,0.000000,&
+ 0.000000,0.000000,0.000000,0.000000,0.000000,&
+ 0.000000,0.000000,0.000000,0.000000,0.000000/)
+
+ vx_vals = (/0.000000,-0.381524,-0.757151,-1.121075,-1.467670,&
+ -1.791579,-2.087795,-2.351740,-2.579333,-2.767058,&
+ -2.912011,-3.011953,-3.065339,-3.071343,-3.029873,&
+ -2.941570,-2.807799,-2.630627,-2.412792,-2.157663,&
+ -1.869183,-1.551810,-1.210451,-0.850381,-0.477167,&
+ -0.096578,0.285505,0.663174,1.030593,1.382081,&
+ 1.712207,2.015866,2.288366,2.525495,2.723586,&
+ 2.879578,2.991061,3.056310,3.074317,3.044804,&
+ 2.968226,2.845769,2.679324,2.471464,2.225402,&
+ 1.944942,1.634419,1.298632,0.942772,0.572339/)
+
+ vy_vals = (/3.074666,3.050903,2.979982,2.862999,2.701762,&
+ 2.498763,2.257141,1.980629,1.673503,1.340509,&
+ 0.986794,0.617827,0.239310,-0.142907,-0.522914,&
+ -0.894839,-1.252932,-1.591658,-1.905782,-2.190448,&
+ -2.441256,-2.654328,-2.826373,-2.954729,-3.037414,&
+ -3.073149,-3.061382,-3.002295,-2.896800,-2.746529,&
+ -2.553805,-2.321606,-2.053522,-1.753696,-1.426763,&
+ -1.077776,-0.712130,-0.335476,0.046363,0.427486,&
+ 0.802001,1.164119,1.508243,1.829054,2.121593,&
+ 2.381338,2.604275,2.786957,2.926560,3.020927/)
+
+ vz_vals = 0.0_dp
+
+ ! call function to validate the ephemerides
+ call compute_chebys_and_error(degree, nephem, n_lag, t_vals, x_vals, y_vals, z_vals,&
+ vx_vals, vy_vals, vz_vals, avg_error)
+ ! Check avg error is within 0.05km (50m)
+ @assertEqual(0.0_dp, avg_error(7), tolerance = 0.05_dp)
+
+ end subroutine test_simulated_GEO_cheby_generation
+
+ !=========================================================================
+ !
+ !> @anchor test_simulated_LEO_cheby_generation
+ !!
+ !> @brief Tests the average error from chebyshev generation and interpolation for simulated LEO
+ !> @author Alex Bush
+ !!
+ !> @date
+ !! - 21.07.2025 (Added function to test_slamInterpolation)
+ !!
+ !!
+ !----------------------------------------------------------------------
+ @test
+ subroutine test_simulated_LEO_cheby_generation()
+
+ implicit none
+ ! Tests the slam_interpolation/chebyshev_generation subroutine
+ ! Uses Known trajectories and chebys to test generation
+ ! Compares generation against original values to calculate error
+
+ ! Reference Data : simulated ephemerides
+ integer :: degree, n_lag, nephem
+ real(dp), dimension(50) :: t_vals, x_vals, y_vals, z_vals, vx_vals, vy_vals, vz_vals
+ real(dp), dimension(7) :: avg_error
+ ! initialization of test data
+ degree = 36
+ nephem = 50
+ n_lag = 5
+ ! initialise ephemeris data 1 orbit of a SSO
+
+ t_vals = (/0.000000,113.874797,227.749593,341.624390,455.499186,&
+ 569.373983,683.248779,797.123576,910.998372,1024.873169,&
+ 1138.747965,1252.622762,1366.497558,1480.372355,1594.247152,&
+ 1708.121948,1821.996745,1935.871541,2049.746338,2163.621134,&
+ 2277.495931,2391.370727,2505.245524,2619.120320,2732.995117,&
+ 2846.869913,2960.744710,3074.619506,3188.494303,3302.369100,&
+ 3416.243896,3530.118693,3643.993489,3757.868286,3871.743082,&
+ 3985.617879,4099.492675,4213.367472,4327.242268,4441.117065,&
+ 4554.991861,4668.866658,4782.741455,4896.616251,5010.491048,&
+ 5124.365844,5238.240641,5352.115437,5465.990234,5579.865030/)
+
+ x_vals = (/6938.000000,6884.379086,6724.345173,6460.371931,6096.539639,&
+ 5638.472113,5093.249780,4469.300233,3776.267964,3024.865289,&
+ 2226.706765,1394.129662,540.003263,-322.470056,-1179.958902,&
+ -2019.208925,-2827.247699,-3591.585231,-4300.407029,-4942.756716,&
+ -5508.705386,-5989.505074,-6377.723980,-6667.361339,-6853.940177,&
+ -6934.576516,-6908.023944,-6774.692891,-6536.644275,-6197.557655,&
+ -5762.674349,-5238.716421,-4633.782776,-3957.223976,-3219.497702,&
+ -2432.007113,-1606.924584,-757.003552,104.618610,964.623665,&
+ 1809.718371,2626.839956,3403.358037,4127.269844,4787.385749,&
+ 5373.502232,5876.559591,6288.781985,6603.797624,6816.737257/)
+
+ y_vals = (/0.000000,-115.350247,-228.917505,-338.946347,-443.736039,&
+ -541.666829,-631.224984,-711.026189,-779.836942,-836.593626,&
+ -880.418942,-910.635475,-926.776163,-928.591517,-916.053477,&
+ -889.355844,-848.911289,-795.344971,-729.484872,-652.349003,&
+ -565.129667,-469.175027,-365.968270,-257.104680,-144.266980,&
+ -29.199321,86.319677,200.504417,311.589926,417.859138,&
+ 517.669432,609.478022,691.865808,763.559309,823.450346,&
+ 870.613173,904.318787,924.046193,929.490463,920.567444,&
+ 897.415059,860.391180,810.068090,747.223642,672.829233,&
+ 588.034790,494.150995,392.629025,285.038123,173.041339/)
+
+ z_vals = (/0.000000,853.148824,1693.110383,2506.901252,3281.942529,&
+ 4006.254270,4668.640669,5258.863108,5767.798420,6187.579906,&
+ 6511.718934,6735.205232,6854.584336,6868.010983,6775.277634,&
+ 6577.817685,6278.683307,5882.498271,5395.386474,4824.877285,&
+ 4179.789161,3470.093336,2706.759698,1901.587222,1067.021594,&
+ 215.962835,-638.434098,-1482.962649,-2304.568797,-3090.552840,&
+ -3828.765690,-4507.796669,-5117.149879,-5647.406448,-6090.370110,&
+ -6439.193902,-6688.485996,-6834.393042,-6874.659732,-6808.663655,&
+ -6637.424925,-6363.590406,-5991.392806,-5526.585245,-4976.352330,&
+ -4349.199105,-3654.819581,-2903.946899,-2108.187424,-1279.841343/)
+
+ vx_vals = (/0.000000,-0.940537,-1.866536,-2.763684,-3.618113,&
+ -4.416616,-5.146851,-5.797530,-6.358596,-6.821376,&
+ -7.178716,-7.425095,-7.556702,-7.571504,-7.469272,&
+ -7.251586,-6.921811,-6.485045,-5.948038,-5.319091,&
+ -4.607926,-3.825536,-2.984014,-2.096367,-1.176317,&
+ -0.238084,0.703829,1.634863,2.540627,3.407119,&
+ 4.220947,4.969532,5.641301,6.225872,6.714209,&
+ 7.098763,7.373590,7.534442,7.578833,7.506077,&
+ 7.317299,7.015415,6.605093,6.092675,5.486082,&
+ 4.794689,4.029184,3.201399,2.324130,1.410936/)
+
+ vy_vals = (/-1.015574,-1.007725,-0.984300,-0.945660,-0.892403,&
+ -0.825351,-0.745543,-0.654210,-0.552765,-0.442775,&
+ -0.325942,-0.204071,-0.079045,0.047203,0.172721,&
+ 0.295569,0.413848,0.525731,0.629487,0.723514,&
+ 0.806356,0.876735,0.933562,0.975959,1.003270,&
+ 1.015073,1.011187,0.991670,0.956825,0.907190,&
+ 0.843532,0.766836,0.678286,0.579253,0.471265,&
+ 0.355994,0.235219,0.110809,-0.015314,-0.141200,&
+ -0.264904,-0.384513,-0.498179,-0.604144,-0.700771,&
+ -0.786566,-0.860202,-0.920543,-0.966654,-0.997824/)
+
+ vz_vals = (/7.511351,7.453298,7.280039,6.994252,6.600353,&
+ 6.104431,5.514152,4.838640,4.088336,3.274838,&
+ 2.410720,1.509339,0.584629,-0.349119,-1.277470,&
+ -2.186075,-3.060889,-3.888391,-4.655789,-5.351222,&
+ -5.963940,-6.484473,-6.904774,-7.218347,-7.420344,&
+ -7.507644,-7.478897,-7.334548,-7.076827,-6.709719,&
+ -6.238897,-5.671640,-5.016715,-4.284246,-3.485554,&
+ -2.632986,-1.739720,-0.819562,0.113264,1.044339,&
+ 1.959272,2.843920,3.684609,4.468344,5.183011,&
+ 5.817564,6.362194,6.808482,7.149530,7.380067/)
+
+ ! call function to validate the ephemerides
+ call compute_chebys_and_error(degree, nephem, n_lag, t_vals, x_vals, y_vals, z_vals,&
+ vx_vals, vy_vals, vz_vals, avg_error)
+ ! Check avg error is within 0.05km (50m)
+ @assertEqual(0.0_dp, avg_error(7), tolerance = 0.05_dp)
+
+ end subroutine test_simulated_LEO_cheby_generation
+
+ !=========================================================================
+ !
+ !> @anchor test_simulated_GTO_cheby_generation
+ !!
+ !> @brief Tests the average error from chebyshev generation and interpolation for simulated GTO
+ !> @author Alex Bush
+ !!
+ !> @date
+ !! - 21.07.2025 (Added function to test_slamInterpolation)
+ !!
+ !!
+ !----------------------------------------------------------------------
+ @test
+ subroutine test_simulated_GTO_cheby_generation()
+
+ implicit none
+ ! Tests the slam_interpolation/chebyshev_generation subroutine
+ ! Uses Known trajectories and chebys to test generation
+ ! Compares generation against original values to calculate error
+
+ ! Reference Data : simulated ephemerides
+ integer :: degree, n_lag, nephem
+ real(dp), dimension(50) :: t_vals, x_vals, y_vals, z_vals, vx_vals, vy_vals, vz_vals
+ real(dp), dimension(7) :: avg_error
+ ! initialization of test data
+ degree = 36
+ nephem = 50
+ n_lag = 5
+ ! initialise ephemeris data 1 orbit of a GTO
+
+ t_vals = (/0.000000,750.690018,1501.380037,2252.070055,3002.760073,&
+ 3753.450092,4504.140110,5254.830128,6005.520147,6756.210165,&
+ 7506.900183,8257.590202,9008.280220,9758.970239,10509.660257,&
+ 11260.350275,12011.040294,12761.730312,13512.420330,14263.110349,&
+ 15013.800367,15764.490385,16515.180404,17265.870422,18016.560440,&
+ 18767.250459,19517.940477,20268.630495,21019.320514,21770.010532,&
+ 22520.700550,23271.390569,24022.080587,24772.770605,25523.460624,&
+ 26274.150642,27024.840661,27775.530679,28526.220697,29276.910716,&
+ 30027.600734,30778.290752,31528.980771,32279.670789,33030.360807,&
+ 33781.050826,34531.740844,35282.430862,36033.120881,36783.810899/)
+
+ x_vals = (/6621.000000,4456.717411,238.884647,-4126.058064,-8206.189989,&
+ -11942.406562,-15351.240408,-18462.325623,-21304.300664,-23901.896192,&
+ -26275.816029,-28443.270268,-30418.581039,-32213.712429,-33838.700290,&
+ -35301.991811,-36610.711675,-37770.870515,-38787.528506,-39664.924010,&
+ -40406.574781,-41015.357392,-41493.569063,-41842.975025,-42064.843698,&
+ -42159.971315,-42128.697101,-41970.909675,-41686.044951,-41273.075454,&
+ -40730.490570,-40056.266871,-39247.827146,-38301.986208,-37214.880809,&
+ -35981.880039,-34597.471348,-33055.115679,-31347.063089,-29464.117522,&
+ -27395.336432,-25127.648530,-22645.374568,-19929.652520,-16957.834182,&
+ -13703.149911,-10135.745744,-6229.251616,-1990.110868,2408.234156/)
+
+ y_vals = (/0.000000,6880.545032,11268.248309,13849.359406,15370.062940,&
+ 16224.222746,16625.867337,16701.614463,16532.149870,16172.034383,&
+ 15659.952688,15024.408739,14287.086424,13464.934514,12571.515981,&
+ 11617.913342,10613.355449,9565.663674,8481.577614,7366.998521,&
+ 6227.175436,5066.850800,3890.377154,2701.813137,1505.004827,&
+ 303.656964,-898.602304,-2098.160097,-3291.358169,-4474.430245,&
+ -5643.434478,-6794.177719,-7922.127574,-9022.307022,-10089.164611,&
+ -11116.410513,-12096.804549,-13021.875832,-13881.543304,-14663.589548,&
+ -15352.911637,-15930.422707,-16371.386475,-16642.791652,-16699.018322,&
+ -16474.282588,-15868.572353,-14719.379497,-12740.248861,-9386.252751/)
+
+ z_vals = 0.0_dp
+
+ vx_vals = (/0.000000,-4.953234,-5.900201,-5.655858,-5.205988,&
+ -4.752776,-4.335905,-3.959101,-3.618022,-3.307116,&
+ -3.021325,-2.756408,-2.508892,-2.275945,-2.055242,&
+ -1.844859,-1.643184,-1.448850,-1.260685,-1.077665,&
+ -0.898889,-0.723548,-0.550902,-0.380271,-0.211011,&
+ -0.042505,0.125851,0.294654,0.464515,0.636060,&
+ 0.809951,0.986897,1.167667,1.353113,1.544195,&
+ 1.742005,1.947806,2.163078,2.389578,2.629416,&
+ 2.885154,3.159923,3.457563,3.782724,4.140797,&
+ 4.537119,4.973551,5.434871,5.830818,5.716375/)
+
+ vy_vals = (/10.201167,7.507986,4.424723,2.614624,1.520125,&
+ 0.801193,0.296149,-0.076835,-0.362755,-0.588201,&
+ -0.769838,-0.918619,-1.042033,-1.145365,-1.232447,&
+ -1.306116,-1.368513,-1.421273,-1.465660,-1.502657,&
+ -1.533027,-1.557363,-1.576117,-1.589622,-1.598112,&
+ -1.601733,-1.600544,-1.594526,-1.583576,-1.567509,&
+ -1.546041,-1.518783,-1.485217,-1.444670,-1.396277,&
+ -1.338926,-1.271182,-1.191180,-1.096463,-0.983747,&
+ -0.848554,-0.684625,-0.482961,-0.230151,0.094666,&
+ 0.525708,1.122880,1.999599,3.388828,5.766293/)
+
+ vz_vals = 0.0_dp
+
+ ! call function to validate the ephemerides
+ call compute_chebys_and_error(degree, nephem, n_lag, t_vals, x_vals, y_vals, z_vals,&
+ vx_vals, vy_vals, vz_vals, avg_error)
+ ! Use large error value due to being a GTO
+ @AssertLessThanOrEqual(avg_error(7),0.3_dp)
+
+ end subroutine test_simulated_GTO_cheby_generation
+
+ !=========================================================================
+ !
+ !> @anchor test_simulated_half_GTO_cheby_generation
+ !!
+ !> @brief Tests the average error from chebyshev generation and interpolation for half of a simulated GTO
+ !> @author Alex Bush
+ !!
+ !> @date
+ !! - 21.07.2025 (Added function to test_slamInterpolation)
+ !!
+ !!
+ !----------------------------------------------------------------------
+ @test
+ subroutine test_simulated_half_GTO_cheby_generation()
+
+ implicit none
+ ! Tests the slam_interpolation/chebyshev_generation subroutine
+ ! Uses Known trajectories and chebys to test generation
+ ! Compares generation against original values to calculate error
+
+ ! Reference Data : simulated ephemerides
+ integer :: degree, n_lag, nephem
+ real(dp), dimension(50) :: t_vals, x_vals, y_vals, z_vals, vx_vals, vy_vals, vz_vals
+ real(dp), dimension(7) :: avg_error
+ ! initialization of test data
+ degree = 36
+ nephem = 50
+ n_lag = 5
+ ! initialise ephemeris data 1/2 orbit of a GTO
+
+ t_vals = (/0.000000,379.136373,758.272746,1137.409119,1516.545492,&
+ 1895.681865,2274.818237,2653.954610,3033.090983,3412.227356,&
+ 3791.363729,4170.500102,4549.636475,4928.772848,5307.909221,&
+ 5687.045594,6066.181966,6445.318339,6824.454712,7203.591085,&
+ 7582.727458,7961.863831,8341.000204,8720.136577,9099.272950,&
+ 9478.409323,9857.545695,10236.682068,10615.818441,10994.954814,&
+ 11374.091187,11753.227560,12132.363933,12511.500306,12890.636679,&
+ 13269.773052,13648.909425,14028.045797,14407.182170,14786.318543,&
+ 15165.454916,15544.591289,15923.727662,16302.864035,16682.000408,&
+ 17061.136781,17440.273154,17819.409526,18198.545899,18577.682272/)
+
+ x_vals = (/6621.000000,5999.027698,4419.066253,2364.858393,149.398763,&
+ -2078.494910,-4254.577006,-6352.727562,-8363.807939,-10286.319940,&
+ -12122.183762,-13874.770287,-15547.962930,-17145.707525,-18671.800828,&
+ -20129.798243,-21522.981643,-22854.357268,-24126.668096,-25342.412585,&
+ -26503.865490,-27613.098607,-28672.000362,-29682.293790,-30645.552764,&
+ -31563.216499,-32436.602438,-33266.917664,-34055.268994,-34802.671887,&
+ -35510.058329,-36178.283789,-36808.133381,-37400.327311,-37955.525706,&
+ -38474.332889,-38957.301171,-39404.934206,-39817.689966,-40195.983372,&
+ -40540.188616,-40850.641206,-41127.639760,-41371.447571,-41582.293960,&
+ -41760.375438,-41905.856686,-42018.871366,-42099.522776,-42147.884348/)
+
+ y_vals = (/0.000000,3749.028960,6937.333011,9429.858971,11334.991863,&
+ 12791.370603,13908.366416,14764.496656,15415.639907,15902.196727,&
+ 16254.033735,16493.737035,16638.752725,16702.817124,16696.932128,&
+ 16630.044695,16509.530088,16341.542237,16131.272336,15883.142831,&
+ 15600.955150,15288.003732,14947.165160,14580.968636,14191.652289,&
+ 13781.208616,13351.421475,12903.896464,12440.086060,11961.310577,&
+ 11468.775768,10963.587693,10446.765368,9919.251594,9381.922266,&
+ 8835.594450,8281.033396,7718.958700,7150.049714,6574.950351,&
+ 5994.273363,5408.604176,4818.504358,4224.514769,3627.158446,&
+ 3026.943268,2424.364433,1819.906790,1214.047047,607.255884/)
+
+ z_vals = 0._dp
+
+ vx_vals = (/0.000000,-3.127585,-4.977460,-5.724264,-5.901014,&
+ -5.825125,-5.643390,-5.421018,-5.187237,-4.955220,&
+ -4.730752,-4.516125,-4.311955,-4.118055,-3.933875,&
+ -3.758718,-3.591850,-3.432557,-3.280167,-3.134063,&
+ -2.993682,-2.858515,-2.728104,-2.602034,-2.479931,&
+ -2.361459,-2.246311,-2.134210,-2.024905,-1.918165,&
+ -1.813779,-1.711554,-1.611312,-1.512888,-1.416130,&
+ -1.320896,-1.227054,-1.134478,-1.043052,-0.952666,&
+ -0.863215,-0.774599,-0.686724,-0.599498,-0.512834,&
+ -0.426645,-0.340849,-0.255365,-0.170115,-0.085019/)
+
+ vy_vals = (/10.201167,9.304261,7.470272,5.735194,4.377417,&
+ 3.353104,2.573324,1.967136,1.485287,1.094361,&
+ 0.771467,0.500610,0.270365,0.072391,-0.099523,&
+ -0.250091,-0.382947,-0.500940,-0.606327,-0.700926,&
+ -0.786211,-0.863392,-0.933472,-0.997287,-1.055540,&
+ -1.108828,-1.157658,-1.202465,-1.243624,-1.281458,&
+ -1.316250,-1.348244,-1.377656,-1.404672,-1.429460,&
+ -1.452163,-1.472911,-1.491817,-1.508979,-1.524485,&
+ -1.538414,-1.550831,-1.561795,-1.571357,-1.579562,&
+ -1.586444,-1.592035,-1.596359,-1.599434,-1.601274/)
+
+ vz_vals =0.0_dp
+
+ ! call function to validate the ephemerides and (optional) chebys
+ call compute_chebys_and_error(degree, nephem, n_lag, t_vals, x_vals, y_vals, z_vals,&
+ vx_vals, vy_vals, vz_vals, avg_error)
+ ! Check avg error is within 0.05km (50m)
+ @assertEqual(0.0_dp, avg_error(7), tolerance = 0.05_dp)
+
+ end subroutine test_simulated_half_GTO_cheby_generation
+
+ !=========================================================================
+ !
+ !> @anchor test_real_LEO_cheby_generation
+ !!
+ !> @brief Tests the average error from chebyshev generation and interpolation for a real LEO
+ !> @author Alex Bush
+ !!
+ !> @date
+ !! - 21.07.2025 (Added function to test_slamInterpolation)
+ !!
+ !!
+ !----------------------------------------------------------------------
+ @test
+ subroutine test_real_LEO_cheby_generation()
+
+ ! Selected data range: 2025-07-15T12:23:45.998Z → 2025-07-15T13:55:45.998Z
+ ! ASTROCAST-103
+ implicit none
+ ! Tests the slam_interpolation/chebyshev_generation subroutine
+ ! Uses Known trajectories and chebys to test generation
+ ! Compares generation against original values to calculate error
+
+ ! Reference Data : oem database
+ integer :: degree, n_lag, nephem
+ real(dp), dimension(93) :: t_vals, x_vals, y_vals, z_vals, vx_vals, vy_vals, vz_vals
+ real(dp), dimension(7) :: avg_error
+ ! initialization of test data
+ degree = 36
+ nephem = 93
+ n_lag = 5
+ ! initialise ephemeris data from database
+
+ t_vals = (/ 0.0, 60.0, 120.0, 180.0, 240.0,&
+ 300.0, 360.0, 420.0, 480.0, 540.0,&
+ 600.0, 660.0, 720.0, 780.0, 840.0,&
+ 900.0, 960.0, 1020.0, 1080.0, 1140.0,&
+ 1200.0, 1260.0, 1320.0, 1380.0, 1440.0,&
+ 1500.0, 1560.0, 1620.0, 1680.0, 1740.0,&
+ 1800.0, 1860.0, 1920.0, 1980.0, 2040.0,&
+ 2100.0, 2160.0, 2220.0, 2280.0, 2340.0,&
+ 2400.0, 2460.0, 2520.0, 2580.0, 2640.0,&
+ 2700.0, 2760.0, 2820.0, 2880.0, 2940.0,&
+ 3000.0, 3060.0, 3120.0, 3180.0, 3240.0,&
+ 3300.0, 3360.0, 3420.0, 3480.0, 3540.0,&
+ 3600.0, 3660.0, 3720.0, 3780.0, 3840.0,&
+ 3900.0, 3960.0, 4020.0, 4080.0, 4140.0,&
+ 4200.0, 4260.0, 4320.0, 4380.0, 4440.0,&
+ 4500.0, 4560.0, 4620.0, 4680.0, 4740.0,&
+ 4800.0, 4860.0, 4920.0, 4980.0, 5040.0,&
+ 5100.0, 5160.0, 5220.0, 5280.0, 5340.0,&
+ 5400.0, 5460.0, 5520.0 /)
+
+ x_vals = (/ -581.4883170936755, -455.4773196962564, -327.39413459307536, -197.82141832512403, -67.34876743383572,&
+ 63.42992138329106, 193.91915256364646, 323.5245009454158, 451.65525319017445, 577.7270989684217,&
+ 701.164834828239, 821.4049870791983, 937.8984373736134, 1050.1130027753402, 1157.5359392836533,&
+ 1259.6763592306413, 1356.06752161331, 1446.2690267049625, 1529.8689038838343, 1606.485596200687,&
+ 1675.7698225642546, 1737.40616437254, 1791.1145010286314, 1836.6513723492321, 1873.8111006747674,&
+ 1902.426706071034, 1922.3706339999544, 1933.5553040254815, 1935.9333825094543, 1929.4978701931066,&
+ 1914.282107835266, 1890.359553598132, 1857.8433368457052, 1816.8855708049593, 1767.6764862259674,&
+ 1710.4434090290276, 1645.4497058208926, 1572.9935095942192, 1493.4063509177656, 1407.051616606087,&
+ 1314.322857132757, 1215.6419779012592, 1111.4573056979652, 1002.2415271602696, 888.4895784012759,&
+ 770.7165148267113, 649.4552960456292, 525.2545367771597, 398.6761333207408, 270.2927250207842,&
+ 140.68521376768354, 10.44036487019188, -119.85176404643563, -249.60049183347, -378.21712420652415,&
+ -505.117552773319, -629.7248783171311, -751.4720349260248, -869.8043779829368, -984.1822412954771,&
+ -1094.0834350630914, -1199.0056458579081, -1298.4687957188019, -1392.017316648883, -1479.2223455483024,&
+ -1559.6838816371462, -1633.0328052905218, -1698.932485615251, -1757.0803689208499, -1807.2095465672876,&
+ -1849.0899835090618, -1882.5296976624993, -1907.3757420665822, -1923.5148610573417, -1930.873963142809,&
+ -1929.4204103248646, -1919.1621396103826, -1900.1475414803463, -1872.4651307557208, -1836.243088865017,&
+ -1791.648690281299, -1738.8874376265974, -1678.2020035346059, -1609.871013737789, -1534.2076849505506,&
+ -1451.5583518698597, -1362.3008210642265, -1266.842680951607, -1165.6194350601056, -1059.092469971498,&
+ -947.7469865413706, -832.0898923164455, -712.6475814812727 /)
+
+ y_vals = (/ 1079.822115151392, 1515.0682180316155, 1943.420800585655, 2362.929540384556, 2771.683437953355,&
+ 3167.819504373793, 3549.5312322039863, 3915.0767445644406, 4262.786745542611, 4591.072276738612,&
+ 4898.43208917842, 5183.459654393587, 5444.849857876441, 5681.405167365042, 5892.0414016168625,&
+ 6075.793035740339, 6231.817883385876, 6359.401161809126, 6457.958975064257, 6527.041196526832,&
+ 6566.333599141489, 6575.659233676765, 6554.979396931292, 6504.393929998854, 6424.140560582537,&
+ 6314.5935560586195, 6176.261798765726, 6009.786250567006, 5815.93664135191, 5595.607530784274,&
+ 5349.813915423737, 5079.686231655515, 4786.464804089997, 4471.493761489497, 4136.214531849416,&
+ 3782.159065784034, 3410.9427723668023, 3024.2570210060517, 2623.861459424205, 2211.575967478841,&
+ 1789.272421528013, 1358.866341233585, 922.3084126460911, 481.57594455740525, 38.664272559732176,&
+ -404.4219463646025, -845.6774903574776, -1283.1052260356212, -1714.7247817391615, -2138.5812132261103,&
+ -2552.753432230469, -2955.362548810453, -3344.5803362994684, -3718.6373584479356, -4075.8308334100616,&
+ -4414.532463562326, -4733.195984828237, -5030.364389486537, -5304.6767598472015, -5554.874719912398,&
+ -5779.808327626059, -5978.441563897056, -6149.857575200546, -6293.263249477752, -6407.993273398453,&
+ -6493.513614179161, -6549.424260828154, -6575.461118117091, -6571.497731157684, -6537.546250662111,&
+ -6473.757397711444, -6380.419837864755, -6257.958722571676, -6106.933571934138, -5928.035495276835,&
+ -5722.083823026676, -5490.022158464803, -5232.9137849076305, -4951.936516220711, -4648.3771079395765,&
+ -4323.625090256498, -3979.1660420189, -3616.574648070642, -3237.5073821101923, -2843.6947642803448,&
+ -2436.9333405604957, -2019.0775641823452, -1592.031466163807, -1157.7399809554634, -718.1801319704053,&
+ -275.35223601432557, 168.72890733147, 612.0429155310919 /)
+
+ z_vals = (/ 6682.038294502038, 6607.0307644424165, 6501.8734921742125, 6367.042415052587, 6203.148171947553,&
+ 6010.93358419692, 5791.270441157087, 5545.155720603305, 5273.707374349175, 4978.159524561255,&
+ 4659.857016797191, 4320.249507415202, 3960.885007363264, 3583.4029183062235, 3189.5266725528536,&
+ 2781.055830274453, 2359.8577415301484, 1927.8588850309964, 1487.0359072494732, 1039.4063662954397,&
+ 587.01917240794, 131.9450012576637, -323.73333332844396, -777.9308350454152, -1228.5702943725405,&
+ -1673.5920130515922, -2110.9634210350255, -2538.688602443353, -2954.817666600897, -3357.455660681554,&
+ -3744.771231864449, -4115.004989409664, -4466.477468059891, -4797.596590173402, -5106.864580720168,&
+ -5392.884335930978, -5654.365450564964, -5890.129706417098, -6099.11604595301, -6280.385078078309,&
+ -6433.122902521485, -6556.644408532332, -6650.3960023798845, -6713.9578025750825, -6747.045310405938,&
+ -6749.510558643918, -6721.342624475021, -6662.667639501295, -6573.748366310433, -6454.983125625859,&
+ -6306.904078953601, -6130.175238709394, -5925.589911234742, -5694.067339013946, -5436.6490230695545,&
+ -5154.494486993373, -4848.8764143886865, -4521.175207022572, -4172.873008259504, -3805.5472131422302,&
+ -3420.8634663301395, -3020.568478416216, -2606.482250496465, -2180.4898525564467, -1744.5328508817709,&
+ -1300.6003617161389, -850.7196750975179, -396.9468777212519, 58.642536859367105, 513.96367037947,&
+ 966.9321874884578, 1415.4742207673744, 1857.5362631848068, 2291.094867312583, 2714.166140620363,&
+ 3124.814969810593, 3521.1640321664822, 3901.402512711647, 4263.794406801175, 4606.686437186749,&
+ 4928.515661443597, 5227.816456343788, 5503.226955189794, 5753.495100009383, 5977.484151289982,&
+ 6174.177531646045, 6342.683126809845, 6482.237156515285, 6592.207526874503, 6672.096393790979,&
+ 6721.542138825866, 6740.320856660477, 6728.347407665809 /)
+
+ vx_vals = (/ 2.0797153239328927, 2.1190582470535015, 2.1487620878541285, 2.1686899507213315, 2.1787479395370224,&
+ 2.1788867973633086, 2.169102326512362, 2.1494343369891276, 2.1199668946035533, 2.0808294565942984,&
+ 2.032195798103411, 1.9742832343442314, 1.907352790790755, 1.8317077580098657, 1.7476925862036055,&
+ 1.6556909653548455, 1.5561238676548892, 1.4494480602192235, 1.3361540938450693, 1.216764992513522,&
+ 1.0918326721247928, 0.9619335499613356, 0.8276677559341222, 0.6896563673391014, 0.548537211808185,&
+ 0.404961826083069, 0.2595924186493676, 0.11309842090432953, -0.033848597476748496, -0.18057579396191303,&
+ -0.32641212020003585, -0.4706919049177677, -0.6127592175334681, -0.7519709304873728, -0.8877001582061871,&
+ -1.0193371276875858, -1.1462911394751303, -1.2679940429958343, -1.383901376217442, -1.493496064056003,&
+ -1.5962900844071481, -1.6918266346523574, -1.7796821639746225, -1.8594683759047559, -1.930831918467966,&
+ -1.9934558073359363, -2.0470602334198706, -2.0914035336815675, -2.1262852241755796, -2.151547451729648,&
+ -2.1670722996686766, -2.172782866764182, -2.168646595043904, -2.154675013467294, -2.1309228140379686,&
+ -2.097488240757327, -2.054513376746901, -2.0021837875331214, -1.9407278700161956, -1.8704164001604546,&
+ -1.791560741049301, -1.7045120953087716, -1.609660169343286, -1.5074319766835653, -1.3982906211138462,&
+ -1.2827348404908774, -1.1612937316923417, -1.0345214014985533, -0.9029996502238115, -0.7673336017958665,&
+ -0.6281474243877333, -0.48608467409191336, -0.3418020572802087, -0.19596548037655112, -0.04924722143327155,&
+ 0.09767689641044247, 0.24413095183813563, 0.3894429791615178, 0.5329478416200099, 0.6739886508229014,&
+ 0.8119201732225643, 0.9461138197559856, 1.075959637776023, 1.2008695738224038, 1.320278873201574,&
+ 1.4336489818021367, 1.540469335634728, 1.6402583614891357, 1.732567630115414, 1.816982843022994,&
+ 1.8931245874775322, 1.960649012021734, 2.01925096013006 /)
+
+ vy_vals = (/ 7.300577912249002, 7.202120538984326, 7.070878860665573, 6.90743506450951, 6.712517515426457,&
+ 6.486997714847501, 6.23188578266617, 5.9483255281761425, 5.637592024901249, 5.3010869345928935,&
+ 4.940331242213968, 4.556960589680341, 4.152718097673897, 3.729445790674295, 3.2890787059103834,&
+ 2.8336352338218096, 2.365206545278644, 1.8859466706415893, 1.3980628156842823, 0.9038046755077809,&
+ 0.40545027038143616, -0.094703376801344, -0.59434698232834, -1.0911745200036491, -1.5828976240110502,&
+ -2.0672549431566236, -2.542022255727687, -3.0050234399676707, -3.4541441064174667, -3.887338736227909,&
+ -4.302640139396071, -4.6981689471113945, -5.072143137407782, -5.422885761222072, -5.748831198642559,&
+ -6.048528295708793, -6.32064780768167, -6.563987068317808, -6.777474150706344, -6.960173600297738,&
+ -7.111288009667206, -7.230160390609887, -7.316275656133425, -7.369261593410994, -7.388889866210224,&
+ -7.375078315294299, -7.327889813017214, -7.247531254063724, -7.1343545396451225, -6.988854512686095,&
+ -6.8116645953767625, -6.603558640049534, -6.365450338812312, -6.098384921397938, -5.803539100822478,&
+ -5.482218045360532, -5.135850194096199, -4.765981167974391, -4.374267363746959, -3.9624688866733315,&
+ -3.5324387012812153, -3.086121085320564, -2.6255417422329237, -2.1527983420483947, -1.6700515817043753,&
+ -1.1795148709147616, -0.6834391618214838, -0.18410454735993192, 0.3161836247721026, 0.8151136032722495,&
+ 1.3103791831745888, 1.7996912637058962, 2.280790941162654, 2.751460062541233, 3.2095321360729483,&
+ 3.6529012048323906, 4.079532614225198, 4.48747325629925, 4.874859669154023, 5.2399255705922885,&
+ 5.5810131814919455, 5.896578922010942, 6.185197420132488, 6.445568861262864, 6.67652574089985,&
+ 6.877034828425971, 7.046199661850096, 7.183265223662285, 7.2876234285807975, 7.35881266576162,&
+ 7.396518069580296, 7.400572039105373, 7.370956311090771 /)
+
+ vz_vals = (/ -0.9968010080317333, -1.502506671881744, -2.0014132407728944, -2.4912590641996135, -2.969818091185215,&
+ -3.4349121340191098, -3.884422083784645, -4.316295193684226, -4.728553364411682, -5.119304310368893,&
+ -5.486750672037101, -5.829197658077127, -6.145063087683969, -6.432883701106776, -6.6913233934155425,&
+ -6.91918185906022, -7.11540061236182, -7.279068019203137, -7.409424225762732, -7.505866398417632,&
+ -7.567952221435513, -7.595398429928264, -7.588084938474152, -7.546059079462936, -7.469532163409317,&
+ -7.358876463456851, -7.214623622593225, -7.037463617438367, -6.828239013528119, -6.587938044519016,&
+ -6.3176915656140356, -6.018766438593244, -5.692558483194781, -5.3405833564521314, -4.964467132508124,&
+ -4.565938719151954, -4.146824229279959, -3.709035645883403, -3.254565208968325, -2.7854741110047443,&
+ -2.303882863182063, -1.8119622892356202, -1.3119240486793915, -0.8060120191617762, -0.2964937554284478,&
+ 0.21434915640115454, 0.7242315070452726, 1.230871142258918, 1.7319976691250931, 2.225364925795568,&
+ 2.7087581438884043, 3.179998580402568, 3.636957899131697, 4.077566928955757, 4.499821355128556,&
+ 4.901793101238427, 5.281639874625121, 5.637614839644509, 5.96807482385123, 6.271489627509885,&
+ 6.546447724319053, 6.791660728387121, 7.005974852416435, 7.188376026077476, 7.337996098313709,&
+ 7.45411951815418, 7.536189465295325, 7.583802387361124, 7.5967172789199555, 7.574861278624894,&
+ 7.5183257908720345, 7.427368404702681, 7.30240968631677, 7.14403043874982, 6.952967511654237,&
+ 6.730109578492399, 6.476493479950002, 6.193298120308379, 5.881837105687309, 5.543553795222516,&
+ 5.180014063917279, 4.792894449398428, 4.383976029252548, 3.9551365349678953, 3.5083401393962497,&
+ 3.0456267024484927, 2.5691038996889977, 2.0809406026134587, 1.5833549478080657, 1.0786023758770573,&
+ 0.5689668547834457, 0.05675380686303381, -0.4557185507673941 /)
+
+ ! call function to validate the ephemerides
+ call compute_chebys_and_error(degree, nephem, n_lag, t_vals, x_vals, y_vals, z_vals,&
+ vx_vals, vy_vals, vz_vals, avg_error)
+ ! Check avg error is within 0.05km (50m)
+ @assertEqual(0.0_dp, avg_error(7), tolerance = 0.05_dp)
+
+ end subroutine test_real_LEO_cheby_generation
+
+ !=========================================================================
+ !
+ !> @anchor test_real_GEO_cheby_generation
+ !!
+ !> @brief Tests the average error from chebyshev generation and interpolation for a real GEO
+ !> @author Alex Bush
+ !!
+ !> @date
+ !! - 21.07.2025 (Added function to test_slamInterpolation)
+ !!
+ !!
+ !----------------------------------------------------------------------
+
+ @test
+ subroutine test_real_GEO_cheby_generation()
+
+ ! Selected data range: 2025-06-14T21:00:00.106Z → 2025-06-15T20:45:00.106Z
+ ! Object ID: 21789 "Unspecified"
+
+ implicit none
+ ! Tests the slam_interpolation/chebyshev_generation subroutine
+ ! Uses Known trajectories and chebys to test generation
+ ! Compares generation against original values to calculate error
+
+ ! Reference Data : oem database
+ integer :: degree, n_lag, nephem
+ real(dp), dimension(96) :: t_vals, x_vals, y_vals, z_vals, vx_vals, vy_vals, vz_vals
+ real(dp), dimension(7) :: avg_error
+ ! initialization of test data
+ degree = 36
+ nephem = 96
+ n_lag = 5
+ ! initialise ephemeris data from database
+ ! Ephemeris data extracted from database JSON using python
+
+ t_vals = (/ 0.0, 900.0, 1800.0, 2700.0, 3600.0,&
+ 4500.0, 5400.0, 6300.0, 7200.0, 8100.0,&
+ 9000.0, 9900.0, 10800.0, 11700.0, 12600.0,&
+ 13500.0, 14400.0, 15300.0, 16200.0, 17100.0,&
+ 18000.0, 18900.0, 19800.0, 20700.0, 21600.0,&
+ 22500.0, 23400.0, 24300.0, 25200.0, 26100.0,&
+ 27000.0, 27900.0, 28800.0, 29700.0, 30600.0,&
+ 31500.0, 32400.0, 33300.0, 34200.0, 35100.0,&
+ 36000.0, 36900.0, 37800.0, 38700.0, 39600.0,&
+ 40500.0, 41400.0, 42300.0, 43200.0, 44100.0,&
+ 45000.0, 45900.0, 46800.0, 47700.0, 48600.0,&
+ 49500.0, 50400.0, 51300.0, 52200.0, 53100.0,&
+ 54000.0, 54900.0, 55800.0, 56700.0, 57600.0,&
+ 58500.0, 59400.0, 60300.0, 61200.0, 62100.0,&
+ 63000.0, 63900.0, 64800.0, 65700.0, 66600.0,&
+ 67500.0, 68400.0, 69300.0, 70200.0, 71100.0,&
+ 72000.0, 72900.0, 73800.0, 74700.0, 75600.0,&
+ 76500.0, 77400.0, 78300.0, 79200.0, 80100.0,&
+ 81000.0, 81900.0, 82800.0, 83700.0, 84600.0,&
+ 85500.0 /)
+
+ x_vals = (/ -36057.95958643016, -34558.165395768236, -32909.68837929546, -31119.616442665574, -29195.64675746132,&
+ -27146.05279005136, -24979.648852542738, -22705.75232496435, -20334.14370780417, -17875.02467342418,&
+ -15338.974293619807, -12736.90362866037, -10080.008870494268, -7379.723239394915, -4647.667839108313,&
+ -1895.6016805434683, 864.6289118590935, 3621.1412937352193, 6362.067674742536, 9075.606251869627,&
+ 11750.072080762402, 14373.947464338244, 16935.931639575403, 19424.989545984143, 21830.399462901787,&
+ 24141.799307376707, 26349.23139002624, 28443.185432836188, 30414.639660388068, 32255.09978442412,&
+ 33956.63571092738, 35511.91580899792, 36914.23859162702, 38157.56167000969, 39236.52785518337,&
+ 40146.48829349991, 40883.52253563362, 41444.45545244546, 41826.87092499105, 42029.12225019501,&
+ 42050.33921816868, 41890.43183172469, 41550.0906533066, 41030.78377923085, 40334.75045574398,&
+ 39464.99136592677, 38425.25563081407, 37220.0245822292, 35854.49237868296, 34334.54354920964,&
+ 32666.72756316102, 30858.230536693223, 28916.84419892415, 26850.932252452527, 24669.394274071972,&
+ 22381.627312033073, 19997.485346074853, 17527.23678559512, 14981.52018974164, 12371.298400832844,&
+ 9707.811289319177, 7002.5273144443945, 4267.094109841513, 1513.288307469162, -1247.0351835093966,&
+ -4001.9942239732613, -6739.73059798947, -9448.46105126879, -12116.527994937434, -14732.449656235103,&
+ -17284.969460283337, -19763.104430537947, -22156.192399978194, -24453.937830420316, -26646.45604351666,&
+ -28724.31567407633, -30678.57916421681, -32500.84112548519, -34183.26440544993, -35718.61370532628,&
+ -37100.28660588882, -38322.34187016832, -39379.52490325073, -40267.290261748596, -40981.821118213884,&
+ -41520.04559879992, -41879.64992583895, -42059.088310596795, -42057.58955526641, -41875.160337162066,&
+ -41512.58516208894, -40971.42298789231, -40254.00053314895, -39363.40229988731, -38303.45735297744,&
+ -37078.722912399484 /)
+
+ y_vals = (/ -20643.952961465246, -22929.516350409842, -25116.429462950473, -27195.28059089369, -29157.122081335965,&
+ -30993.508825652054, -32696.53460803449, -34258.866157427445, -35673.77475606439, -36935.16526782483,&
+ -38037.60246021888, -38976.33450497051, -39747.3135538647, -40347.21329871249, -40773.4434369097,&
+ -41024.16097712982, -41098.27833308206, -40995.46816698103, -40716.16495834833, -40261.56328792388,&
+ -39633.61284077365, -38835.01014703666, -37869.187093127584, -36740.29625051033, -35453.19308329778,&
+ -34013.41510986978, -32427.15810732896, -30701.24946086682, -28843.118772947837, -26860.765859478266,&
+ -24762.726271859534, -22558.034494880558, -20256.184980748716, -17867.09118914638, -15401.042811988416,&
+ -12868.661369501711, -10280.854371291096, -7648.76824222922, -4983.740218235064, -2297.249421302904,&
+ 399.1326735016806, 3093.7921639640294, 5775.122822985336, 8431.576160111932, 11051.71122566933,&
+ 13624.243942196736, 16138.095750145572, 18582.44135795849, 20946.755390702543, 23220.85773632083,&
+ 25394.957394321835, 27459.694638277106, 29406.181310852644, 31226.03907820674, 32911.43547943056,&
+ 34455.11761624143, 35850.44333834204, 37091.40979066767, 38172.679200146915, 39089.60179151975,&
+ 39838.235734174676, 40415.36403479367, 40818.508303822324, 41045.93933731952, 41096.68446951587,&
+ 40970.53166543075, 40668.030337008175, 40190.488880434146, 39539.968946508474, 38719.276470078534,&
+ 37731.94949856502, 36582.24287343931, 35275.10983207754, 33816.180610677344, 32211.738141795857,&
+ 30468.690952520486, 28594.543381220592, 26597.363242254363, 24485.74707881415, 22268.783154280052,&
+ 19956.012341956575, 17557.387081854235, 15083.228581235233, 12544.182442885374, 9951.172911559544,&
+ 7315.355934683791, 4648.071238183132, 1960.7936222696542, -734.9163148800393, -3427.461815460009,&
+ -6105.259750909587, -8756.790349348692, -11370.646650067752, -13935.583474786308, -16440.56570747288,&
+ -18874.815677512386 /)
+
+ z_vals = (/ -7242.244158117268, -7664.030346187642, -8052.841056503548, -8407.002570942595, -8724.990063492725,&
+ -9005.434168948312, -9247.12688774372, -9449.026801333435, -9610.263575373618, -9730.141730915184,&
+ -9808.14366685965, -9843.931920059305, -9837.35065264185, -9788.426359400788, -9697.367791404053,&
+ -9564.56509531803, -9390.5881713149, -9176.184255810327, -8922.27473865031, -8629.951227718355,&
+ -8300.470877252781, -7935.250999421106, -7535.862981893578, -7104.025537264368, -6641.597313165575,&
+ -6150.568894802393, -5633.054234379238, -5091.281544473535, -4527.5836948404085, -3944.3881543624807,&
+ -3344.2065219098226, -2729.6236917129568, -2103.2867004768345, -1467.893304864574, -826.1803391575016,&
+ -180.91190384135314, 465.1325634274885, 1109.1702825450539, 1748.4271392067983, 2380.1496545095024,&
+ 3001.6168639663297, 3610.1520544503815, 4203.134308257315, 4778.009804375342, 5332.302828158054,&
+ 5863.62644190804, 6369.692770390232, 6848.3228569972, 7297.4560481767085, 7715.158865790513,&
+ 8099.633329305596, 8449.22469210575, 8762.428558747719, 9037.897352660058, 9274.446106589388,&
+ 9471.057551017906, 9626.886478804296, 9741.263367420515, 9813.697243361275, 9843.87777657169,&
+ 9831.676596065066, 9777.147821265438, 9680.52780700224, 9542.234103486928, 9362.863635990916,&
+ 9143.1901123294, 8884.160669590892, 8586.891774843563, 8252.664397776192, 7882.918476371519,&
+ 7479.246699758982, 7043.387635334192, 6577.218230044996, 6082.745718424416, 5562.098972483517,&
+ 5017.519330951516, 4451.350947550518, 3866.0307000225434, 3264.077703463962, 2648.0824731686253,&
+ 2020.695783627042, 1384.6172715707823, 742.583831986257, 97.3578568395237, -548.2846331341667,&
+ -1191.565912828961, -1829.7184824319743, -2459.996951458047, -3079.689826505405, -3686.1311525457318,&
+ -4276.711958216159, -4848.891456434269, -5400.2079527339565, -5928.289414963865, -6430.863659419112,&
+ -6905.768110106437 /)
+
+ vx_vals = (/ 1.5813873559120812, 1.7502939849639536, 1.9116751363892557, 2.0648364875842447, 2.2091189216052265,&
+ 2.343901359381892, 2.468603432005514, 2.5826879816310027, 2.685663380265498, 2.7770856563065878,&
+ 2.8565604195138867, 2.923744575832861, 2.9783478243163235, 3.020133929263271, 3.0489217615948827,&
+ 3.064586104406941, 3.067058218646107, 3.056326165844351, 3.032434885888959, 2.9954860288790157,&
+ 2.945637541199749, 2.883103007053138, 2.8081507478011267, 2.721102682591281, 2.622332954858614,&
+ 2.5122663303995685, 2.3913763737917684, 2.2601834110135908, 2.1192522871167365, 1.9691899287954193,&
+ 1.8106427226168085, 1.644293720558478, 1.4708596852760973, 1.2910879882793853, 1.1057533748419792,&
+ 0.9156546100497385, 0.7216110209134212, 0.5244589498610825, 0.3250481353068103, 0.12423803524681012,&
+ -0.07710588998729401, -0.27811591954963044, -0.4779258221694027, -0.6756745982236212, -0.8705101975986005,&
+ -1.0615931972945407, -1.2481004229449844, -1.4292284986990795, -1.6041973102465104, -1.7722533661628452,&
+ -1.9326730431914214, -2.0847657015974677, -2.2278766572663664, -2.361389997847506, -2.484731230895856,&
+ -2.5973697526818347, -2.6988211270911586, -2.788649164856268, -2.8664677941988193, -2.931942714861689,&
+ -2.984792828439317, -3.0247914388855173, -3.051767218044625, -3.065604932108856, -3.066245925956298,&
+ -3.0536883633109113, -3.027987221838378, -2.989254043294419, -2.9376564399366365, -2.873417359521734,&
+ -2.7968141122208814, -2.708177163831844, -2.607888700741161, -2.496380973042696, -2.374134423156358,&
+ -2.2416756082664824, -2.0995749257680156, -1.9484441517120286, -1.7889338030525326, -1.6217303352304544,&
+ -1.4475531873038727, -1.267151687430073, -1.0813018320924663, -0.8908029529476608, -0.6964742855949961,&
+ -0.49915145494922547, -0.2996828921962753, -0.0989261985673652, 0.10225552866620294, 0.30299739247247515,&
+ 0.5024363990162002, 0.69971515172367, 0.8939855209762047, 1.084412274033725, 1.270176649998912,&
+ 1.450479864872649 /)
+
+ vy_vals = (/ -2.590714787130631, -2.486492831281575, -2.371570426806283, -2.2464410605026, -2.111642113553522,&
+ -1.9677525732990802, -1.8153905665223682, -1.6552107243326586, -1.4879013893691904, -1.3141816768176935,&
+ -1.1347984013071069, -0.9505228823958902, -0.7621476419301706, -0.5704830070629658, -0.37635363320101256,&
+ -0.18059496160759697, 0.015950373288227848, 0.21243617147390337, 0.4080163141913187, 0.6018484142020901,&
+ 0.7930974535392554, 0.9809393927800001, 1.164564735890291, 1.3431820348273285, 1.5160213182920192,&
+ 1.6823374293027695, 1.8414132566379076, 1.992562845654437, 2.135134374502563, 2.268512982421257,&
+ 2.3921234374407176, 2.505432631564025, 2.6079518923864304, 2.69923910090498, 2.778900606230204,&
+ 2.8465929288623593, 2.9020242451829725, 2.9449556468335314, 2.9752021696782815, 2.9926335881062838,&
+ 2.997174971471244, 2.988807000530367, 2.9675660427890627, 2.9335439867060695, 2.8868878357530905,&
+ 2.82779906433188, 2.756532738579831, 2.6733964060574995, 2.578748759302391, 2.4729980791655177,&
+ 2.3566004647690066, 2.23005785782033, 2.0939158698740945, 1.9487614219676983, 1.7952202068459442,&
+ 1.6339539847460014, 1.4656577244245732, 1.291056601776191, 1.110902869004971, 0.9259726078834549,&
+ 0.7370623811323979, 0.5449857964007424, 0.3505699977362345, 0.15465209973114147, -0.041924420221359296,&
+ -0.23831335589272243, -0.43366941668635617, -0.6271518668013735, -0.8179281433314908, -1.005177437649166,&
+ -1.1880942245900696, -1.3658917241976727, -1.5378052811257148, -1.7030956471592276, -1.8610521527799013,&
+ -2.0109957542115713, -2.152281942959126, -2.2843035054840315, -2.406493121331295, -2.5183257887778363,&
+ -2.6193210678196013, -2.709045131142372, -2.787112614562809, -2.853188259320028, -2.9069883394697413,&
+ -2.948281868589513, -2.9768915809447885, -2.9926946831752606, -2.9956233735666524, -2.9856651269832644,&
+ -2.962862744382403, -2.9273141668726135, -2.879172055307575, -2.818643137235196, -2.7459873239933104,&
+ -2.661516601737802 /)
+
+ vz_vals = (/ -0.48631135365536127, -0.4506549555686876, -0.41305876389996776, -0.37368432689813513, -0.3327008499303308,&
+ -0.29028447310055305, -0.2466175188860276, -0.20188771291051866, -0.15628738105638296, -0.1100126262713139,&
+ -0.06326248848411561, -0.016238091156162572, 0.030858221944373952, 0.07782375609048024, 0.12445633736650398,&
+ 0.17055518312759038, 0.21592176739592803, 0.26036067743908886, 0.3036804577945566, 0.34569443802941957,&
+ 0.3862215405779206, 0.42508706507246646, 0.4621234456617811, 0.4971709779215434, 0.5300785120902016,&
+ 0.5607041095015953, 0.5889156592488551, 0.614591452296881, 0.6376207104462305, 0.6579040677739834,&
+ 0.6753540023883391, 0.6898952165654689, 0.7014649635949576, 0.7100133198945948, 0.7155034012177098,&
+ 0.7179115220364116, 0.717227297445916, 0.7134536871942061, 0.7066069817046307, 0.6967167302174152,&
+ 0.6838256114290578, 0.6679892472627026, 0.6492759606413783, 0.6277664783794675, 0.6035535805409763,&
+ 0.5767416978299152, 0.5474464588035078, 0.5157941889026055, 0.48192136349527415, 0.4459740173176596,&
+ 0.40810711287983426, 0.36848387057503, 0.32727506338718554, 0.28465827924328047, 0.2408171541948915,&
+ 0.19594057973450296, 0.15022188766457242, 0.1038580160356597, 0.05704865975231976, 0.0099954095134226,&
+ -0.037099117194068804, -0.08403214929393196, -0.13060163573146236, -0.1766071157198875, -0.22185058186153353,&
+ -0.26613733239851806, -0.3092768089157546, -0.351083415869626, -0.39137731840142453, -0.42998521499690495,&
+ -0.466741081661626, -0.5014868844103814, -0.5340732570208586, -0.5643601411513813, -0.5922173860945779,&
+ -0.6175253056233795, -0.6401751895787158, -0.6600697680490101, -0.6771236262022453, -0.6912635680552222,&
+ -0.7024289276834905, -0.710571826607569, -0.7156573763243701, -0.7176638251920917, -0.7165826491071603,&
+ -0.7124185856575294, -0.7051896116738356, -0.6949268643270097, -0.6816745061634767, -0.6654895347094208,&
+ -0.6464415374750017, -0.6246123934268184, -0.6000959222303577, -0.5729974827454098, -0.5434335224674325,&
+ -0.5115310798217358 /)
+
+ ! call function to validate the ephemerides
+ call compute_chebys_and_error(degree, nephem, n_lag, t_vals, x_vals, y_vals, z_vals,&
+ vx_vals, vy_vals, vz_vals, avg_error)
+ ! Check avg error is within 0.05km (50m)
+ @assertEqual(0.0_dp, avg_error(7), tolerance = 0.05_dp)
+
+ end subroutine test_real_GEO_cheby_generation
+
+ !=========================================================================
+ !
+ !> @anchor test_real_GTO_cheby_generation
+ !!
+ !> @brief Tests the average error from chebyshev generation and interpolation for a real GTO
+ !> @author Alex Bush
+ !!
+ !> @date
+ !! - 21.07.2025 (Added function to test_slamInterpolation)
+ !!
+ !!
+ !----------------------------------------------------------------------
+
+
+ @test
+ subroutine test_real_GTO_cheby_generation()
+
+ ! Selected data range: 2025-05-31T20:07:27.560Z → 2025-06-01T06:52:27.560Z
+ ! Object ID: 34112 "Unspecified"
+
+ implicit none
+ ! Tests the slam_interpolation/chebyshev_generation subroutine
+ ! Uses Known trajectories and chebys to test generation
+ ! Compares generation against original values to calculate error
+
+ ! Reference Data : oem database
+ integer :: degree, n_lag, nephem
+ real(dp), dimension(44) :: t_vals, x_vals, y_vals, z_vals, vx_vals, vy_vals, vz_vals
+ real(dp), dimension(7) :: avg_error
+
+ ! initialization of test data
+ degree = 36
+ nephem = 44
+ n_lag = 5
+ ! initialise ephemeris data from database
+
+ t_vals = (/ 0.0, 900.0, 1800.0, 2700.0, 3600.0,&
+ 4500.0, 5400.0, 6300.0, 7200.0, 8100.0,&
+ 9000.0, 9900.0, 10800.0, 11700.0, 12600.0,&
+ 13500.0, 14400.0, 15300.0, 16200.0, 17100.0,&
+ 18000.0, 18900.0, 19800.0, 20700.0, 21600.0,&
+ 22500.0, 23400.0, 24300.0, 25200.0, 26100.0,&
+ 27000.0, 27900.0, 28800.0, 29700.0, 30600.0,&
+ 31500.0, 32400.0, 33300.0, 34200.0, 35100.0,&
+ 36000.0, 36900.0, 37800.0, 38700.0 /)
+
+ x_vals = (/ -31760.346346389517, -33217.38246275971, -34390.53015263985, -35306.16510904038, -35985.692297037094,&
+ -36446.70253584497, -36703.802108077434, -36769.220005918454, -36653.26054783433, -36364.64623753927,&
+ -35910.781259896685, -35297.95665257954, -34531.51203818341, -33615.964702304795, -32555.114066160855,&
+ -31352.127811137514, -30009.614829061084, -28529.689686841077, -26914.033412315977, -25163.956266103356,&
+ -23280.47009205614, -21264.38149838595, -19116.42379810722, -16837.457859123824, -14428.794913268082,&
+ -11892.738824972885, -9233.53559377644, -6459.111534129384, -3584.4253732266716, -638.3602393007992,&
+ 2320.917049857711, 5168.064901547202, 7605.086588693619, 8841.022163273316, 6958.7116362809065,&
+ 998.60743376712, -5768.298349224206, -11582.967630777934, -16391.906332665927, -20383.710025432785,&
+ -23720.28309502083, -26520.056127925753, -28869.06361310009, -30831.077090255778 /)
+
+ y_vals = (/ -2887.2901376742593, -4686.836025675784, -6446.650091800536, -8158.426016111543, -9815.816441813693,&
+ -11413.733446299586, -12947.894346370611, -14414.514496297217, -15810.090443969944, -17131.2394221625,&
+ -18374.57385165739, -19536.5968476924, -20613.608975075436, -21601.618919893765, -22496.251994687882,&
+ -23292.65080940525, -23985.36216869019, -24568.203304149836, -25034.098797623043, -25374.876725898852,&
+ -25581.008168189604, -25641.267423114292, -25542.27963901128, -25267.9055539491, -24798.385170958234,&
+ -24109.115180897854, -23168.853099952717, -21936.993912256126, -20359.292655779424, -18360.896636418795,&
+ -15834.648796157853, -12621.610982499586, -8485.320017138594, -3149.614837295458, 3002.8648475966324,&
+ 7279.335866191098, 8486.256841621667, 8040.011258566703, 6849.5573842059375, 5303.787210143741,&
+ 3581.9603742848253, 1776.3787630598028, -60.87722648341039, -1898.2099818418978 /)
+
+ z_vals = (/ -230.76694225235096, -1416.7819590670329, -2590.9156896285162, -3745.8118066658913, -4875.777965856397,&
+ -5976.226740680711, -7043.308168166998, -8073.658599447485, -9064.222062204903, -10012.117589795396,&
+ -10914.535751623309, -11768.653309937286, -12571.558278073067, -13320.17959666297, -14011.216680697647,&
+ -14641.064485129806, -15205.729606667743, -15700.73229569704, -16120.988009589799, -16460.660097272204,&
+ -16712.971999996935, -16869.962353488892, -16922.158491138478, -16858.131158272583, -16663.87228853652,&
+ -16321.9020066657, -15809.948158393034, -15098.926835129132, -14149.734981305983, -12907.943882588346,&
+ -11294.674825193173, -9190.702602022144, -6412.285166757091, -2719.625135131544, 1725.7486051605797,&
+ 5075.570357280889, 6303.236965726065, 6311.308689213137, 5738.523216989048, 4869.776377969901,&
+ 3840.517802950482, 2722.4261903256565, 1557.0071262573574, 370.0825071639013 /)
+
+ vx_vals = (/ -1.7881363897249636, -1.4557883984502726, -1.156060997804968, -0.8826262341182725, -0.6306766463526808,&
+ -0.39648434609471706, -0.1771043981448981, 0.029829355776287328, 0.22624787571920263, 0.41374987397528395,&
+ 0.593676925421294, 0.7671690858121533, 0.9352065525409591, 1.0986410677736123, 1.2582195215272471,&
+ 1.4146013207670218, 1.5683703863689167, 1.7200419936000098, 1.8700639536439956, 2.018810673267073,&
+ 2.166567154019972, 2.3134975098577635, 2.4595881421598746, 2.6045473755237194, 2.7476269752868863,&
+ 2.887297169305302, 3.020633155098777, 3.1421001582731396, 3.2409968929410042, 3.2956517464371733,&
+ 3.258944321014038, 3.0178338199288124, 2.266269894088338, 0.1188793570977499, -4.670611838403899,&
+ -7.705913958835909, -7.065129100690851, -5.869171096482646, -4.854942034406745, -4.045707556870835,&
+ -3.3905881639874065, -2.8468735813783677, -2.3848275102655903, -1.9840874823098817 /)
+
+ vy_vals = (/ -2.0177214801871255, -1.9791936629633469, -1.9299860291676996, -1.872797546680989, -1.8093582465376594,&
+ -1.7407808874103814, -1.6677686265344496, -1.5907413929583842, -1.5099143406166378, -1.4253468581369373,&
+ -1.336972677350458, -1.2446172050773316, -1.1480056254471807, -1.046763726412204, -0.9404123330701931,&
+ -0.8283554145349995, -0.7098611948147097, -0.5840347999758766, -0.4497799653711095, -0.3057459115828185,&
+ -0.150253375238662, 0.01880954943907201, 0.2041365153727788, 0.4092208131111694, 0.6386816134660068,&
+ 0.8987662472656566, 1.1981481061875943, 1.549238258682803, 1.9704183327771712, 2.4899525308718196,&
+ 3.15281994945432, 4.030866097933055, 5.219098885940645, 6.622228821366678, 6.451790636748552,&
+ 2.831587421322512, 0.17939335336194787, -1.0129951079370458, -1.5658613333573939, -1.8379400902624787,&
+ -1.9720085223165467, -2.0310801978159203, -2.0460169879304857, -2.033258466877411 /)
+
+ vz_vals = (/ -1.3210291344261624, -1.3127512448053478, -1.295088324545512, -1.270303371798623, -1.2398896309779226,&
+ -1.2048436755769585, -1.16582872850041, -1.1232753899778807, -1.077445124930075, -1.0284706764948433,&
+ -0.9763815675529588, -0.9211194841506237, -0.8625463570816989, -0.8004467297202226, -0.7345251742451387,&
+ -0.6643988923528821, -0.5895850772951866, -0.5094820144618184, -0.42334214568688194, -0.330234269886702,&
+ -0.22899047184857885, -0.11813088110106348, 0.004244707228824351, 0.1406161975658631, 0.2942834174238068,&
+ 0.4697388279315027, 0.673265149158373, 0.9139295483252248, 1.2053040249394977, 1.568555195973008,&
+ 2.0380885255654477, 2.671016313652558, 3.5517876561479484, 4.663491554019988, 4.8133071746887115,&
+ 2.4267217295309202, 0.5189710551210106, -0.38875158400047516, -0.83502723619936, -1.0718169058177598,&
+ -1.202700104261279, -1.2745047473504847, -1.3106516175956375, -1.3238662484384058 /)
+
+ ! call function to validate the ephemerides
+ call compute_chebys_and_error(degree, nephem, n_lag, t_vals, x_vals, y_vals, z_vals,&
+ vx_vals, vy_vals, vz_vals, avg_error)
+ ! Use large error value due to being a GTO
+ @AssertLessThanOrEqual(avg_error(7),34.0_dp)
+
+ end subroutine test_real_GTO_cheby_generation
+
+end module test_slamInterpolation
+
\ No newline at end of file
diff --git a/pFUnittests/test_slamrandomNumber.pf b/pFUnittests/test_slamrandomNumber.pf
new file mode 100644
index 0000000..f9e90dc
--- /dev/null
+++ b/pFUnittests/test_slamrandomNumber.pf
@@ -0,0 +1,52 @@
+!==============================================================================
+!
+!> @anchor test_slamtime
+!!
+!> @brief Program for testing most important functions and subroutines in randomNumber
+!!
+!> @author Oscar Rodriguez (AC)
+!!
+!> @date
+!! - 28.07.2025 (initial design)
+!!
+!!
+!! @details Program for testing slamRandomNumber functions and subroutines
+!! Sources and Examples are mentioned above every test
+!------------------------------------------------------------------------
+module test_slamrandomNumber
+ use funit
+ use slam_time
+ use iso_fortran_env
+ use ieee_arithmetic
+ use slam_types
+ use slam_randomNumber
+
+
+ implicit none
+
+ contains
+
+ @test
+ subroutine test_randomNumber()
+ implicit None
+ real(dp) :: x_mean, x_sigma, X_random, X_second_random
+ integer :: iIndex
+
+ call initRandomSeed(1)
+
+ x_random = getRandomNumber(RANDOM_NORMAL, 0._dp, 1._dp)
+ ! Check that the random state is not a NAN
+ @assertFalse(ieee_is_nan(X_random))
+
+ ! Check that sucessive calls to random number with the same mean and sigma does not return the same result
+ x_mean=4.0_dp
+ x_sigma=3.0_dp
+ x_random = getRandomNumber(RANDOM_NORMAL, x_mean, x_sigma)
+ X_second_random = getRandomNumber(RANDOM_NORMAL, x_mean, x_sigma)
+ @assertNotEqual(x_random, x_second_random)
+
+ end subroutine
+
+
+
+end module test_slamrandomNumber
\ No newline at end of file
diff --git a/pFUnittests/test_slamstrings.pf b/pFUnittests/test_slamstrings.pf
new file mode 100644
index 0000000..9f8a2e6
--- /dev/null
+++ b/pFUnittests/test_slamstrings.pf
@@ -0,0 +1,42 @@
+!==============================================================================
+!
+!> @anchor test_slamstrings
+!!
+!> @brief Program for testing most important functions and subroutines in test_slamstrings
+!!
+!> @author Oscar Rodriguez (AC)
+!!
+!> @date
+!! - 19.08.2025 (initial design)
+!!
+!!
+!! @details Program for testing slam_time functions and subroutines
+!! Sources and Examples are mentioned above every test
+!------------------------------------------------------------------------
+module test_slamstrings
+ use funit
+ use slam_strings
+ use iso_fortran_env
+ use slam_error_handling
+ use slam_types
+ use slam_math, only: pi, halfPi, twoPi, rad2deg, deg2rad
+
+
+ implicit none
+
+ contains
+ @test
+ subroutine test_intArrayToString()
+ integer, dimension (4) :: iArray
+ iArray=1
+ @assertEqual("[1, 1, 1, 1]", toString(iArray))
+ end subroutine test_intArrayToString
+
+ @test
+ subroutine test_realArrayToString()
+ real(dp), dimension (2) :: rArray
+ rArray=2.5_dp
+ @assertEqual("[2.5000000000000000, 2.5000000000000000]", toString(rArray))
+ end subroutine test_realArrayToString
+
+end module test_slamstrings
\ No newline at end of file
diff --git a/pFUnittests/test_slamtime.pf b/pFUnittests/test_slamtime.pf
index 25a4b91..e4895ce 100644
--- a/pFUnittests/test_slamtime.pf
+++ b/pFUnittests/test_slamtime.pf
@@ -75,7 +75,7 @@ module test_slamtime
! Tests that the date2longstring function correctly converts a time_t object to a long string
type(time_t) :: date
- character(len=LEN_TIME_STRING_LONG) :: date_str
+ character(len=LEN_TIME_STRING_LONG) :: date_str, date_input
date%year = 2021
date%month = 5
@@ -88,8 +88,78 @@ module test_slamtime
@assertEqual('2021-05-03T12:09:05.445566Z', date_str)
+ ! Corner case that failed before fix of leading seconds
+ ! It was giving "2025-02-01T15:49:00.000Z"
+ date_input = "2025-02-01T15:50:00.000Z"
+ call tokenizeDate(date_input, date)
+
+ date_str = date2longstring(date)
+ ! Loss of precision due to use of double precision for MJD
+ @assertEqual("2025-02-01T15:49:59.999982Z", date_str)
+
end subroutine test_date2longstring
-
+
+ @test
+ subroutine test_checktimeformat()
+ ! Test that we are able to properly recognize any ISO8601 compatible time format
+
+
+ character(len=127) :: date_str
+
+ ! good time strings
+ ! No time zone
+ date_str = "2023-01-01T00:00:00"
+ @assertTrue(checkTimeFormat(date_str))
+ date_str = "2023-01-01T00:00:00."
+ @assertTrue(checkTimeFormat(date_str))
+ date_str = "2023-01-01T00:00:00.00"
+ @assertTrue(checkTimeFormat(date_str))
+ ! Zulu timezone
+ date_str = "2023-01-01T00:00:00.000000Z"
+ @assertTrue(checkTimeFormat(date_str))
+ date_str = "2023-01-01T00:00:00.000Z"
+ @assertTrue(checkTimeFormat(date_str))
+ date_str = "2023-01-01T00:00:00Z"
+ @assertTrue(checkTimeFormat(date_str))
+ date_str = "2023-01-01T00:00:00.Z"
+ @assertTrue(checkTimeFormat(date_str))
+ date_str = "2023-01-01T00:00:00.0Z"
+ @assertTrue(checkTimeFormat(date_str))
+ ! Positive Time zone offset
+ date_str = "2023-01-01T00:00:00.000000+01:01"
+ @assertTrue(checkTimeFormat(date_str))
+ date_str = "2023-01-01T00:00:00.000+01:01"
+ @assertTrue(checkTimeFormat(date_str))
+ date_str = "2023-01-01T00:00:00+01:01"
+ @assertTrue(checkTimeFormat(date_str))
+ date_str = "2023-01-01T00:00:00.+01:01"
+ @assertTrue(checkTimeFormat(date_str))
+ date_str = "2023-01-01T00:00:00.0+01:01"
+ @assertTrue(checkTimeFormat(date_str))
+ ! Negative Time zone offset
+ date_str = "2023-01-01T00:00:00.000000-01:01"
+ @assertTrue(checkTimeFormat(date_str))
+ date_str = "2023-01-01T00:00:00.000-01:01"
+ @assertTrue(checkTimeFormat(date_str))
+ date_str = "2023-01-01T00:00:00-01:01"
+ @assertTrue(checkTimeFormat(date_str))
+ date_str = "2023-01-01T00:00:00.-01:01"
+ @assertTrue(checkTimeFormat(date_str))
+ date_str = "2023-01-01T00:00:00.0-01:01"
+ @assertTrue(checkTimeFormat(date_str))
+
+ ! Wrong Formats
+ date_str = "2023-01-01T00:00"
+ @assertFalse(checkTimeFormat(date_str))
+ date_str = "2023-01-01TAA:00:00.Z"
+ @assertFalse(checkTimeFormat(date_str))
+ date_str = "2023-01-01TAA:00:00.-+01:01"
+ @assertFalse(checkTimeFormat(date_str))
+
+ end subroutine test_checktimeformat
+
+
+
@test
subroutine test_gd2jd_std()
! Tests that the gd2jd_std function correctly converts Gregorian dates to Julian dates
@@ -372,5 +442,47 @@ module test_slamtime
@assertRelativelyEqual(expected_delT, DELTAT, tolerance=1.0e-10)
end subroutine test_delta_AT
+
+ @test
+ subroutine test_parseDate
+ implicit none
+ type(time_t) :: date
+ character(:), allocatable :: date_str
+ real(dp), parameter :: tolerance=1e-4
+
+ date_str = "2025-01-01T05:00:00.00Z"
+
+ call parseDateString(date_str, date)
+
+ @assertEqual(2025, date%year)
+ @assertEqual(1, date%month)
+ @assertEqual(1, date%day)
+ @assertEqual(5, date%hour)
+ @assertEqual(0, date%minute)
+ @assertEqual(0._dp, date%second,tolerance=tolerance)
+
+ date_str = "2025-01-01T05:00:10"
+ call parseDateString(date_str, date)
+ @assertEqual(2025, date%year)
+ @assertEqual(1, date%month)
+ @assertEqual(1, date%day)
+ @assertEqual(5, date%hour)
+ @assertEqual(0, date%minute)
+ @assertEqual(10._dp, date%second,tolerance=tolerance)
+
+ date_str = "2025-01-01T05:00:10.0000+02:00"
+ call parseDateString(date_str, date)
+ @assertEqual(2025, date%year)
+ @assertEqual(1, date%month)
+ @assertEqual(1, date%day)
+ @assertEqual(7, date%hour)
+ @assertEqual(0, date%minute)
+ @assertEqual(10._dp, date%second,tolerance=tolerance)
+
+
+
+
+
+ end subroutine
end module test_slamtime
\ No newline at end of file
diff --git a/src/astro/slam_time.f90 b/src/astro/slam_time.f90
index 5b2ab09..d7f71c2 100644
--- a/src/astro/slam_time.f90
+++ b/src/astro/slam_time.f90
@@ -84,6 +84,10 @@ module slam_time
module procedure tokenizeDate_std, tokenizeDate_drv
end interface tokenizeDate
+ interface parseDateString
+ module procedure tokenizeDate_drv
+ end interface
+
interface gd2mjd
module procedure gd2mjd_dt, gd2mjd_std
end interface gd2mjd
@@ -140,6 +144,7 @@ module slam_time
public :: dayFraction2hms
public :: delta_AT
public :: tokenizeDate
+ public :: parseDateString
public :: gd2jd
public :: gd2mjd
public :: is_leap_year
@@ -478,7 +483,8 @@ end subroutine checkdate
!
!> @anchor checkTimeFormat
!> @brief Checks for supported time formats
-!> @returns logical indicating if the time format is valid or not
+!> @returns logical indicating if the time format is valid or not according
+!> to ISO8601 -> YYYY-MM-DDThh:mm:ss[.s+][Z?][[+-]hh:mm]
!---------------------------------------------------
logical function checkTimeFormat(check)
@@ -486,9 +492,29 @@ logical function checkTimeFormat(check)
integer :: ctest
integer :: i ! counter
+ integer :: decimal_pos ! position of decimal point
+ integer :: tz_pos ! position of timezone indicator
+ integer :: str_len ! Len of trimed str
!** initialise
checkTimeFormat = .false.
+ tz_pos =0
+ decimal_pos=0
+ str_len = len_trim(check)
+ if (str_len < 19) return
+
+ decimal_pos = index(check, '.')
+ tz_pos = max(index(check, 'Z'), index(check, '+', .true.), index(check, '-', .true.))
+
+ ! If timezone indicator found but it's part of the date (position 5 or 8), ignore it
+ if (tz_pos == 5 .or. tz_pos == 8) then
+ if (str_len>19) then
+ tz_pos = max(index(check(20:), '+'), index(check(20:), '-'))
+ if (tz_pos > 0) tz_pos = tz_pos + 19
+ else
+ tz_pos=0
+ end if
+ end if
do i=1,len_trim(check)
ctest = ichar(check(i:i))
@@ -517,26 +543,44 @@ logical function checkTimeFormat(check)
!** not a ':'
return
end if
- !** checking 'Z'
- else if(i == 20) then
- !** check if there is a time zone designator
- if(len_trim(check) > 20) then
- if((ctest /= 43).and.(ctest /= 45).and.(ctest /= 46)) then
- !** not a '+' or a '-' or a '.'
- return
+ else if (i==decimal_pos) then
+ if(ctest /= 46) then
+ !** not a '.'
+ return
end if
- else
- if(ctest /= 90) then
- !** not a 'Z'
- return
+ !** checking fractional seconds part
+ else if (decimal_pos > 0 .and. i > decimal_pos .and. &
+ (tz_pos == 0 .or. i < tz_pos)) then
+ if((ctest < 48).or.(ctest > 57)) then
+ !** not a digit in fractional seconds
+ return
end if
- end if
- !** checking '+/-hh:mm'
- else if((i == 21).or.(i == 22).or.(i == 24).or.(i == 25)) then ! hh
- if((ctest < 48).or.(ctest > 57)) then
- !** not a digit
- return
- end if
+
+ ! ** checking timezone or offset (+-HH:MM)
+ else if (tz_pos > 0 .and. i >= tz_pos) then
+ if (i == tz_pos) then
+ ! Should be Z, + or -
+ if((ctest /= 43).and.(ctest /= 45).and.(ctest /= 90)) then
+ return
+ end if
+ else if (ctest == 90) then ! 'Z'
+ ! Z should be the last character
+ if (i /= str_len) return
+ else if ((i == tz_pos + 1) .or. (i == tz_pos + 2) .or. &
+ (i == tz_pos + 4) .or. (i == tz_pos + 5)) then
+ ! Hours and minutes in timezone offset
+ if((ctest < 48).or.(ctest > 57)) then
+ return
+ end if
+ else if (i == tz_pos + 3) then
+ ! Colon in timezone offset
+ if(ctest /= 58) then
+ return
+ end if
+ else
+ ! Invalid character in timezone
+ return
+ end if
end if
end do
@@ -616,15 +660,15 @@ character(len=LEN_TIME_STRING_LONG) function date2longstring(date)
end if
! Handle the leading zero issue for floating point numbers (only for the seconds)
- second_fraction = anint((date%second-int(date%second))*1.0d6)/1.0d6
call mjd2gd(tmp_date)
+ second_fraction = anint((tmp_date%second-int(tmp_date%second))*1.0d6)/1.0d6
if (second_fraction > 0.999999d0) then
! Handle rounding to the next second using mjd2gd subroutine
second_fraction = 0.0d0
- tmp_date%mjd = tmp_date%mjd + 1E-6/sec_per_day
+ tmp_date%mjd = tmp_date%mjd + 1.0E-6_dp/sec_per_day
call mjd2gd(tmp_date)
end if
-
+
! Return date string with microseconds and a trailing Z for UTC
write(date2longstring,'(i4,2("-",i2.2),"T",2(i2.2,":"),i2.2,f0.6,"Z")') &
tmp_date%year, tmp_date%month, tmp_date%day, tmp_date%hour, &
@@ -2443,7 +2487,7 @@ subroutine tokenizeDate_std(cin, yr, mo, dy, hr, mi, sc)
!** locals
character(len=*), parameter :: csubid = 'tokenizeDate_std'
- character(len=25) :: ctime
+ character(len=len(cin)) :: ctime
integer :: hr_add ! hours to add to get UTC
integer :: mi_add ! minutes to add to get UTC
integer :: zone_index ! pointer to the + or - sign
@@ -2451,6 +2495,7 @@ subroutine tokenizeDate_std(cin, yr, mo, dy, hr, mi, sc)
integer :: zulu_index ! pointer to the Z at the end
integer :: last_index ! length of the string
integer :: fraction_end_index ! points to the list fraction of the second + 1
+ integer :: subsecond_precision ! total subsecond decimals
real(dp) :: second_fraction ! milliseconds in the iso datetune
real(dp) :: jd ! temporary julian day
@@ -2485,8 +2530,9 @@ subroutine tokenizeDate_std(cin, yr, mo, dy, hr, mi, sc)
fraction_end_index = last_index + 1
if (zulu_index /= 0) fraction_end_index = zulu_index
if (zone_index /= 0) fraction_end_index = zone_index
+ subsecond_precision= fraction_end_index-decimal_index
read(ctime(decimal_index+1:fraction_end_index-1),*) second_fraction
- sc = sc + second_fraction / 1000.d0
+ sc = sc + second_fraction / 10.0_dp**subsecond_precision
end if
!** correct time zone
@@ -2495,7 +2541,7 @@ subroutine tokenizeDate_std(cin, yr, mo, dy, hr, mi, sc)
read(ctime(zone_index+1:zone_index+2),*) hr_add
! Check for the minute correction
- if (index(ctime,':',.true.) > 20) read(ctime(zone_index+3:zone_index+4),*) mi_add
+ if (index(ctime,':',.true.) > 20) read(ctime(zone_index+4:zone_index+5),*) mi_add
call gd2jd(yr, mo, dy, hr, mi, sc, jd)
diff --git a/src/inout/slam_strings.f90 b/src/inout/slam_strings.f90
index b9fab2c..9cbfd54 100644
--- a/src/inout/slam_strings.f90
+++ b/src/inout/slam_strings.f90
@@ -55,7 +55,8 @@ module slam_strings
public :: replace_text
interface toString
- module procedure boolToString, intToString, int8ToString, realToString
+ module procedure boolToString, intToString, int8ToString, realToString, &
+ intArrayToString, realArrayToString
end interface toString
contains
@@ -435,4 +436,77 @@ function string_to_boolean(cValue) result(bValue)
end function string_to_boolean
+ !=========================================================================
+ !!
+ !> @anchor intArrayToString
+ !!
+ !> @brief Converts an integer array to a string
+ !> @author Oscar Rodriguez (OR)
+ !!
+ !! @details Converts a given integer array to a string format [val1, val2, val3, ...]
+ !!
+ !> @param[in] iArray integer array to be converted
+ !!
+ !! @return cvalue the converted array as character string
+ !!
+ !> @date
+ !! - 19.08.2025 (initial implementation)
+ !!
+ !!
+ !-------------------------------------------------------------------------
+ function intArrayToString(iArray) result(cvalue)
+ integer, intent(in) :: iArray(:)
+ character(:), allocatable :: cvalue
+ character(:), allocatable :: ctmp
+ integer :: i
+
+ ctmp = '['
+ do i = 1, size(iArray)
+ if (i > 1) then
+ ctmp = ctmp // ', '
+ end if
+ ctmp = ctmp // toString(iArray(i))
+ end do
+ ctmp = ctmp // ']'
+ cvalue = ctmp
+
+ end function intArrayToString
+
+ !=========================================================================
+ !!
+ !> @anchor realArrayToString
+ !!
+ !> @brief Converts a real array to a string
+ !> @author Oscar Rodriguez (OR)
+ !!
+ !! @details Converts a given real(dp) array to a string format [val1, val2, val3, ...]
+ !!
+ !> @param[in] rArray real(dp) array to be converted
+ !!
+ !! @return cvalue the converted array as character string
+ !!
+ !> @date
+ !! - 19.08.2025 (initial implementation)
+ !!
+ !!
+ !-------------------------------------------------------------------------
+ function realArrayToString(rArray) result(cvalue)
+ use slam_types, only: dp
+ real(dp), intent(in) :: rArray(:)
+ character(:), allocatable :: cvalue
+ character(:), allocatable :: ctmp
+ integer :: i
+
+ ctmp = '['
+ do i = 1, size(rArray)
+ if (i > 1) then
+ ctmp = ctmp // ', '
+ end if
+ ctmp = ctmp // toString(rArray(i))
+ end do
+ ctmp = ctmp // ']'
+ cvalue = ctmp
+
+ end function realArrayToString
+
end module slam_strings
diff --git a/src/math/slam_randomNumber.f90 b/src/math/slam_randomNumber.f90
index 0a58ff1..8d1fd2b 100644
--- a/src/math/slam_randomNumber.f90
+++ b/src/math/slam_randomNumber.f90
@@ -179,8 +179,9 @@ end subroutine initRandomSeed
!!------------------------------------------------------------------------------------------------
real(dp) function getRandomNumber(iopt, xmean, xsigma)
-
+ use ieee_arithmetic
implicit none
+
integer, intent(in) :: iopt
real(dp), intent(in) :: xmean
@@ -195,8 +196,8 @@ real(dp) function getRandomNumber(iopt, xmean, xsigma)
real(dp), dimension(2:3),save :: otherNumber ! storing the second generated random number for normal (=2) and log-normal (=3) distributions
real(dp), save :: xmean_prev, xsigma_prev ! mean and st. dev. from previous call, 'otherNumber' is only returned if these values are equal
! to xmean and xsigma
-
-
+ ! Initialize to NAN, to help catching issues
+ getRandomNumber=ieee_value(getRandomNumber, ieee_quiet_nan)
!** initialize if not done yet...
if(.not. initialized) then
@@ -211,19 +212,13 @@ real(dp) function getRandomNumber(iopt, xmean, xsigma)
getRandomNumber = xmean + getRandomNumber*(xsigma - xmean)
else if(iopt == RANDOM_NORMAL .or. iopt == RANDOM_LOG_NORMAL) then
-
+
!** check if there is already a number available
- if(isOtherNumber(iopt)) then
- if ((xmean_prev == xmean) .and. (xsigma_prev == xsigma)) then
-
+ if(isOtherNumber(iopt) .and. (xmean_prev == xmean) .and. (xsigma_prev == xsigma)) then
getRandomNumber = otherNumber(iopt)
isOtherNumber(iopt) = .false.
- end if
-
else !** generate two new numbers
-
do
-
call random_number(ran1)
call random_number(ran2)
v1 = 2.d0*ran1 - 1.d0
@@ -258,7 +253,6 @@ real(dp) function getRandomNumber(iopt, xmean, xsigma)
end if
end if
-
return
end function getRandomNumber