Skip to content

Commit c16016c

Browse files
authored
Merge pull request #83 from Project-SEA-Stack/feature/vsg-visualization
Add VSG free-surface visualization and refactor test infrastructure
2 parents 5dba5c6 + 21b1cb6 commit c16016c

59 files changed

Lines changed: 3862 additions & 1811 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,4 @@ build-config.json
6060
/tests/regression/run_hydrochrono/iea_sphere/decay/outputs
6161
/tests/regression/run_hydrochrono/oswec/decay/outputs
6262
/tests/regression/run_hydrochrono/rm3/decay/outputs
63+
/data/demos/run_hydrochrono/**/outputs

CMakeLists.txt

Lines changed: 80 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,7 @@ endif()
169169

170170
find_package(Chrono
171171
CONFIG REQUIRED
172-
COMPONENTS Parsers
173-
OPTIONAL_COMPONENTS Irrlicht VSG)
172+
COMPONENTS Parsers)
174173

175174
message(STATUS "----\n")
176175

@@ -419,6 +418,19 @@ endif()
419418
if(HYDROCHRONO_ENABLE_VSG)
420419
set(HCGUI_SOURCES ${HCGUI_SOURCES}
421420
src/gui/guihelperVSG.cpp
421+
src/gui/vsg_gui_component.cpp
422+
src/gui/vsg_lighting.cpp
423+
src/gui/vsg_materials.cpp
424+
src/gui/vsg_water_surface.cpp
425+
src/gui/vsg_radiation_surface.cpp
426+
)
427+
set(HCGUI_HEADERS ${HCGUI_HEADERS}
428+
src/gui/vsg_config.h
429+
src/gui/vsg_gui_component.h
430+
src/gui/vsg_lighting.h
431+
src/gui/vsg_materials.h
432+
src/gui/vsg_water_surface.h
433+
src/gui/vsg_radiation_surface.h
422434
)
423435
endif()
424436

@@ -431,11 +443,6 @@ target_include_directories(HydroChronoGUI
431443
"$<INSTALL_INTERFACE:include>"
432444
)
433445

