From 9e2e0759bc174e1cee3aa62fa57e7b530b941042 Mon Sep 17 00:00:00 2001 From: Jiaxing Song Date: Tue, 27 Oct 2026 01:40:23 +0800 Subject: [PATCH 1/2] Work around an NVHPC 26.9 miscompile of any() over shear_indices NVHPC 26.9 at -O2 and above vectorizes any(idx == shear_indices) inside a loop to always true, so every normal stress component was counted as shear and its elastic energy added twice. The hypoelasticity tests failed on 26.9 (CPU and GPU); 25.9 and 26.3 are not affected. An IS_SHEAR Fypp macro writes the test as three comparisons, which 26.9 compiles correctly at -O2 and with -Minline. Results are unchanged with GNU and NVHPC 26.3. Co-authored-by: ruru25254649 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01JcWJMEPdfRnApebSDv7mrf --- src/common/include/macros.fpp | 6 ++++++ src/common/m_variables_conversion.fpp | 7 +++---- src/simulation/m_riemann_state.fpp | 4 ++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/common/include/macros.fpp b/src/common/include/macros.fpp index e0ede31540..d17cc8a4d3 100644 --- a/src/common/include/macros.fpp +++ b/src/common/include/macros.fpp @@ -143,6 +143,12 @@ #endif #:enddef +! Whether stress index idx is a shear component. Spelled out because NVHPC 26.9 at -O2 vectorizes any(idx == shear_indices) +! inside a loop to always true, which doubled the normal-stress elastic energy. +#:def IS_SHEAR(idx) + (${idx}$ == shear_indices(1) .or. ${idx}$ == shear_indices(2) .or. ${idx}$ == shear_indices(3)) +#:enddef + #:def PROHIBIT(condition, message = None) if (${condition}$) then call s_prohibit_abort("${condition}$", ${message or '""'}$) diff --git a/src/common/m_variables_conversion.fpp b/src/common/m_variables_conversion.fpp index 9e1260800b..1b7b39d2a5 100644 --- a/src/common/m_variables_conversion.fpp +++ b/src/common/m_variables_conversion.fpp @@ -658,8 +658,7 @@ contains $:GPU_LOOP(parallelism='[seq]') do i = eqn_idx%stress%beg, eqn_idx%stress%end qK_prim_vf(eqn_idx%E)%sf(j, k, l) = qK_prim_vf(eqn_idx%E)%sf(j, k, & - & l) - f_elastic_energy(real(qK_prim_vf(i)%sf(j, k, l), wp), G_K, & - & any(i == shear_indices))/gamma_K + & l) - f_elastic_energy(real(qK_prim_vf(i)%sf(j, k, l), wp), G_K, ${IS_SHEAR('i')}$)/gamma_K end do end if @@ -905,7 +904,7 @@ contains q_cons_vf(eqn_idx%E)%sf(j, k, l) = q_cons_vf(eqn_idx%E)%sf(j, k, l) + (q_prim_vf(i)%sf(j, k, & & l)**2._wp)/max(4._wp*G, verysmall) ! Double for shear stresses - if (any(i == shear_indices)) then + if (${IS_SHEAR('i')}$) then q_cons_vf(eqn_idx%E)%sf(j, k, l) = q_cons_vf(eqn_idx%E)%sf(j, k, l) + (q_prim_vf(i)%sf(j, k, & & l)**2._wp)/max(4._wp*G, verysmall) end if @@ -1242,7 +1241,7 @@ contains E_e = 0._wp do s = eqn_idx%stress%beg, eqn_idx%stress%end - E_e = E_e + f_elastic_energy(real(q_cons_vf(s)%sf(j, k, l), wp)/rho, G, any(s == shear_indices)) + E_e = E_e + f_elastic_energy(real(q_cons_vf(s)%sf(j, k, l), wp)/rho, G, ${IS_SHEAR('s')}$) end do end function f_hypoelastic_energy diff --git a/src/simulation/m_riemann_state.fpp b/src/simulation/m_riemann_state.fpp index 1c589d4f7f..20f7bb1f4b 100644 --- a/src/simulation/m_riemann_state.fpp +++ b/src/simulation/m_riemann_state.fpp @@ -1280,14 +1280,14 @@ contains if (G_L > verysmall) then E_L = E_L + (tau_e_L(i)*tau_e_L(i))/(4._wp*G_L) ! Double for shear stresses - if (any(eqn_idx%stress%beg - 1 + i == shear_indices)) then + if (${IS_SHEAR('eqn_idx%stress%beg - 1 + i')}$) then E_L = E_L + (tau_e_L(i)*tau_e_L(i))/(4._wp*G_L) end if end if if (G_R > verysmall) then E_R = E_R + (tau_e_R(i)*tau_e_R(i))/(4._wp*G_R) ! Double for shear stresses - if (any(eqn_idx%stress%beg - 1 + i == shear_indices)) then + if (${IS_SHEAR('eqn_idx%stress%beg - 1 + i')}$) then E_R = E_R + (tau_e_R(i)*tau_e_R(i))/(4._wp*G_R) end if end if From 5666e4f0d668ae3b2bcfde68207d6884a2438eba Mon Sep 17 00:00:00 2001 From: Jiaxing Song Date: Tue, 27 Oct 2026 01:40:37 +0800 Subject: [PATCH 2/2] Let -cudalib=nvtx3 pick the NVTX wrapper so NVHPC 26.9 links For CUDA >= 12.9 the targets linked nvhpcwrapnvtx by name in addition to -cudalib=nvtx3. NVHPC 26.9 renamed that library to libnvhpcnvtx, so every NVHPC build, CPU or GPU, stops at its first link (syscheck): /usr/bin/ld: cannot find -lnvhpcwrapnvtx -cudalib=nvtx3 already links the wrapper under each release's name (-lnvhpcwrapnvtx through 26.3, -lnvhpcnvtx on 26.9), so the explicit name is dropped. Checked on every CI release, 25.5 to 26.3, and on 26.9: the flag alone links MFC's NVTX calls, and CMake takes this branch in the CI images. LINKER_LANGUAGE Fortran keeps nvfortran, the only driver that understands the flag, on the link. The CUDA <= 12.8 branch stays: NVHPC 21.7 to 22.3 reject -cudalib=nvtx3, and 22.11 to 24.5 accept it but leave the NVTX symbols undefined. CI: add 26.9 CPU (full suite) and GPU (build) jobs. Add cmake/** to the cmakelist filter in file-filter.yml, which lists CMakeLists.txt and toolchain/cmake/** but not the cmake/ directory added in #1552, so a PR that only changes cmake/*.cmake skipped the build matrix. Also name cmake/ in the coverage run-all prefixes next to toolchain/cmake/; such changes already ran the full suite through the fallback, so only the rule becomes explicit. Co-authored-by: ruru25254649 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01JcWJMEPdfRnApebSDv7mrf --- .github/file-filter.yml | 1 + .github/workflows/test.yml | 2 ++ cmake/MFCTargets.cmake | 4 +++- toolchain/mfc/test/coverage.py | 1 + toolchain/mfc/test/test_coverage_unit.py | 1 + 5 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/file-filter.yml b/.github/file-filter.yml index b74b2a4f11..15841240ab 100644 --- a/.github/file-filter.yml +++ b/.github/file-filter.yml @@ -11,6 +11,7 @@ python_src: &python_src cmakelist: &cmakelist - 'CMakeLists.txt' + - 'cmake/**' - 'toolchain/cmake/**' tests: &tests diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 915dad9ff7..282523f526 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -117,6 +117,8 @@ jobs: - { nvhpc: '26.1', target: gpu } - { nvhpc: '26.3', target: cpu } - { nvhpc: '26.3', target: gpu } + - { nvhpc: '26.9', target: cpu } + - { nvhpc: '26.9', target: gpu } fail-fast: false continue-on-error: true diff --git a/cmake/MFCTargets.cmake b/cmake/MFCTargets.cmake index 13777ccc32..f42eb334bc 100644 --- a/cmake/MFCTargets.cmake +++ b/cmake/MFCTargets.cmake @@ -345,8 +345,10 @@ exit 0 if (TARGET CUDA::nvToolsExt) # CUDA <= 12.8 target_link_libraries(${a_target} PRIVATE CUDA::nvToolsExt) else() # CUDA >= 12.9 - target_link_libraries(${a_target} PRIVATE nvhpcwrapnvtx) + # -cudalib=nvtx3 lets the NVHPC driver link its NVTX wrapper, whose name changes between releases. + # Only nvfortran understands the flag, so it must drive the link. target_link_options(${a_target} PRIVATE "-cudalib=nvtx3") + set_target_properties(${a_target} PROPERTIES LINKER_LANGUAGE Fortran) endif() endif() endforeach() diff --git a/toolchain/mfc/test/coverage.py b/toolchain/mfc/test/coverage.py index 2b9574677c..54a46598fd 100644 --- a/toolchain/mfc/test/coverage.py +++ b/toolchain/mfc/test/coverage.py @@ -97,6 +97,7 @@ def save_map(path: Path, entries: dict, *, n_tests: int, git_sha: str, gfortran_ ) ALWAYS_RUN_ALL_PREFIXES = ( "src/common/include/", # GPU/Fypp macro & include files (CPU map can't line-attribute) + "cmake/", # build system "toolchain/cmake/", # build system "toolchain/bootstrap/", # build/run scripts ) diff --git a/toolchain/mfc/test/test_coverage_unit.py b/toolchain/mfc/test/test_coverage_unit.py index 5bc7e01470..b2099e069f 100644 --- a/toolchain/mfc/test/test_coverage_unit.py +++ b/toolchain/mfc/test/test_coverage_unit.py @@ -60,6 +60,7 @@ def test_macro_file_forces_all(): def test_cmake_forces_all(): assert is_always_run_all({"CMakeLists.txt"}) assert is_always_run_all({"toolchain/cmake/foo.cmake"}) + assert is_always_run_all({"cmake/MFCTargets.cmake"}) def test_param_codegen_forces_all():