Skip to content
Open
7 changes: 6 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,18 @@ if(SEASTACK_ENABLE_CHRONO)
" (or /usr/local/opt/libomp on Intel Homebrew).")
endif()

# If Chrono set HDF5_DIR, retry the find
# If Chrono set HDF5_DIR to NOTFOUND (common when Chrono itself found HDF5
# via module mode, not hdf5-config.cmake), clear it so later FindHDF5
# module-mode discovery (e.g. Ubuntu libhdf5-dev) can succeed.
if(NOT HDF5_FOUND AND DEFINED CACHE{HDF5_DIR})
if("${HDF5_DIR}" MATCHES "NOTFOUND")
unset(HDF5_DIR CACHE)
find_package(HDF5 CONFIG QUIET)
endif()
endif()
if(SEASTACK_ENABLE_HYDRO_IO AND NOT HDF5_FOUND)
find_package(HDF5 QUIET COMPONENTS CXX)
endif()

# Use same C++ standard as Chrono for ABI compatibility
if(DEFINED CHRONO_CXX_STANDARD)
Expand Down
28 changes: 17 additions & 11 deletions adapters/chrono/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,25 @@ target_include_directories(seastack_chrono_adapter

# Chrono MBS YAML registers TSDA/RSDA force functors without copying damping onto the link;
# simulation_export reads damping_coefficient from model YAML when GetDampingCoefficient()==0.
find_package(yaml-cpp CONFIG QUIET)
if(NOT yaml-cpp_FOUND)
find_package(yaml-cpp QUIET)
endif()
if(TARGET yaml-cpp::yaml-cpp)
set(_seastack_yaml_cpp_target yaml-cpp::yaml-cpp)
elseif(TARGET yaml-cpp)
set(_seastack_yaml_cpp_target yaml-cpp)
elseif(TARGET Chrono::yaml-cpp)
# Chrono's config often provides yaml-cpp as an imported target without a system package.
#
# Prefer Chrono's bundled yaml-cpp when available so that the yaml-cpp headers
# (which come from Chrono's chrono_thirdparty/yaml-cpp/include via Chrono::Chrono_core)
# match the linked library. Mixing a system libyaml-cpp.so with Chrono's headers can
# produce link errors against internal symbols (e.g. YAML::FpToString, YAML::Emitter::Write).
if(TARGET Chrono::yaml-cpp)
set(_seastack_yaml_cpp_target Chrono::yaml-cpp)
else()
message(FATAL_ERROR "yaml-cpp not found (required for Chrono adapter).")
find_package(yaml-cpp CONFIG QUIET)
if(NOT yaml-cpp_FOUND)
find_package(yaml-cpp QUIET)
endif()
if(TARGET yaml-cpp::yaml-cpp)
set(_seastack_yaml_cpp_target yaml-cpp::yaml-cpp)
elseif(TARGET yaml-cpp)
set(_seastack_yaml_cpp_target yaml-cpp)
else()
message(FATAL_ERROR "yaml-cpp not found (required for Chrono adapter).")
endif()
endif()

target_link_libraries(seastack_chrono_adapter
Expand Down
19 changes: 12 additions & 7 deletions adapters/chrono/src/simulation_export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1082,13 +1082,18 @@ void SimulationExporter::RecordStep(::chrono::ChSystem* system) {
}

// ── Generic joint reactions (level-gated) ───────────────────────────────
// GetReaction1/2 and GetFrame1Abs/2Abs are virtual on ChLinkBase, so they
// work for every concrete joint type (ChLinkLock, ChLinkUniversal,
// ChLinkRevoluteSpherical, ...). Previously this code dynamic_cast<>'d to
// ChLinkLock* only, silently writing zeros for every other joint type --
// including the ChLinkUniversal joints used by the 5SA articulated WEC demos.
for (auto& j : impl_->joints) {
auto* L = j.link;
if (auto* lock = dynamic_cast<::chrono::ChLinkLock*>(L)) {
if (L) {
try {
auto w1 = lock->GetReaction1();
auto F1 = lock->GetFrame1Abs().TransformDirectionLocalToParent(w1.force);
auto T1 = lock->GetFrame1Abs().TransformDirectionLocalToParent(w1.torque);
auto w1 = L->GetReaction1();
auto F1 = L->GetFrame1Abs().TransformDirectionLocalToParent(w1.force);
auto T1 = L->GetFrame1Abs().TransformDirectionLocalToParent(w1.torque);
Comment on lines +1094 to +1096
Comment on lines +1095 to +1096
j.react_force_b1.insert(j.react_force_b1.end(), {F1.x(), F1.y(), F1.z()});
j.react_torque_b1.insert(j.react_torque_b1.end(), {T1.x(), T1.y(), T1.z()});
} catch (const std::exception& ex) {
Expand All @@ -1098,9 +1103,9 @@ void SimulationExporter::RecordStep(::chrono::ChSystem* system) {
}
if (!is_compact) {
try {
auto w2 = lock->GetReaction2();
auto F2 = lock->GetFrame2Abs().TransformDirectionLocalToParent(w2.force);
auto T2 = lock->GetFrame2Abs().TransformDirectionLocalToParent(w2.torque);
auto w2 = L->GetReaction2();
auto F2 = L->GetFrame2Abs().TransformDirectionLocalToParent(w2.force);
auto T2 = L->GetFrame2Abs().TransformDirectionLocalToParent(w2.torque);
Comment on lines +1107 to +1108
j.react_force_b2.insert(j.react_force_b2.end(), {F2.x(), F2.y(), F2.z()});
j.react_torque_b2.insert(j.react_torque_b2.end(), {T2.x(), T2.y(), T2.z()});
} catch (const std::exception& ex) {
Expand Down
26 changes: 21 additions & 5 deletions data/demos/run_seastack/5sa/bimodal/5sa_bimodal.hydro.yaml
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
hydrodynamics:
bodies:
# Surge/sway/heave/roll/pitch/yaw damping mirrored from the spreading
# case. The bimodal swell + wind sea combination contains spectral
# energy near the chain's heave natural frequency, and with zero
# linear and quadratic damping in heave/pitch/yaw the rigid-body
# heave mode runs away after ~200 s of accumulation (body z-position
# exceeded 10 m above SWL by t=280 s in the previous configuration).
- name: body1
h5_file: ../assets/hydroData/5sa_directional.h5
linear_damping: [0, 100000, 0, 500000, 0, 0]
linear_damping: [20000, 80000, 80000, 500000, 200000, 200000]
quadratic_damping: [10000, 40000, 40000, 250000, 100000, 100000]
- name: body2
h5_file: ../assets/hydroData/5sa_directional.h5
linear_damping: [0, 100000, 0, 500000, 0, 0]
linear_damping: [20000, 80000, 80000, 500000, 200000, 200000]
quadratic_damping: [10000, 40000, 40000, 250000, 100000, 100000]
- name: body3
h5_file: ../assets/hydroData/5sa_directional.h5
linear_damping: [0, 100000, 0, 500000, 0, 0]
linear_damping: [20000, 80000, 80000, 500000, 200000, 200000]
quadratic_damping: [10000, 40000, 40000, 250000, 100000, 100000]
- name: body4
h5_file: ../assets/hydroData/5sa_directional.h5
linear_damping: [0, 100000, 0, 500000, 0, 0]
linear_damping: [20000, 80000, 80000, 500000, 200000, 200000]
quadratic_damping: [10000, 40000, 40000, 250000, 100000, 100000]
- name: body5
h5_file: ../assets/hydroData/5sa_directional.h5
linear_damping: [0, 100000, 0, 500000, 0, 0]
linear_damping: [20000, 80000, 80000, 500000, 200000, 200000]
quadratic_damping: [10000, 40000, 40000, 250000, 100000, 100000]

# Bimodal sea state: swell along +X, wind sea from beam (90 deg).
waves:
Expand Down Expand Up @@ -42,6 +53,11 @@ hydrodynamics:
type: cos2s
s: 8

# Bimodal sea: swell and wind-sea have different headings, so excitation
# must be evaluated in the frequency domain (matches spreading case).
excitation:
method: frequency_domain

radiation:
method: rirf_convolution
smoothing:
Expand Down
15 changes: 8 additions & 7 deletions scripts/unix/build.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -318,14 +318,15 @@ else
USE_VSG=0
fi

# HydroIO / HDF5:
# Do not force HydroIO OFF merely because build-config.json leaves HDF5Dir empty.
# On Ubuntu/Debian, libhdf5-dev is discovered by CMake FindHDF5 (module mode)
# without a config-mode HDF5_DIR. Passing -DHDF5_DIR is optional; Chrono's
# ChronoConfig may even set HDF5_DIR to NOTFOUND when it used module-mode HDF5.
# Only --no-hydro-io disables HydroIO here. If CMake cannot find HDF5, configure
# fails with a clear FindHDF5 error instead of a later missing-header failure.
if [[ -z "${SEASTACK_HDF5_DIR:-}" && "${NO_HYDRO_IO}" -eq 0 ]]; then
echo " [WARN] HDF5 not found; HydroIO will be disabled." >&2
if [[ "${USE_CHRONO}" -eq 1 ]]; then
echo " If Chrono was built without HDF5, set HDF5Dir in build-config.json." >&2
else
echo " For Chrono-free builds, set HDF5Dir or use --no-hydro-io." >&2
fi
NO_HYDRO_IO=1
echo " [INFO] HDF5Dir unset; HydroIO left ON for CMake HDF5 discovery (module/config)." >&2
fi

if [[ "${MOORDYN}" -eq 1 && ! -f "${REPO_ROOT}/extern/MoorDyn/CMakeLists.txt" ]]; then
Expand Down
Empty file modified scripts/unix/ctest_suite.sh
100644 → 100755
Empty file.
Empty file modified scripts/unix/run_benchmarks.sh
100644 → 100755
Empty file.
Empty file modified scripts/unix/run_chrono_free_tests.sh
100644 → 100755
Empty file.
Empty file modified scripts/unix/run_comparison_tests.sh
100644 → 100755
Empty file.
Empty file modified scripts/unix/run_regression_tests.sh
100644 → 100755
Empty file.
Empty file modified scripts/unix/run_seastack_demo_smoke.sh
100644 → 100755
Empty file.
Empty file modified scripts/unix/run_unit_tests.sh
100644 → 100755
Empty file.
Empty file modified scripts/unix/run_verification_tests.sh
100644 → 100755
Empty file.