From 4d7c2a30d0433acc540d676739df639bdfd4b883 Mon Sep 17 00:00:00 2001 From: Luis Manuel Diaz Angulo Date: Fri, 22 May 2026 11:20:41 +0000 Subject: [PATCH 1/2] Increasing test coverage for wired --- CMakeLists.txt | 10 ++ external/ngspice | 2 +- src_wires_pub/wires.F90 | 19 ++-- test/CMakeLists.txt | 3 + test/fdtd_tests.cpp | 1 + test/preprocess/preprocess_tests.h | 15 +++ test/preprocess/test_preprocess_geom.F90 | 120 +++++++++++++++++++++++ test/pyWrapper/utils.py | 9 +- 8 files changed, 170 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 06c3cadbc..285989629 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ option(SEMBA_FDTD_ENABLE_SMBJSON "Use smbjson" ON) option(SEMBA_FDTD_ENABLE_DOUBLE_PRECISION "Use double precision (CompileWithReal8)" OFF) option(SEMBA_FDTD_ENABLE_TEST "Compile tests" ON) +option(SEMBA_FDTD_ENABLE_COVERAGE "Enable gcov coverage instrumentation (GNU only)" OFF) option(SEMBA_FDTD_ENABLE_INTEL_XHOST_OPTIMIZATION "When compiling in Release, enables the -xHost optimization flag (not supported in github actions)" OFF) option(SEMBA_FDTD_ENABLE_INTEL_IPO "When compiling in Release, enables the interprocedural optimization" OFF) @@ -68,6 +69,15 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") set(CMAKE_CXX_FLAGS_DEBUG "-g -O0") set(CMAKE_Fortran_FLAGS_DEBUG "-g -O0 -fno-inline -fcheck=all -fbacktrace") + if(SEMBA_FDTD_ENABLE_COVERAGE) + message(STATUS "Enabling coverage instrumentation") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} --coverage") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage") + endif() + elseif(CMAKE_Fortran_COMPILER_ID MATCHES "IntelLLVM") message(STATUS "Using IntelLLVM (ifx) flags") diff --git a/external/ngspice b/external/ngspice index 909c2731f..d4a8166e2 160000 --- a/external/ngspice +++ b/external/ngspice @@ -1 +1 @@ -Subproject commit 909c2731f3bb67742bdeeeb0c6e7d296ac76fd8b +Subproject commit d4a8166e2b6f8dccd12775fe00958eb4d32685e3 diff --git a/src_wires_pub/wires.F90 b/src_wires_pub/wires.F90 index 288c5fdbf..3ef514903 100755 --- a/src_wires_pub/wires.F90 +++ b/src_wires_pub/wires.F90 @@ -33,7 +33,7 @@ module HollandWires_m !!! private - public InitWires,AdvanceWiresE,AdvanceWiresH,AdvanceWiresEcrank,StoreFieldsWires,DestroyWires, GetHwires,ReportWireJunctions,calc_wirehollandconstants + public InitWires,AdvanceWiresE,AdvanceWiresH,AdvanceWiresEcrank,StoreFieldsWires,DestroyWires,DestroyWireMedia, GetHwires,ReportWireJunctions,calc_wirehollandconstants @@ -5831,11 +5831,7 @@ subroutine DestroyWires(sgg) !free up memory !ojo no se como hacerlo do i=1,sgg%NumMedia - if (sgg%Med(i)%Is%ThinWire) then - if (associated(sgg%Med(i)%wire(1)%Vsource)) deallocate(sgg%Med(i)%wire(1)%Vsource) - if (associated(sgg%Med(i)%wire(1)%Isource)) deallocate(sgg%Med(i)%wire(1)%Isource) - if (associated(sgg%Med(i)%wire)) deallocate(sgg%Med(i)%wire) - end if + call DestroyWireMedia(sgg%Med(i)) end do if (associated(HWires%WireTipoMedio )) deallocate(HWires%WireTipoMedio ) @@ -5847,6 +5843,17 @@ subroutine DestroyWires(sgg) #endif end subroutine + subroutine DestroyWireMedia(media) + type(MediaData_t), intent(inout) :: media + + if (.not. media%Is%ThinWire) return + if (.not. associated(media%Wire)) return + + if (associated(media%wire(1)%Vsource)) deallocate(media%wire(1)%Vsource) + if (associated(media%wire(1)%Isource)) deallocate(media%wire(1)%Isource) + if (associated(media%wire)) deallocate(media%wire) + end subroutine + !!!!!!!!!!!!!!!!!!!!!!!!!!!! !Function to publish the private wire data (used in observation and in MPI) !!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1cf9378ed..a9858a6f2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -23,6 +23,8 @@ if (SEMBA_FDTD_ENABLE_SMBJSON) set(ROTATE_TESTS_LIBRARY rotate_tests) add_subdirectory(vtk) set(VTK_TESTS_LIBRARY vtk_tests) + add_subdirectory(wires) + set(WIRES_TESTS_LIBRARY wires_tests) if (NOT SEMBA_FDTD_ENABLE_MPI) add_subdirectory(observation) set(OBSERVATION_TESTS_LIBRARY observation_tests) @@ -47,6 +49,7 @@ target_link_libraries(fdtd_tests ${ROTATE_TESTS_LIBRARY} ${HDF_TESTS_LIBRARY} ${VTK_TESTS_LIBRARY} + ${WIRES_TESTS_LIBRARY} ${SYSTEM_TESTS_LIBRARY} ${OBSERVATION_TESTS_LIBRARY} GTest::gtest_main diff --git a/test/fdtd_tests.cpp b/test/fdtd_tests.cpp index 8c9aee1cc..432154923 100644 --- a/test/fdtd_tests.cpp +++ b/test/fdtd_tests.cpp @@ -8,6 +8,7 @@ #include "smbjson/smbjson_tests.h" #include "rotate/rotate_tests.h" #include "vtk/vtk_tests.h" + #include "wires/wires_tests.h" #endif #ifndef CompileWithMPI #include "observation/observation_tests.h" diff --git a/test/preprocess/preprocess_tests.h b/test/preprocess/preprocess_tests.h index 992219a3f..e451b6e48 100644 --- a/test/preprocess/preprocess_tests.h +++ b/test/preprocess/preprocess_tests.h @@ -10,7 +10,10 @@ extern "C" { int test_searchtag_single(); int test_searchtag_special_chars(); int test_checkDielectricTag_no_dup(); + int test_checkDielectricTag_c2P_duplicate_current(); int test_checkLossyTag_basic(); + int test_checkLossyTag_duplicate_current(); + int test_checkLossyTag_duplicate_previous(); } // Test cases following the conformal_tests.h pattern @@ -34,8 +37,20 @@ TEST(preprocess, checkDielectricTag_no_dup) { EXPECT_EQ(0, test_checkDielectricTag_no_dup()); } +TEST(preprocess, checkDielectricTag_c2P_duplicate_current) { + EXPECT_EQ(0, test_checkDielectricTag_c2P_duplicate_current()); +} + TEST(preprocess, checkLossyTag_basic) { EXPECT_EQ(0, test_checkLossyTag_basic()); } +TEST(preprocess, checkLossyTag_duplicate_current) { + EXPECT_EQ(0, test_checkLossyTag_duplicate_current()); +} + +TEST(preprocess, checkLossyTag_duplicate_previous) { + EXPECT_EQ(0, test_checkLossyTag_duplicate_previous()); +} + #endif // PREPROCESS_TESTS_H diff --git a/test/preprocess/test_preprocess_geom.F90 b/test/preprocess/test_preprocess_geom.F90 index 9868d0ae3..d52d58632 100644 --- a/test/preprocess/test_preprocess_geom.F90 +++ b/test/preprocess/test_preprocess_geom.F90 @@ -306,3 +306,123 @@ integer function test_checkLossyTag_basic() bind(C, name="test_checkLossyTag_bas print *, 'test_checkLossyTag_basic PASSED' end if end function test_checkLossyTag_basic + +! Test checkDielectricTagForDuplicate - duplicate in current c2P list +integer function test_checkDielectricTag_c2P_duplicate_current() bind(C, name="test_checkDielectricTag_c2P_duplicate_current") result(status) + use, intrinsic :: iso_c_binding + use FDETYPES_m + use NFDETypes_m + use Preprocess_m + implicit none + type(Dielectric_t) :: diel_comp, prev_diel(1) + type(tagtype_t) :: tagtype + integer(c_int) :: numertag + character(len=100) :: error_msg + + status = 0 + + diel_comp%n_c1P = 0 + diel_comp%n_c2P = 2 + allocate(diel_comp%c2P(2)) + diel_comp%c2P(1)%tag = 'shared_tag' + diel_comp%c2P(2)%tag = 'shared_tag' + + prev_diel(1)%n_c1P = 0 + prev_diel(1)%n_c2P = 0 + + tagtype%numertags = 0 + allocate(tagtype%tag(10)) + + numertag = 2 + error_msg = 'Error in dielectric tag check' + call checkDielectricTagForDuplicate(diel_comp, prev_diel, 0, 2, 'c2P', numertag, tagtype, 1, error_msg) + if (numertag /= 1) then + print *, 'test_checkDielectricTag_c2P_duplicate_current FAILED: Expected numertag=1, got', numertag + status = 1 + end if + + deallocate(diel_comp%c2P) + deallocate(tagtype%tag) + + if (status == 0) then + print *, 'test_checkDielectricTag_c2P_duplicate_current PASSED' + end if +end function test_checkDielectricTag_c2P_duplicate_current + +! Test checkLossyTagForDuplicate - duplicate in current component list +integer function test_checkLossyTag_duplicate_current() bind(C, name="test_checkLossyTag_duplicate_current") result(status) + use, intrinsic :: iso_c_binding + use FDETYPES_m + use NFDETypes_m + use Preprocess_m + implicit none + type(LossyThinSurface_t) :: lossy_comp, prev_lossy(1) + type(tagtype_t) :: tagtype + integer(c_int) :: numertag + + status = 0 + + lossy_comp%nc = 2 + allocate(lossy_comp%C(2)) + lossy_comp%C(1)%tag = 'dup_lossy' + lossy_comp%C(2)%tag = 'dup_lossy' + + prev_lossy(1)%nc = 0 + + tagtype%numertags = 0 + allocate(tagtype%tag(10)) + + numertag = 2 + call checkLossyTagForDuplicate(lossy_comp, prev_lossy, 0, 2, numertag, tagtype, 1) + if (numertag /= 1) then + print *, 'test_checkLossyTag_duplicate_current FAILED: Expected numertag=1, got', numertag + status = 1 + end if + + deallocate(lossy_comp%C) + deallocate(tagtype%tag) + + if (status == 0) then + print *, 'test_checkLossyTag_duplicate_current PASSED' + end if +end function test_checkLossyTag_duplicate_current + +! Test checkLossyTagForDuplicate - duplicate against previous components +integer function test_checkLossyTag_duplicate_previous() bind(C, name="test_checkLossyTag_duplicate_previous") result(status) + use, intrinsic :: iso_c_binding + use FDETYPES_m + use NFDETypes_m + use Preprocess_m + implicit none + type(LossyThinSurface_t) :: lossy_comp, prev_lossy(1) + type(tagtype_t) :: tagtype + integer(c_int) :: numertag + + status = 0 + + lossy_comp%nc = 1 + allocate(lossy_comp%C(1)) + lossy_comp%C(1)%tag = 'prev_dup' + + prev_lossy(1)%nc = 1 + allocate(prev_lossy(1)%C(1)) + prev_lossy(1)%C(1)%tag = 'prev_dup' + + tagtype%numertags = 0 + allocate(tagtype%tag(10)) + + numertag = 1 + call checkLossyTagForDuplicate(lossy_comp, prev_lossy, 1, 1, numertag, tagtype, 1) + if (numertag /= 0) then + print *, 'test_checkLossyTag_duplicate_previous FAILED: Expected numertag=0, got', numertag + status = 1 + end if + + deallocate(lossy_comp%C) + deallocate(prev_lossy(1)%C) + deallocate(tagtype%tag) + + if (status == 0) then + print *, 'test_checkLossyTag_duplicate_previous PASSED' + end if +end function test_checkLossyTag_duplicate_previous diff --git a/test/pyWrapper/utils.py b/test/pyWrapper/utils.py index 1d0f668fc..ff45bb0c0 100644 --- a/test/pyWrapper/utils.py +++ b/test/pyWrapper/utils.py @@ -33,8 +33,13 @@ ) # Use of absolute path to avoid conflicts when changing directory. -if platform == "linux": - SEMBA_EXE = os.path.join(os.getcwd(), 'build', 'bin', 'semba-fdtd') +# Check environment variable first, then fall back to build detection. +if "SEMBA_FDTD_EXECUTABLE" in os.environ: + SEMBA_EXE = os.environ["SEMBA_FDTD_EXECUTABLE"] +elif platform == "linux": + SEMBA_EXE = os.path.join(os.getcwd(), 'build-dbg', 'bin', 'semba-fdtd') + if not os.path.isfile(SEMBA_EXE): + SEMBA_EXE = os.path.join(os.getcwd(), 'build', 'bin', 'semba-fdtd') elif platform == "win32": SEMBA_EXE = os.path.join(os.getcwd(), 'build', 'bin', 'semba-fdtd.exe') From 6d5ea96a6c903a953ae8fe5b88691d0c503e6acc Mon Sep 17 00:00:00 2001 From: Luis Manuel Diaz Angulo Date: Tue, 26 May 2026 11:07:08 +0000 Subject: [PATCH 2/2] More tests --- .gitignore | 2 + src_main_pub/healer.F90 | 2 +- src_main_pub/maloney_nostoch.F90 | 1 + src_wires_pub/wires.F90 | 2 +- test/CMakeLists.txt | 8 + test/fdtd_tests.cpp | 2 + test/healer/CMakeLists.txt | 20 +++ test/healer/healer_tests.cpp | 1 + test/healer/healer_tests.h | 39 +++++ test/healer/test_healer.F90 | 199 ++++++++++++++++++++++ test/observation/observation_tests.h | 2 + test/observation/test_preprocess.F90 | 43 +++++ test/pyWrapper/conftest.py | 7 + test/sgbc/CMakeLists.txt | 18 ++ test/sgbc/sgbc_tests.cpp | 1 + test/sgbc/sgbc_tests.h | 24 +++ test/sgbc/test_sgbc.F90 | 98 +++++++++++ test/wires/CMakeLists.txt | 20 +++ test/wires/test_wires.F90 | 243 +++++++++++++++++++++++++++ test/wires/wires_tests.cpp | 2 + test/wires/wires_tests.h | 59 +++++++ 21 files changed, 791 insertions(+), 2 deletions(-) create mode 100644 test/healer/CMakeLists.txt create mode 100644 test/healer/healer_tests.cpp create mode 100644 test/healer/healer_tests.h create mode 100644 test/healer/test_healer.F90 create mode 100644 test/pyWrapper/conftest.py create mode 100644 test/sgbc/CMakeLists.txt create mode 100644 test/sgbc/sgbc_tests.cpp create mode 100644 test/sgbc/sgbc_tests.h create mode 100644 test/sgbc/test_sgbc.F90 create mode 100644 test/wires/CMakeLists.txt create mode 100644 test/wires/test_wires.F90 create mode 100644 test/wires/wires_tests.cpp create mode 100644 test/wires/wires_tests.h diff --git a/.gitignore b/.gitignore index d959ecee5..b1c0b962a 100755 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,5 @@ git_info.txt .venv/build2/ build2/ + +.venv/ \ No newline at end of file diff --git a/src_main_pub/healer.F90 b/src_main_pub/healer.F90 index 187e976c7..5712722a6 100755 --- a/src_main_pub/healer.F90 +++ b/src_main_pub/healer.F90 @@ -28,7 +28,7 @@ module CreateMatrices_m & 0, 0,-1, 0, 0, 0,-1,-1, 0,-1, 0,-1, 0,-1, 0, 0, & -1,-1,-1, 0 /), (/ 6, 3, 2 /)) ! - public CreatePMLmatrix, Readjust + public CreatePMLmatrix, Readjust, SortInitEndWithIncreasingOrder public CreateVolumeMM, CreateSurfaceMM, CreateLineMM public CreateSurfaceSlotMM,CreateMagneticSurface public CreateConformalPECVolume diff --git a/src_main_pub/maloney_nostoch.F90 b/src_main_pub/maloney_nostoch.F90 index 10226019d..eb3d15d9b 100755 --- a/src_main_pub/maloney_nostoch.F90 +++ b/src_main_pub/maloney_nostoch.F90 @@ -87,6 +87,7 @@ module SGBC_nostoch_m !!! public Malon_t,SGBCSurface_t !el tipo es publico public AdvanceSGBCE,AdvanceSGBCH,InitSGBCs,DestroySGBCs,StoreFieldsSGBCs,calc_SGBCconstants,GetSGBCs +public solve_tridiag_iguales contains diff --git a/src_wires_pub/wires.F90 b/src_wires_pub/wires.F90 index 3ef514903..a76e6952b 100755 --- a/src_wires_pub/wires.F90 +++ b/src_wires_pub/wires.F90 @@ -33,7 +33,7 @@ module HollandWires_m !!! private - public InitWires,AdvanceWiresE,AdvanceWiresH,AdvanceWiresEcrank,StoreFieldsWires,DestroyWires,DestroyWireMedia, GetHwires,ReportWireJunctions,calc_wirehollandconstants + public InitWires,AdvanceWiresE,AdvanceWiresH,AdvanceWiresEcrank,StoreFieldsWires,DestroyWires,DestroyWireMedia, GetHwires,ReportWireJunctions,calc_wirehollandconstants,evolucion diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a9858a6f2..3a367b621 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -37,6 +37,12 @@ set(CONFORMAL_TESTS_LIBRARY conformal_tests) add_subdirectory(preprocess) set(PREPROCESS_TESTS_LIBRARY preprocess_tests) +add_subdirectory(healer) +set(HEALER_TESTS_LIBRARY healer_tests) + +add_subdirectory(sgbc) +set(SGBC_TESTS_LIBRARY sgbc_tests) + add_executable(fdtd_tests "fdtd_tests.cpp" ) @@ -52,5 +58,7 @@ target_link_libraries(fdtd_tests ${WIRES_TESTS_LIBRARY} ${SYSTEM_TESTS_LIBRARY} ${OBSERVATION_TESTS_LIBRARY} + ${HEALER_TESTS_LIBRARY} + ${SGBC_TESTS_LIBRARY} GTest::gtest_main ) \ No newline at end of file diff --git a/test/fdtd_tests.cpp b/test/fdtd_tests.cpp index 432154923..7d73bdc69 100644 --- a/test/fdtd_tests.cpp +++ b/test/fdtd_tests.cpp @@ -15,6 +15,8 @@ #endif #include "conformal/conformal_tests.h" #include "preprocess/preprocess_tests.h" +#include "healer/healer_tests.h" +#include "sgbc/sgbc_tests.h" int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); diff --git a/test/healer/CMakeLists.txt b/test/healer/CMakeLists.txt new file mode 100644 index 000000000..a77c9807b --- /dev/null +++ b/test/healer/CMakeLists.txt @@ -0,0 +1,20 @@ +message(STATUS "Creating build system for test/healer") + +set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/mod) + +add_library(healer_test_fortran + "test_healer.F90" +) + +target_link_libraries(healer_test_fortran + semba-main + semba-reports + fhash +) + +add_library(healer_tests "healer_tests.cpp") + +target_link_libraries(healer_tests + healer_test_fortran + GTest::gtest +) diff --git a/test/healer/healer_tests.cpp b/test/healer/healer_tests.cpp new file mode 100644 index 000000000..e54c04fe9 --- /dev/null +++ b/test/healer/healer_tests.cpp @@ -0,0 +1 @@ +#include "healer_tests.h" diff --git a/test/healer/healer_tests.h b/test/healer/healer_tests.h new file mode 100644 index 000000000..f93401edd --- /dev/null +++ b/test/healer/healer_tests.h @@ -0,0 +1,39 @@ +#ifndef HEALER_TESTS_H +#define HEALER_TESTS_H + +#include + +extern "C" { + int test_sort_all_swapped(); + int test_sort_already_ordered(); + int test_sort_x_reversed_yz_ok(); + int test_readjust_grow(); + int test_readjust_shrink(); + int test_readjust_same_size(); +} + +TEST(healer, sort_all_swapped) { + EXPECT_EQ(0, test_sort_all_swapped()); +} + +TEST(healer, sort_already_ordered) { + EXPECT_EQ(0, test_sort_already_ordered()); +} + +TEST(healer, sort_x_reversed_yz_ok) { + EXPECT_EQ(0, test_sort_x_reversed_yz_ok()); +} + +TEST(healer, readjust_grow) { + EXPECT_EQ(0, test_readjust_grow()); +} + +TEST(healer, readjust_shrink) { + EXPECT_EQ(0, test_readjust_shrink()); +} + +TEST(healer, readjust_same_size) { + EXPECT_EQ(0, test_readjust_same_size()); +} + +#endif // HEALER_TESTS_H diff --git a/test/healer/test_healer.F90 b/test/healer/test_healer.F90 new file mode 100644 index 000000000..0c051440a --- /dev/null +++ b/test/healer/test_healer.F90 @@ -0,0 +1,199 @@ +! Unit tests for src_main_pub/healer.F90 +! Tests SortInitEndWithIncreasingOrder and Readjust. + +integer function test_sort_all_swapped() bind(C, name="test_sort_all_swapped") result(status) + use CreateMatrices_m, only: SortInitEndWithIncreasingOrder + use FDETYPES_m, only: XYZlimit_t + implicit none + type(XYZlimit_t) :: p + + status = 0 + p%XI = 10; p%XE = 5 + p%YI = 20; p%YE = 2 + p%ZI = 15; p%ZE = 3 + + call SortInitEndWithIncreasingOrder(p) + + if (p%XI /= 5 .or. p%XE /= 10) then + print *, "test_sort_all_swapped FAILED: X not sorted" + status = 1 + end if + if (p%YI /= 2 .or. p%YE /= 20) then + print *, "test_sort_all_swapped FAILED: Y not sorted" + status = 1 + end if + if (p%ZI /= 3 .or. p%ZE /= 15) then + print *, "test_sort_all_swapped FAILED: Z not sorted" + status = 1 + end if +end function test_sort_all_swapped + +integer function test_sort_already_ordered() bind(C, name="test_sort_already_ordered") result(status) + use CreateMatrices_m, only: SortInitEndWithIncreasingOrder + use FDETYPES_m, only: XYZlimit_t + implicit none + type(XYZlimit_t) :: p + + status = 0 + p%XI = 1; p%XE = 5 + p%YI = 2; p%YE = 20 + p%ZI = 3; p%ZE = 15 + + call SortInitEndWithIncreasingOrder(p) + + if (p%XI /= 1 .or. p%XE /= 5) then + print *, "test_sort_already_ordered FAILED: X changed unexpectedly" + status = 1 + end if + if (p%YI /= 2 .or. p%YE /= 20) then + print *, "test_sort_already_ordered FAILED: Y changed unexpectedly" + status = 1 + end if + if (p%ZI /= 3 .or. p%ZE /= 15) then + print *, "test_sort_already_ordered FAILED: Z changed unexpectedly" + status = 1 + end if +end function test_sort_already_ordered + +integer function test_sort_x_reversed_yz_ok() bind(C, name="test_sort_x_reversed_yz_ok") result(status) + use CreateMatrices_m, only: SortInitEndWithIncreasingOrder + use FDETYPES_m, only: XYZlimit_t + implicit none + type(XYZlimit_t) :: p + + status = 0 + p%XI = 9; p%XE = 1 ! reversed + p%YI = 3; p%YE = 7 ! already ordered + p%ZI = 4; p%ZE = 4 ! equal + + call SortInitEndWithIncreasingOrder(p) + + if (p%XI /= 1 .or. p%XE /= 9) then + print *, "test_sort_x_reversed_yz_ok FAILED: X not sorted" + status = 1 + end if + if (p%YI /= 3 .or. p%YE /= 7) then + print *, "test_sort_x_reversed_yz_ok FAILED: Y changed unexpectedly" + status = 1 + end if + if (p%ZI /= 4 .or. p%ZE /= 4) then + print *, "test_sort_x_reversed_yz_ok FAILED: Z changed unexpectedly" + status = 1 + end if +end function test_sort_x_reversed_yz_ok + +integer function test_readjust_grow() bind(C, name="test_readjust_grow") result(status) + use CreateMatrices_m, only: Readjust + use FDETYPES_m, only: MediaData_t, set_priorities + implicit none + type(MediaData_t), pointer, dimension(:) :: med + integer(kind=4) :: numMedia, newNumMedia + + status = 0 + call set_priorities(.false., .false., .false.) + + numMedia = 2 + newNumMedia = 5 + allocate(med(0:numMedia)) + med(0)%Epr = 1.0 + med(1)%Epr = 2.0 + med(2)%Epr = 3.0 + + call Readjust(numMedia, med, newNumMedia) + + if (numMedia /= 5) then + print *, "test_readjust_grow FAILED: NumMedia not updated, got", numMedia + status = 1 + end if + if (size(med) /= 6) then ! 0:5 = 6 elements + print *, "test_readjust_grow FAILED: med size wrong, got", size(med) + status = 1 + end if + ! Original entries preserved + if (med(0)%Epr /= 1.0 .or. med(1)%Epr /= 2.0 .or. med(2)%Epr /= 3.0) then + print *, "test_readjust_grow FAILED: original entries corrupted" + status = 1 + end if + ! New entries initialised to sentinel -1 + if (med(3)%Epr /= -1.0 .or. med(4)%Epr /= -1.0 .or. med(5)%Epr /= -1.0) then + print *, "test_readjust_grow FAILED: new entries not initialised to -1" + status = 1 + end if + + deallocate(med) +end function test_readjust_grow + +integer function test_readjust_shrink() bind(C, name="test_readjust_shrink") result(status) + use CreateMatrices_m, only: Readjust + use FDETYPES_m, only: MediaData_t, set_priorities + implicit none + type(MediaData_t), pointer, dimension(:) :: med + integer(kind=4) :: numMedia, newNumMedia + + status = 0 + call set_priorities(.false., .false., .false.) + + numMedia = 5 + newNumMedia = 2 + allocate(med(0:numMedia)) + med(0)%Epr = 10.0 + med(1)%Epr = 11.0 + med(2)%Epr = 12.0 + med(3)%Epr = 13.0 + med(4)%Epr = 14.0 + med(5)%Epr = 15.0 + + call Readjust(numMedia, med, newNumMedia) + + if (numMedia /= 2) then + print *, "test_readjust_shrink FAILED: NumMedia not updated, got", numMedia + status = 1 + end if + if (size(med) /= 3) then ! 0:2 = 3 elements + print *, "test_readjust_shrink FAILED: med size wrong, got", size(med) + status = 1 + end if + ! First entries preserved + if (med(0)%Epr /= 10.0 .or. med(1)%Epr /= 11.0 .or. med(2)%Epr /= 12.0) then + print *, "test_readjust_shrink FAILED: remaining entries corrupted" + status = 1 + end if + + deallocate(med) +end function test_readjust_shrink + +integer function test_readjust_same_size() bind(C, name="test_readjust_same_size") result(status) + use CreateMatrices_m, only: Readjust + use FDETYPES_m, only: MediaData_t, set_priorities + implicit none + type(MediaData_t), pointer, dimension(:) :: med + integer(kind=4) :: numMedia, newNumMedia + + status = 0 + call set_priorities(.false., .false., .false.) + + numMedia = 3 + newNumMedia = 3 + allocate(med(0:numMedia)) + med(0)%Epr = 5.0 + med(1)%Epr = 6.0 + med(2)%Epr = 7.0 + med(3)%Epr = 8.0 + + call Readjust(numMedia, med, newNumMedia) + + if (numMedia /= 3) then + print *, "test_readjust_same_size FAILED: NumMedia changed unexpectedly, got", numMedia + status = 1 + end if + if (size(med) /= 4) then ! 0:3 = 4 elements + print *, "test_readjust_same_size FAILED: med size wrong, got", size(med) + status = 1 + end if + if (med(0)%Epr /= 5.0 .or. med(1)%Epr /= 6.0 .or. med(2)%Epr /= 7.0 .or. med(3)%Epr /= 8.0) then + print *, "test_readjust_same_size FAILED: entries corrupted" + status = 1 + end if + + deallocate(med) +end function test_readjust_same_size diff --git a/test/observation/observation_tests.h b/test/observation/observation_tests.h index c3a1ebb31..20036a0e3 100644 --- a/test/observation/observation_tests.h +++ b/test/observation/observation_tests.h @@ -9,6 +9,7 @@ extern "C" int test_timestep_greater_and_mapvtk(); extern "C" int test_timestep_greater_not_mapvtk(); extern "C" int test_freqstep_zero_or_large(); extern "C" int test_volumic_false_true_and_saveall(); +extern "C" int test_volumic_true_forces_saveall_false(); extern "C" int test_saveall_branch(); extern "C" int test_final_less_than_initial(); extern "C" int test_huge_cap(); @@ -26,6 +27,7 @@ TEST(observation, test_preproces_timestep_greater_and_mapvtk ) {EXPECT_EQ( TEST(observation, test_preproces_timestep_greater_not_mapvtk ) {EXPECT_EQ(0, test_timestep_greater_not_mapvtk()); } TEST(observation, test_preproces_freqstep_zero_or_large ) {EXPECT_EQ(0, test_freqstep_zero_or_large()); } TEST(observation, test_preproces_volumic_false_true_and_saveall ) {EXPECT_EQ(0, test_volumic_false_true_and_saveall()); } +TEST(observation, test_preproces_volumic_true_forces_saveall_false) {EXPECT_EQ(0, test_volumic_true_forces_saveall_false()); } TEST(observation, test_preproces_saveall_branch ) {EXPECT_EQ(0, test_saveall_branch()); } TEST(observation, test_preproces_final_less_than_initial ) {EXPECT_EQ(0, test_final_less_than_initial()); } TEST(observation, test_preproces_huge_cap ) {EXPECT_EQ(0, test_huge_cap()); } diff --git a/test/observation/test_preprocess.F90 b/test/observation/test_preprocess.F90 index 582149b76..5c79e35cc 100644 --- a/test/observation/test_preprocess.F90 +++ b/test/observation/test_preprocess.F90 @@ -300,6 +300,49 @@ integer function test_final_less_than_initial() bind(C) result(err) end if end function test_final_less_than_initial +integer function test_volumic_true_forces_saveall_false() bind(C) result(err) + use observation_testingTools + use FDETYPES_m + use Observa_m + + type(Obses_t) :: obs + type(output_t) :: out + + integer :: finalTimeIndex + real(kind=RKIND_tiempo) :: dt + real(kind=RKIND_tiempo), pointer, dimension(:) :: tiempo + logical :: saveall + + finalTimeIndex = 90 + dt = 0.1_RKIND + tiempo => create_time_array(100, dt) + saveall = .true. + + ! Volumic = .TRUE. should force both privateOutput%SaveAll and obs%Saveall to .FALSE. + obs%Volumic = .true. + obs%Saveall = .true. + obs%TimeStep = 0.2_RKIND + obs%InitialTime = 0.0_RKIND + obs%FinalTime = 1.0_RKIND + obs%InitialFreq = 0.0_RKIND + obs%FinalFreq = 1.0_RKIND + obs%FreqStep = 0.1_RKIND + obs%nP = 0 + out%SaveAll = .true. + + call preprocess_observation(obs, out, tiempo, finalTimeIndex, dt, saveall) + + err = 0 + if (out%SaveAll .neqv. .false.) then + print *, "test_volumic_true_forces_saveall_false FAILED: out%SaveAll=", out%SaveAll + err = 1 + end if + if (obs%Saveall .neqv. .false.) then + print *, "test_volumic_true_forces_saveall_false FAILED: obs%Saveall=", obs%Saveall + err = 1 + end if +end function test_volumic_true_forces_saveall_false + integer function test_huge_cap() bind(C) result(err) use observation_testingTools use FDETYPES_m diff --git a/test/pyWrapper/conftest.py b/test/pyWrapper/conftest.py new file mode 100644 index 000000000..611382947 --- /dev/null +++ b/test/pyWrapper/conftest.py @@ -0,0 +1,7 @@ +import os +import sys + +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) +if ROOT not in sys.path: + sys.path.insert(0, ROOT) + diff --git a/test/sgbc/CMakeLists.txt b/test/sgbc/CMakeLists.txt new file mode 100644 index 000000000..4c6290e45 --- /dev/null +++ b/test/sgbc/CMakeLists.txt @@ -0,0 +1,18 @@ +message(STATUS "Creating build system for test/sgbc") + +set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/mod) + +add_library(sgbc_test_fortran + "test_sgbc.F90" +) + +target_link_libraries(sgbc_test_fortran + semba-components +) + +add_library(sgbc_tests "sgbc_tests.cpp") + +target_link_libraries(sgbc_tests + sgbc_test_fortran + GTest::gtest +) diff --git a/test/sgbc/sgbc_tests.cpp b/test/sgbc/sgbc_tests.cpp new file mode 100644 index 000000000..c49fa61c7 --- /dev/null +++ b/test/sgbc/sgbc_tests.cpp @@ -0,0 +1 @@ +#include "sgbc_tests.h" diff --git a/test/sgbc/sgbc_tests.h b/test/sgbc/sgbc_tests.h new file mode 100644 index 000000000..b29a92fb2 --- /dev/null +++ b/test/sgbc/sgbc_tests.h @@ -0,0 +1,24 @@ +#ifndef SGBC_TESTS_H +#define SGBC_TESTS_H + +#include + +extern "C" { + int test_solve_tridiag_3x3_poisson(); + int test_solve_tridiag_5x5_poisson(); + int test_solve_tridiag_diagonal_system(); +} + +TEST(sgbc, solve_tridiag_3x3_poisson) { + EXPECT_EQ(0, test_solve_tridiag_3x3_poisson()); +} + +TEST(sgbc, solve_tridiag_5x5_poisson) { + EXPECT_EQ(0, test_solve_tridiag_5x5_poisson()); +} + +TEST(sgbc, solve_tridiag_diagonal_system) { + EXPECT_EQ(0, test_solve_tridiag_diagonal_system()); +} + +#endif // SGBC_TESTS_H diff --git a/test/sgbc/test_sgbc.F90 b/test/sgbc/test_sgbc.F90 new file mode 100644 index 000000000..a1ead089d --- /dev/null +++ b/test/sgbc/test_sgbc.F90 @@ -0,0 +1,98 @@ +! Unit tests for src_main_pub/maloney_nostoch.F90 +! Tests the Thomas-algorithm tridiagonal solver solve_tridiag_iguales. + +! Solve the 1D Poisson tridiagonal system of size 3: +! [2 -1 0] [x1] [1] +! [-1 2 -1] [x2] = [0] +! [0 -1 2] [x3] [1] +! Exact solution: x1=x2=x3=1 +integer function test_solve_tridiag_3x3_poisson() bind(C, name="test_solve_tridiag_3x3_poisson") result(status) + use SGBC_nostoch_m, only: solve_tridiag_iguales + use FDETYPES_m, only: RKIND + implicit none + integer, parameter :: n = 3 + real(kind=RKIND) :: d(n), x(n) + real(kind=RKIND) :: aa, bb, cc ! interior row values (sub, main, super) + real(kind=RKIND) :: a1, b1, c1 ! first row + real(kind=RKIND) :: an, bn, cn ! last row + real(kind=RKIND), parameter :: tol = 1.0e-5_RKIND + integer :: i + + status = 0 + ! Tridiagonal: -1, 2, -1 interior; 0,2,-1 first; -1,2,0 last + a1 = 0.0_RKIND; b1 = 2.0_RKIND; c1 = -1.0_RKIND + aa = -1.0_RKIND; bb = 2.0_RKIND; cc = -1.0_RKIND + an = -1.0_RKIND; bn = 2.0_RKIND; cn = 0.0_RKIND + d = [1.0_RKIND, 0.0_RKIND, 1.0_RKIND] + + call solve_tridiag_iguales(aa, bb, cc, a1, b1, c1, an, bn, cn, d, x, n) + + do i = 1, n + if (abs(x(i) - 1.0_RKIND) > tol) then + print *, "test_solve_tridiag_3x3_poisson FAILED: x(", i, ")=", x(i), " expected 1.0" + status = 1 + end if + end do +end function test_solve_tridiag_3x3_poisson + +! Solve the 1D Poisson tridiagonal system of size 5: +! Same stencil, d=[1,0,0,0,1]; exact solution is all ones. +integer function test_solve_tridiag_5x5_poisson() bind(C, name="test_solve_tridiag_5x5_poisson") result(status) + use SGBC_nostoch_m, only: solve_tridiag_iguales + use FDETYPES_m, only: RKIND + implicit none + integer, parameter :: n = 5 + real(kind=RKIND) :: d(n), x(n) + real(kind=RKIND) :: aa, bb, cc + real(kind=RKIND) :: a1, b1, c1 + real(kind=RKIND) :: an, bn, cn + real(kind=RKIND), parameter :: tol = 1.0e-5_RKIND + integer :: i + + status = 0 + a1 = 0.0_RKIND; b1 = 2.0_RKIND; c1 = -1.0_RKIND + aa = -1.0_RKIND; bb = 2.0_RKIND; cc = -1.0_RKIND + an = -1.0_RKIND; bn = 2.0_RKIND; cn = 0.0_RKIND + d = [1.0_RKIND, 0.0_RKIND, 0.0_RKIND, 0.0_RKIND, 1.0_RKIND] + + call solve_tridiag_iguales(aa, bb, cc, a1, b1, c1, an, bn, cn, d, x, n) + + do i = 1, n + if (abs(x(i) - 1.0_RKIND) > tol) then + print *, "test_solve_tridiag_5x5_poisson FAILED: x(", i, ")=", x(i), " expected 1.0" + status = 1 + end if + end do +end function test_solve_tridiag_5x5_poisson + +! Solve a diagonal system of size 4: +! All off-diagonals zero, main diagonal = 3.0; d=[6,9,-3,12] => x=[2,3,-1,4] +integer function test_solve_tridiag_diagonal_system() bind(C, name="test_solve_tridiag_diagonal_system") result(status) + use SGBC_nostoch_m, only: solve_tridiag_iguales + use FDETYPES_m, only: RKIND + implicit none + integer, parameter :: n = 4 + real(kind=RKIND) :: d(n), x(n) + real(kind=RKIND) :: aa, bb, cc + real(kind=RKIND) :: a1, b1, c1 + real(kind=RKIND) :: an, bn, cn + real(kind=RKIND), parameter :: tol = 1.0e-5_RKIND + real(kind=RKIND), dimension(n), parameter :: expected = [2.0_RKIND, 3.0_RKIND, -1.0_RKIND, 4.0_RKIND] + integer :: i + + status = 0 + a1 = 0.0_RKIND; b1 = 3.0_RKIND; c1 = 0.0_RKIND + aa = 0.0_RKIND; bb = 3.0_RKIND; cc = 0.0_RKIND + an = 0.0_RKIND; bn = 3.0_RKIND; cn = 0.0_RKIND + d = [6.0_RKIND, 9.0_RKIND, -3.0_RKIND, 12.0_RKIND] + + call solve_tridiag_iguales(aa, bb, cc, a1, b1, c1, an, bn, cn, d, x, n) + + do i = 1, n + if (abs(x(i) - expected(i)) > tol) then + print *, "test_solve_tridiag_diagonal_system FAILED: x(", i, ")=", x(i), " expected", expected(i) + status = 1 + end if + end do +end function test_solve_tridiag_diagonal_system + diff --git a/test/wires/CMakeLists.txt b/test/wires/CMakeLists.txt new file mode 100644 index 000000000..16ca4e4b9 --- /dev/null +++ b/test/wires/CMakeLists.txt @@ -0,0 +1,20 @@ +message(STATUS "Creating build system for test/wires") + +set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/mod) + +add_library( + wires_test_fortran + "test_wires.F90" +) + +target_link_libraries(wires_test_fortran + semba-components +) + +add_library(wires_tests "wires_tests.cpp") + +target_link_libraries(wires_tests + wires_test_fortran + GTest::gtest +) + diff --git a/test/wires/test_wires.F90 b/test/wires/test_wires.F90 new file mode 100644 index 000000000..f9b1a2031 --- /dev/null +++ b/test/wires/test_wires.F90 @@ -0,0 +1,243 @@ +integer function test_getHwires_returns_associated() bind(C, name="test_getHwires_returns_associated") result(status) + use HollandWires_m, only: GetHwires + use wiresHolland_constants_m, only: ThinWires_t + implicit none + type(ThinWires_t), pointer :: p + + status = 0 + p => GetHwires() + if (.not. associated(p)) then + print *, "test_getHwires_returns_associated FAILED: returned pointer is not associated" + status = 1 + end if +end function test_getHwires_returns_associated + +integer function test_destroyWires_deallocates_wires_data() bind(C, name="test_destroyWires_deallocates_wires_data") result(status) + use HollandWires_m, only: DestroyWires, GetHwires + use FDETYPES_m, only: SGGFDTDINFO_t, MediaData_t + use wiresHolland_constants_m, only: ThinWires_t + implicit none + type(SGGFDTDINFO_t) :: sgg + type(MediaData_t) :: basic_media + type(ThinWires_t), pointer :: p + + status = 0 + + sgg%NumMedia = 1 + allocate(sgg%Med(0:sgg%NumMedia)) + sgg%Med = basic_media + + sgg%Med(1)%Is%ThinWire = .true. + allocate(sgg%Med(1)%wire(1)) + allocate(sgg%Med(1)%wire(1)%Vsource(1)) + allocate(sgg%Med(1)%wire(1)%Isource(1)) + + p => GetHwires() + allocate(p%WireTipoMedio(1)) + allocate(p%CurrentSegment(1)) + allocate(p%ChargeNode(1)) + + call DestroyWires(sgg) + + if (associated(sgg%Med(1)%wire)) then + print *, "test_destroyWires_deallocates_wires_data FAILED: media wire pointer still associated" + status = 1 + end if + if (associated(p%WireTipoMedio)) then + print *, "test_destroyWires_deallocates_wires_data FAILED: HWires%WireTipoMedio still associated" + status = 1 + end if + if (associated(p%CurrentSegment)) then + print *, "test_destroyWires_deallocates_wires_data FAILED: HWires%CurrentSegment still associated" + status = 1 + end if + if (associated(p%ChargeNode)) then + print *, "test_destroyWires_deallocates_wires_data FAILED: HWires%ChargeNode still associated" + status = 1 + end if + + if (associated(sgg%Med)) deallocate(sgg%Med) +end function test_destroyWires_deallocates_wires_data + +integer function test_destroyWires_keeps_non_thinwire_media() bind(C, name="test_destroyWires_keeps_non_thinwire_media") result(status) + use HollandWires_m, only: DestroyWires + use FDETYPES_m, only: SGGFDTDINFO_t, MediaData_t + implicit none + type(SGGFDTDINFO_t) :: sgg + type(MediaData_t) :: basic_media + + status = 0 + + sgg%NumMedia = 1 + allocate(sgg%Med(0:sgg%NumMedia)) + sgg%Med = basic_media + + sgg%Med(1)%Is%ThinWire = .false. + allocate(sgg%Med(1)%wire(1)) + allocate(sgg%Med(1)%wire(1)%Vsource(1)) + allocate(sgg%Med(1)%wire(1)%Isource(1)) + + call DestroyWires(sgg) + + if (.not. associated(sgg%Med(1)%wire)) then + print *, "test_destroyWires_keeps_non_thinwire_media FAILED: non-thinwire media was deallocated" + status = 1 + end if + + if (associated(sgg%Med(1)%wire(1)%Vsource)) deallocate(sgg%Med(1)%wire(1)%Vsource) + if (associated(sgg%Med(1)%wire(1)%Isource)) deallocate(sgg%Med(1)%wire(1)%Isource) + if (associated(sgg%Med(1)%wire)) deallocate(sgg%Med(1)%wire) + if (associated(sgg%Med)) deallocate(sgg%Med) +end function test_destroyWires_keeps_non_thinwire_media + +integer function test_destroyWireMedia_thinwire() bind(C, name="test_destroyWireMedia_thinwire") result(status) + use HollandWires_m, only: DestroyWireMedia + use FDETYPES_m, only: MediaData_t + implicit none + type(MediaData_t) :: media + + status = 0 + + media%Is%ThinWire = .true. + allocate(media%wire(1)) + allocate(media%wire(1)%Vsource(1)) + allocate(media%wire(1)%Isource(1)) + + call DestroyWireMedia(media) + + if (associated(media%wire)) then + print *, "test_destroyWireMedia_thinwire FAILED: wire storage still associated" + status = 1 + end if +end function test_destroyWireMedia_thinwire + +integer function test_evolucion_out_of_range_low() bind(C, name="test_evolucion_out_of_range_low") result(status) + use HollandWires_m, only: evolucion + use FDETYPES_m, only: RKIND_wires + implicit none + integer(kind=4) :: numus + real(kind=RKIND_wires), dimension(0:3) :: evol + real(kind=RKIND_wires) :: deltaevol, t, result + + status = 0 + numus = 3 + deltaevol = 1.0_RKIND_wires + evol = [0.0_RKIND_wires, 1.0_RKIND_wires, 2.0_RKIND_wires, 3.0_RKIND_wires] + ! t = -1.5 -> nprev = int(-1.5) = -1 -> nprev+1 = 0 <= 0 -> returns 0 + t = -1.5_RKIND_wires + result = evolucion(t, evol, deltaevol, numus) + if (abs(result) > 1.0e-12_RKIND_wires) then + print *, "test_evolucion_out_of_range_low FAILED: result=", result + status = 1 + end if +end function test_evolucion_out_of_range_low + +integer function test_evolucion_out_of_range_high() bind(C, name="test_evolucion_out_of_range_high") result(status) + use HollandWires_m, only: evolucion + use FDETYPES_m, only: RKIND_wires + implicit none + integer(kind=4) :: numus + real(kind=RKIND_wires), dimension(0:3) :: evol + real(kind=RKIND_wires) :: deltaevol, t, result + + status = 0 + numus = 3 + deltaevol = 1.0_RKIND_wires + evol = [0.0_RKIND_wires, 1.0_RKIND_wires, 2.0_RKIND_wires, 3.0_RKIND_wires] + ! t = 3.0 -> nprev = int(3.0) = 3 = numus -> nprev+1 = 4 > 3 = numus -> returns 0 + t = 3.0_RKIND_wires + result = evolucion(t, evol, deltaevol, numus) + if (abs(result) > 1.0e-12_RKIND_wires) then + print *, "test_evolucion_out_of_range_high FAILED: result=", result + status = 1 + end if +end function test_evolucion_out_of_range_high + +integer function test_evolucion_at_zero() bind(C, name="test_evolucion_at_zero") result(status) + use HollandWires_m, only: evolucion + use FDETYPES_m, only: RKIND_wires + implicit none + integer(kind=4) :: numus + real(kind=RKIND_wires), dimension(0:3) :: evol + real(kind=RKIND_wires) :: deltaevol, t, result + + status = 0 + numus = 3 + deltaevol = 1.0_RKIND_wires + evol = [5.0_RKIND_wires, 1.0_RKIND_wires, 2.0_RKIND_wires, 3.0_RKIND_wires] + ! t = 0.0 -> nprev = 0, returns evol(0) = 5.0 + t = 0.0_RKIND_wires + result = evolucion(t, evol, deltaevol, numus) + if (abs(result - 5.0_RKIND_wires) > 1.0e-12_RKIND_wires) then + print *, "test_evolucion_at_zero FAILED: result=", result + status = 1 + end if +end function test_evolucion_at_zero + +integer function test_evolucion_midpoint_interp() bind(C, name="test_evolucion_midpoint_interp") result(status) + use HollandWires_m, only: evolucion + use FDETYPES_m, only: RKIND_wires + implicit none + integer(kind=4) :: numus + real(kind=RKIND_wires), dimension(0:3) :: evol + real(kind=RKIND_wires) :: deltaevol, t, result, expected + + status = 0 + numus = 3 + deltaevol = 1.0_RKIND_wires + evol = [0.0_RKIND_wires, 2.0_RKIND_wires, 4.0_RKIND_wires, 6.0_RKIND_wires] + ! t = 0.5 -> nprev = 0, result = (2-0)/1*0.5 + 0 = 1.0 + t = 0.5_RKIND_wires + expected = 1.0_RKIND_wires + result = evolucion(t, evol, deltaevol, numus) + if (abs(result - expected) > 1.0e-10_RKIND_wires) then + print *, "test_evolucion_midpoint_interp FAILED: result=", result, " expected=", expected + status = 1 + end if +end function test_evolucion_midpoint_interp + +integer function test_evolucion_exact_sample() bind(C, name="test_evolucion_exact_sample") result(status) + use HollandWires_m, only: evolucion + use FDETYPES_m, only: RKIND_wires + implicit none + integer(kind=4) :: numus + real(kind=RKIND_wires), dimension(0:3) :: evol + real(kind=RKIND_wires) :: deltaevol, t, result + + status = 0 + numus = 3 + deltaevol = 1.0_RKIND_wires + evol = [0.0_RKIND_wires, 7.0_RKIND_wires, 4.0_RKIND_wires, 6.0_RKIND_wires] + ! t = 1.0 -> nprev = 1, result = (evol(2)-evol(1))/1*0 + evol(1) = 7.0 + t = 1.0_RKIND_wires + result = evolucion(t, evol, deltaevol, numus) + if (abs(result - 7.0_RKIND_wires) > 1.0e-12_RKIND_wires) then + print *, "test_evolucion_exact_sample FAILED: result=", result + status = 1 + end if +end function test_evolucion_exact_sample + +integer function test_destroyWireMedia_non_thinwire() bind(C, name="test_destroyWireMedia_non_thinwire") result(status) + use HollandWires_m, only: DestroyWireMedia + use FDETYPES_m, only: MediaData_t + implicit none + type(MediaData_t) :: media + + status = 0 + + media%Is%ThinWire = .false. + allocate(media%wire(1)) + allocate(media%wire(1)%Vsource(1)) + allocate(media%wire(1)%Isource(1)) + + call DestroyWireMedia(media) + + if (.not. associated(media%wire)) then + print *, "test_destroyWireMedia_non_thinwire FAILED: non-thinwire storage was deallocated" + status = 1 + end if + + if (associated(media%wire(1)%Vsource)) deallocate(media%wire(1)%Vsource) + if (associated(media%wire(1)%Isource)) deallocate(media%wire(1)%Isource) + if (associated(media%wire)) deallocate(media%wire) +end function test_destroyWireMedia_non_thinwire diff --git a/test/wires/wires_tests.cpp b/test/wires/wires_tests.cpp new file mode 100644 index 000000000..3eaa151e8 --- /dev/null +++ b/test/wires/wires_tests.cpp @@ -0,0 +1,2 @@ +#include "wires_tests.h" + diff --git a/test/wires/wires_tests.h b/test/wires/wires_tests.h new file mode 100644 index 000000000..be077d2c1 --- /dev/null +++ b/test/wires/wires_tests.h @@ -0,0 +1,59 @@ +#ifndef WIRES_TESTS_H +#define WIRES_TESTS_H + +#include + +extern "C" { + int test_getHwires_returns_associated(); + int test_destroyWires_deallocates_wires_data(); + int test_destroyWires_keeps_non_thinwire_media(); + int test_destroyWireMedia_thinwire(); + int test_destroyWireMedia_non_thinwire(); + int test_evolucion_out_of_range_low(); + int test_evolucion_out_of_range_high(); + int test_evolucion_at_zero(); + int test_evolucion_midpoint_interp(); + int test_evolucion_exact_sample(); +} + +TEST(wires, getHwires_returns_associated) { + EXPECT_EQ(0, test_getHwires_returns_associated()); +} + +TEST(wires, destroyWires_deallocates_wires_data) { + EXPECT_EQ(0, test_destroyWires_deallocates_wires_data()); +} + +TEST(wires, destroyWires_keeps_non_thinwire_media) { + EXPECT_EQ(0, test_destroyWires_keeps_non_thinwire_media()); +} + +TEST(wires, destroyWireMedia_thinwire) { + EXPECT_EQ(0, test_destroyWireMedia_thinwire()); +} + +TEST(wires, destroyWireMedia_non_thinwire) { + EXPECT_EQ(0, test_destroyWireMedia_non_thinwire()); +} + +TEST(wires, evolucion_out_of_range_low) { + EXPECT_EQ(0, test_evolucion_out_of_range_low()); +} + +TEST(wires, evolucion_out_of_range_high) { + EXPECT_EQ(0, test_evolucion_out_of_range_high()); +} + +TEST(wires, evolucion_at_zero) { + EXPECT_EQ(0, test_evolucion_at_zero()); +} + +TEST(wires, evolucion_midpoint_interp) { + EXPECT_EQ(0, test_evolucion_midpoint_interp()); +} + +TEST(wires, evolucion_exact_sample) { + EXPECT_EQ(0, test_evolucion_exact_sample()); +} + +#endif // WIRES_TESTS_H