434-
if(MSVC)
435-
target_compile_options(HydroChronoGUI PRIVATE $<$<COMPILE_LANGUAGE:CXX>:/wd4996>) # deprecated function or class member
436-
target_compile_options(HydroChronoGUI PRIVATE $<$<COMPILE_LANGUAGE:CXX>:/wd4458>) # declaration hides class member
437-
endif()
438-
439446
set_target_properties(HydroChronoGUI PROPERTIES POSITION_INDEPENDENT_CODE ON)
440447
target_link_libraries(HydroChronoGUI
441448
PUBLIC
@@ -536,6 +543,7 @@ if(HYDROCHRONO_ENABLE_TESTS)
536543
endif()
537544

538545
add_subdirectory(tests/regression)
546+
add_subdirectory(tests/unit)
539547
endif()
540548

541549
# ===============================================================================
@@ -611,27 +619,33 @@ endif()
611619
# Flat install tree for public distribution
612620
option(HC_INSTALL_DEV_DEMOS "Install developer demo executables" OFF)
613621

614-
# Install main CLI only (if built)
622+
# Install main CLI and project shared libraries (if built)
615623
if(TARGET run_hydrochrono)
616624
install(TARGETS run_hydrochrono CONFIGURATIONS Release DESTINATION bin COMPONENT runtime)
617625
endif()
626+
if(TARGET HydroChrono)
627+
install(TARGETS HydroChrono CONFIGURATIONS Release RUNTIME DESTINATION bin COMPONENT runtime)
628+
endif()
629+
if(TARGET HydroChronoGUI)
630+
install(TARGETS HydroChronoGUI CONFIGURATIONS Release RUNTIME DESTINATION bin COMPONENT runtime)
631+
endif()
618632

619633
# On Windows, install DLLs
620634
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
621635
message(STATUS "Set DLLs for installation")
622636

623-
# Chrono DLLs
624-
foreach(tgt ${CHRONO_TARGETS})
625-
get_target_property(tgt_DLL ${tgt} IMPORTED_LOCATION_RELEASE)
626-
get_target_property(tgt_DLL_d ${tgt} IMPORTED_LOCATION_DEBUG)
627-
if(EXISTS ${tgt_DLL})
628-
message(STATUS " Chrono DLL ${tgt_DLL}")
629-
install(FILES ${tgt_DLL} DESTINATION bin COMPONENT runtime)
630-
endif()
631-
if(EXISTS ${tgt_DLL_d})
632-
install(FILES ${tgt_DLL_d} DESTINATION bin COMPONENT runtime)
633-
endif()
634-
endforeach()
637+
# Chrono DLLs — glob ALL DLLs from the Chrono bin directory to catch
638+
# transitive dependencies (e.g., Chrono_fsitdpf_vsg, yaml-cpp) that may
639+
# not be listed in CHRONO_TARGETS.
640+
get_target_property(_chrono_core_dll Chrono::Chrono_core IMPORTED_LOCATION_RELEASE)
641+
if(_chrono_core_dll)
642+
get_filename_component(_chrono_dll_dir "${_chrono_core_dll}" DIRECTORY)
643+
file(GLOB _chrono_dlls "${_chrono_dll_dir}/*.dll")
644+
foreach(_dll ${_chrono_dlls})
645+
message(STATUS " Chrono DLL ${_dll}")
646+
install(FILES "${_dll}" DESTINATION bin COMPONENT runtime)
647+
endforeach()
648+
endif()
635649

636650
# HDF5 DLLs
637651
foreach(tgt ${HDF5_TARGETS})
@@ -660,24 +674,42 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
660674
endif()
661675
endif()
662676

663-
# Python DLLs, if Chrono::Parsers depends on it
664-
if(CHRONO_PARSERS_PYTHON)
665-
find_package(Python3 QUIET COMPONENTS Interpreter Development)
666-
if(Python3_Interpreter_FOUND AND Python3_Development_FOUND)
667-
#message(STATUS "Found Python and dependencies")
668-
#message(STATUS " Python3_Interpreter_FOUND: ${Python3_Interpreter_FOUND}")
669-
#message(STATUS " Python3_Development_FOUND: ${Python3_Development_FOUND}")
670-
get_target_property(tgt_DLL Python3::Python IMPORTED_LOCATION_RELEASE)
671-
get_target_property(tgt_DLL_d Python3::Python IMPORTED_LOCATION_DEBUG)
672-
if(EXISTS ${tgt_DLL})
673-
message(STATUS " Python DLL ${tgt_DLL}")
674-
install(FILES ${tgt_DLL} DESTINATION bin COMPONENT runtime)
677+
# VSG DLLs (vsg, vsgImGui, vsgXchange, draco, etc.)
678+
if(HYDROCHRONO_ENABLE_VSG)
679+
# VSG_DLL_DIR is set by Chrono's find_package when VSG is found
680+
# Fall back to deriving from vsg_DIR if VSG_DLL_DIR is not set
681+
if(NOT DEFINED VSG_DLL_DIR OR VSG_DLL_DIR STREQUAL "")
682+
if(DEFINED vsg_DIR)
683+
# vsg_DIR points to lib/cmake/vsg, go up 3 levels to root then into bin
684+
get_filename_component(_vsg_root "${vsg_DIR}" DIRECTORY) # lib/cmake
685+
get_filename_component(_vsg_root "${_vsg_root}" DIRECTORY) # lib
686+
get_filename_component(_vsg_root "${_vsg_root}" DIRECTORY) # root
687+
set(VSG_DLL_DIR "${_vsg_root}/bin")
675688
endif()
676-
if(EXISTS ${tgt_DLL_d})
677-
install(FILES ${tgt_DLL_d} DESTINATION bin COMPONENT runtime)
689+
endif()
690+
691+
if(DEFINED VSG_DLL_DIR AND EXISTS "${VSG_DLL_DIR}")
692+
file(GLOB _vsg_dlls "${VSG_DLL_DIR}/*.dll")
693+
if(_vsg_dlls)
694+
message(STATUS "Installing VSG DLLs from: ${VSG_DLL_DIR}")
695+
install(FILES ${_vsg_dlls} DESTINATION bin COMPONENT runtime)
678696
endif()
697+
else()
698+
message(WARNING "HYDROCHRONO_ENABLE_VSG is ON but VSG_DLL_DIR not found. VSG DLLs will not be packaged.")
679699
endif()
680700
endif()
701+
702+
# Python DLLs, if Chrono::Parsers depends on it.
703+
# Derive the DLL path from the already-found interpreter rather than calling
704+
# find_package(Python3 ... Development), which can stall on Windows/conda.
705+
if(CHRONO_PARSERS_PYTHON AND Python3_EXECUTABLE)
706+
get_filename_component(_py_bin_dir "${Python3_EXECUTABLE}" DIRECTORY)
707+
file(GLOB _py_dlls "${_py_bin_dir}/python3*.dll")
708+
foreach(_py_dll ${_py_dlls})
709+
message(STATUS " Python DLL ${_py_dll}")
710+
install(FILES "${_py_dll}" DESTINATION bin COMPONENT runtime)
711+
endforeach()
712+
endif()
681713

682714
endif()
683715

@@ -699,6 +731,20 @@ install(PROGRAMS ${PROJECT_SOURCE_DIR}/scripts/RUN-TESTS.ps1
699731
DESTINATION tests COMPONENT python-tests)
700732

701733
# MSVC runtime DLLs and ZIP packaging via CPack
734+
# InstallRequiredSystemLibraries handles msvcp/vcruntime/ucrt, but not vcomp (OpenMP).
735+
# Append the OpenMP runtime so it's included in the package.
736+
if(MSVC AND OpenMP_CXX_FOUND)
737+
get_filename_component(_msvc_dir "${CMAKE_CXX_COMPILER}" DIRECTORY)
738+
find_file(_vcomp_dll "vcomp140.dll"
739+
PATHS "${_msvc_dir}" "${_msvc_dir}/../../../redist/x64" "C:/Windows/System32"
740+
NO_DEFAULT_PATH)
741+
if(_vcomp_dll)
742+
list(APPEND CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS "${_vcomp_dll}")
743+
message(STATUS " OpenMP DLL ${_vcomp_dll}")
744+
else()
745+
message(WARNING "vcomp140.dll not found — OpenMP runtime will be missing from package")
746+
endif()
747+
endif()
702748
include(InstallRequiredSystemLibraries)
703749
set(CPACK_GENERATOR "ZIP")
704750
set(CPACK_PACKAGE_NAME "HydroChrono")

build.ps1

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<#
1+
<#
22
HydroChrono Build Script
33
44
Configures and builds HydroChrono. Dependency paths (Eigen, HDF5, Irrlicht)
@@ -250,7 +250,7 @@ if ($LASTEXITCODE -ne 0) {
250250
Write-OK "Built in $buildSecs seconds"
251251

252252
# =============================================================================
253-
# Copy Third-Party DLLs (Irrlicht - not handled by Chrono's DLL copy command)
253+
# Copy Third-Party DLLs (not handled by Chrono's DLL copy command)
254254
# =============================================================================
255255

256256
$binPath = ".\build\bin\$BuildType"
@@ -269,6 +269,43 @@ if ($useIrrlicht) {
269269
}
270270
}
271271

272+
if ($useVSG) {
273+
# Get VSG DLL directory from Chrono config (set by find_package(vsg))
274+
# VSG_DLL_DIR is set by Chrono when it finds VSG
275+
$vsgDllDir = $null
276+
277+
if ($chronoContent -match 'VSG_DLL_DIR\s+([^\s\)]+)') {
278+
$vsgDllDir = $Matches[1].Trim('"')
279+
}
280+
281+
# Fallback: derive from vsg_DIR (lib/cmake/vsg -> bin)
282+
if (-not $vsgDllDir -or -not (Test-Path $vsgDllDir)) {
283+
if ($chronoContent -match 'vsg_DIR\s+"([^"]+)"') {
284+
$vsgCmakeDir = $Matches[1]
285+
# Go up from lib/cmake/vsg to root, then into bin
286+
$vsgRoot = Split-Path (Split-Path (Split-Path $vsgCmakeDir))
287+
$vsgDllDir = Join-Path $vsgRoot "bin"
288+
}
289+
}
290+
291+
if ($vsgDllDir -and (Test-Path $vsgDllDir)) {
292+
$vsgDlls = Get-ChildItem -Path $vsgDllDir -Filter "*.dll" -ErrorAction SilentlyContinue
293+
$copiedCount = 0
294+
foreach ($dll in $vsgDlls) {
295+
$destDll = Join-Path $binPath $dll.Name
296+
if (-not (Test-Path $destDll)) {
297+
Copy-Item $dll.FullName $destDll -Force
298+
$copiedCount++
299+
}
300+
}
301+
if ($copiedCount -gt 0) {
302+
Write-OK "Copied $copiedCount VSG DLLs from $vsgDllDir"
303+
}
304+
} else {
305+
Write-Warn "VSG enabled but could not find VSG DLL directory"
306+
}
307+
}
308+
272309
# =============================================================================
273310
# Verify
274311
# =============================================================================
@@ -325,4 +362,6 @@ Write-Host "========================================`n" -ForegroundColor Green
325362

326363
Write-Host "Output: $binPath" -ForegroundColor Cyan
327364
Write-Host "Tests: ctest -C $BuildType -L regression --test-dir build" -ForegroundColor Gray
365+
Write-Host " ctest -C $BuildType -L unit --test-dir build" -ForegroundColor Gray
366+
Write-Host " Add -V for verbose output, --output-on-failure for failures only" -ForegroundColor DarkGray
328367
Write-Host ""

data/textures/water_grid.png

961 Bytes
Loading

demos/DeepCWind/demo_DeepCWind_decay.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,7 @@ int main(int argc, char* argv[]) {
4141
system.SetGravitationalAcceleration(ChVector3d(0.0, 0.0, -9.81));
4242
double timestep = 0.08;
4343
system.SetTimestepperType(ChTimestepper::Type::HHT);
44-
system.SetSolverType(ChSolver::Type::GMRES);
45-
system.GetSolver()->AsIterative()->SetMaxIterations(
46-
300); // the higher, the easier to keep the constraints satisfied.
44+
system.SetSolverType(ChSolver::Type::SPARSE_QR);
4745
double simulationDuration = 1000.0;
4846

4947
// Create user interface

demos/oswec/demo_oswec_reg_waves.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ int main(int argc, char* argv[]) {
215215
// main simulation loop
216216
ui.Init(&system, "OSWEC - Regular Waves");
217217
ui.SetCamera(0, -50, -10, 0, 0, -10);
218+
ui.SetWaveModel(my_hydro_inputs); // Enable animated water surface
218219

219220
while (system.GetChTime() <= simulationDuration) {
220221
if (ui.IsRunning(timestep) == false) break;

demos/rm3/demo_rm3_decay.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@ int main(int argc, char* argv[]) {
4545

4646
double timestep = 0.01;
4747
system.SetTimestepperType(ChTimestepper::Type::HHT);
48-
system.SetSolverType(ChSolver::Type::GMRES);
49-
system.GetSolver()->AsIterative()->SetMaxIterations(
50-
300); // the higher, the easier to keep the constraints satisfied.
48+
system.SetSolverType(ChSolver::Type::SPARSE_QR);
5149
ChRealtimeStepTimer realtime_timer;
5250
double simulationDuration = 40.0;
5351

demos/rm3/demo_rm3_reg_waves.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,7 @@ int main(int argc, char* argv[]) {
5656
system.SetGravitationalAcceleration(ChVector3d(0.0, 0.0, -9.81));
5757
double timestep = 0.01;
5858
system.SetTimestepperType(ChTimestepper::Type::HHT);
59-
system.SetSolverType(ChSolver::Type::GMRES);
60-
system.GetSolver()->AsIterative()->SetMaxIterations(
61-
300); // the higher, the easier to keep the constraints satisfied.
59+
system.SetSolverType(ChSolver::Type::SPARSE_QR);
6260
ChRealtimeStepTimer realtime_timer;
6361
double simulationDuration = 40.0;
6462

@@ -148,6 +146,7 @@ int main(int argc, char* argv[]) {
148146
// main simulation loop
149147
ui.Init(&system, "RM3 - Regular Wave Test");
150148
ui.SetCamera(0, -50, -10, 0, 0, -10);
149+
ui.SetWaveModel(my_hydro_inputs); // Enable animated water surface
151150

152151
while (system.GetChTime() <= simulationDuration) {
153152
if (ui.IsRunning(timestep) == false) break;

demos/sphere/demo_sphere_decay.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ int main(int argc, char* argv[]) {
4343
system.SetGravitationalAcceleration(ChVector3d(0.0, 0.0, -9.81));
4444

4545
double timestep = 0.015;
46-
system.SetSolverType(ChSolver::Type::GMRES);
47-
system.GetSolver()->AsIterative()->SetMaxIterations(
48-
300); // the higher, the easier to keep the constraints satisfied.
46+
system.SetSolverType(ChSolver::Type::SPARSE_QR);
4947
ChRealtimeStepTimer realtime_timer;
5048
double simulationDuration = 40.0;
5149

demos/sphere/demo_sphere_irreg_waves.cpp

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ int main(int argc, char* argv[]) {
3939
ChSystemNSC system;
4040
system.SetGravitationalAcceleration(ChVector3d(0.0, 0.0, -9.81));
4141
double timestep = 0.015;
42-
system.SetSolverType(ChSolver::Type::GMRES);
43-
system.GetSolver()->AsIterative()->SetMaxIterations(300);
42+
system.SetSolverType(ChSolver::Type::SPARSE_QR);
4443
ChRealtimeStepTimer realtime_timer;
4544
double simulationDuration = 600.0;
4645

@@ -127,39 +126,12 @@ int main(int argc, char* argv[]) {
127126
TestHydro hydro_forces(bodies, h5fname);
128127
hydro_forces.AddWaves(my_hydro_inputs);
129128

130-
// set up free surface from a mesh
131-
auto fse_plane = chrono_types::make_shared<ChBody>();
132-
fse_plane->SetPos(ChVector3d(0, 0, 0));
133-
fse_plane->SetFixed(true);
134-
fse_plane->EnableCollision(false);
135-
system.AddBody(fse_plane);
136-
137-
my_hydro_inputs->SetUpWaveMesh();
138-
std::shared_ptr<ChBody> fse_mesh = chrono_types::make_shared<ChBodyEasyMesh>( //
139-
my_hydro_inputs->GetMeshFile(), // file name
140-
1000, // density
141-
false, // do not evaluate mass automatically
142-
true, // create visualization asset
143-
false // do not collide
144-
);
145-
fse_mesh->SetMass(1.0);
146-
fse_mesh->SetPosDt(my_hydro_inputs->GetWaveMeshVelocity());
147-
system.Add(fse_mesh);
148-
auto fse_prismatic = chrono_types::make_shared<ChLinkLockPrismatic>();
149-
fse_prismatic->Initialize(fse_plane, fse_mesh, ChFramed(ChVector3d(1.0, 0.0, 0.0), QuatFromAngleY(CH_PI_2)));
150-
system.AddLink(fse_prismatic);
151-
152-
// Create a visualization material
153-
auto fse_texture = chrono_types::make_shared<ChVisualMaterial>();
154-
fse_texture->SetDiffuseColor(ChColor(0.026f, 0.084f, 0.168f));
155-
fse_texture->SetOpacity(0.1f);
156-
fse_mesh->GetVisualShape(0)->SetMaterial(0, fse_texture);
157-
158129
// for profiling
159130
auto start = std::chrono::high_resolution_clock::now();
160131
// main simulation loop
161132
ui.Init(&system, "Sphere - Irregular Waves Test");
162133
ui.SetCamera(8, -25, 15, 0, 0, 0);
134+
ui.SetWaveModel(my_hydro_inputs); // Enable animated water surface
163135

164136
while (system.GetChTime() <= simulationDuration) {
165137
if (ui.IsRunning(timestep) == false) break;

0 commit comments

Comments
 (0)