From ed5d806b4d0d2e523b94e455b625521345106d20 Mon Sep 17 00:00:00 2001 From: Xiangyu Hu Date: Thu, 23 Sep 2021 11:31:28 +0200 Subject: [PATCH 01/41] delete static library for windows --- tests/2d_examples/test_1d_shock_tube/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_T_shaped_pipe/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_airfoil/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_collision/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_dambreak/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_depolarization/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_diffusion/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_elastic_gate/src/CMakeLists.txt | 2 +- .../test_2d_eulerian_taylor_green/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_filling_tank/src/CMakeLists.txt | 2 +- .../test_2d_flow_around_cylinder/src/CMakeLists.txt | 2 +- .../test_2d_free_stream_around_cylinder/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_fsi2/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_heat_transfer/src/CMakeLists.txt | 2 +- .../2d_examples/test_2d_hydrostatic_fsi/src/CMakeLists.txt | 2 +- .../2d_examples/test_2d_oscillating_beam/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_owsc/src/CMakeLists.txt | 2 +- .../CMakeLists.txt | 2 +- tests/2d_examples/test_2d_plate/src/CMakeLists.txt | 2 +- .../2d_examples/test_2d_poiseuille_flow/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_self_contact/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_shell/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_sliding/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_square_droplet/src/CMakeLists.txt | 2 +- .../test_2d_static_confinement/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_taylor_green/src/CMakeLists.txt | 2 +- .../test_2d_tethered_dead_fish_in_flow/src/CMakeLists.txt | 2 +- tests/2d_examples/test_2d_throat/src/CMakeLists.txt | 2 +- .../test_2d_two_phase_dambreak/src/CMakeLists.txt | 2 +- .../2d_examples/test_2d_wetting_effects/src/CMakeLists.txt | 2 +- tests/3d_examples/test_3d_arch/src/CMakeLists.txt | 2 +- tests/3d_examples/test_3d_bernoulli_beam/src/CMakeLists.txt | 2 +- tests/3d_examples/test_3d_dambreak/src/CMakeLists.txt | 2 +- .../test_3d_heart_electromechanics/CMakeLists.txt | 2 +- tests/3d_examples/test_3d_load_image/CMakeLists.txt | 2 +- .../test_3d_muscle_compression/src/CMakeLists.txt | 2 +- .../src/CMakeLists.txt | 2 +- tests/3d_examples/test_3d_myocaridum/src/CMakeLists.txt | 2 +- tests/3d_examples/test_3d_network/CMakeLists.txt | 2 +- .../3d_examples/test_3d_particle_generation/CMakeLists.txt | 2 +- .../CMakeLists.txt | 2 +- .../test_3d_passive_cantilever/src/CMakeLists.txt | 2 +- .../src/CMakeLists.txt | 2 +- .../test_3d_pkj_lv_electrocontraction/CMakeLists.txt | 2 +- tests/3d_examples/test_3d_play_simbody/src/CMakeLists.txt | 2 +- tests/3d_examples/test_3d_roof/src/CMakeLists.txt | 2 +- tests/3d_examples/test_3d_self_contact/CMakeLists.txt | 2 +- tests/3d_examples/test_3d_taylor_bar/src/CMakeLists.txt | 2 +- tests/3d_examples/test_3d_thin_plate/src/CMakeLists.txt | 2 +- .../3d_examples/test_3d_twisting_column/src/CMakeLists.txt | 2 +- tests/unit_tests_src/shared/common/CMakeLists.txt | 6 +++--- 51 files changed, 53 insertions(+), 53 deletions(-) diff --git a/tests/2d_examples/test_1d_shock_tube/src/CMakeLists.txt b/tests/2d_examples/test_1d_shock_tube/src/CMakeLists.txt index 7c41d09d48..b35ce4f59a 100644 --- a/tests/2d_examples/test_1d_shock_tube/src/CMakeLists.txt +++ b/tests/2d_examples/test_1d_shock_tube/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_T_shaped_pipe/src/CMakeLists.txt b/tests/2d_examples/test_2d_T_shaped_pipe/src/CMakeLists.txt index 6d1d678de7..d15ad20ca2 100644 --- a/tests/2d_examples/test_2d_T_shaped_pipe/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_T_shaped_pipe/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_airfoil/CMakeLists.txt b/tests/2d_examples/test_2d_airfoil/CMakeLists.txt index 876a315d73..04720eb204 100644 --- a/tests/2d_examples/test_2d_airfoil/CMakeLists.txt +++ b/tests/2d_examples/test_2d_airfoil/CMakeLists.txt @@ -31,7 +31,7 @@ add_test(NAME ${PROJECT_NAME}_particle_relaxation if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_collision/src/CMakeLists.txt b/tests/2d_examples/test_2d_collision/src/CMakeLists.txt index ee0c2a544e..cdcb49dc95 100644 --- a/tests/2d_examples/test_2d_collision/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_collision/src/CMakeLists.txt @@ -15,7 +15,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME} --r=false --i=true) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_dambreak/src/CMakeLists.txt b/tests/2d_examples/test_2d_dambreak/src/CMakeLists.txt index 792c519dc5..4d7ce4ad23 100644 --- a/tests/2d_examples/test_2d_dambreak/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_dambreak/src/CMakeLists.txt @@ -15,7 +15,7 @@ add_test(NAME ${PROJECT_NAME}_restart COMMAND ${PROJECT_NAME} --restart_step=400 if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_depolarization/src/CMakeLists.txt b/tests/2d_examples/test_2d_depolarization/src/CMakeLists.txt index 6d1d678de7..d15ad20ca2 100644 --- a/tests/2d_examples/test_2d_depolarization/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_depolarization/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_diffusion/src/CMakeLists.txt b/tests/2d_examples/test_2d_diffusion/src/CMakeLists.txt index 6d1d678de7..d15ad20ca2 100644 --- a/tests/2d_examples/test_2d_diffusion/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_diffusion/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_elastic_gate/src/CMakeLists.txt b/tests/2d_examples/test_2d_elastic_gate/src/CMakeLists.txt index 6d1d678de7..d15ad20ca2 100644 --- a/tests/2d_examples/test_2d_elastic_gate/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_elastic_gate/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_eulerian_taylor_green/src/CMakeLists.txt b/tests/2d_examples/test_2d_eulerian_taylor_green/src/CMakeLists.txt index 6d1d678de7..d15ad20ca2 100644 --- a/tests/2d_examples/test_2d_eulerian_taylor_green/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_eulerian_taylor_green/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_filling_tank/src/CMakeLists.txt b/tests/2d_examples/test_2d_filling_tank/src/CMakeLists.txt index 3cddf16b63..ec6b8506ff 100644 --- a/tests/2d_examples/test_2d_filling_tank/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_filling_tank/src/CMakeLists.txt @@ -15,7 +15,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_flow_around_cylinder/src/CMakeLists.txt b/tests/2d_examples/test_2d_flow_around_cylinder/src/CMakeLists.txt index 59688b721c..758f9a8c08 100644 --- a/tests/2d_examples/test_2d_flow_around_cylinder/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_flow_around_cylinder/src/CMakeLists.txt @@ -26,7 +26,7 @@ add_test(NAME ${PROJECT_NAME} if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_free_stream_around_cylinder/src/CMakeLists.txt b/tests/2d_examples/test_2d_free_stream_around_cylinder/src/CMakeLists.txt index 59688b721c..758f9a8c08 100644 --- a/tests/2d_examples/test_2d_free_stream_around_cylinder/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_free_stream_around_cylinder/src/CMakeLists.txt @@ -26,7 +26,7 @@ add_test(NAME ${PROJECT_NAME} if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_fsi2/src/CMakeLists.txt b/tests/2d_examples/test_2d_fsi2/src/CMakeLists.txt index ee0c2a544e..cdcb49dc95 100644 --- a/tests/2d_examples/test_2d_fsi2/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_fsi2/src/CMakeLists.txt @@ -15,7 +15,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME} --r=false --i=true) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_heat_transfer/src/CMakeLists.txt b/tests/2d_examples/test_2d_heat_transfer/src/CMakeLists.txt index 7c41d09d48..b35ce4f59a 100644 --- a/tests/2d_examples/test_2d_heat_transfer/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_heat_transfer/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_hydrostatic_fsi/src/CMakeLists.txt b/tests/2d_examples/test_2d_hydrostatic_fsi/src/CMakeLists.txt index 7c41d09d48..b35ce4f59a 100644 --- a/tests/2d_examples/test_2d_hydrostatic_fsi/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_hydrostatic_fsi/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_oscillating_beam/src/CMakeLists.txt b/tests/2d_examples/test_2d_oscillating_beam/src/CMakeLists.txt index 6d1d678de7..d15ad20ca2 100644 --- a/tests/2d_examples/test_2d_oscillating_beam/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_oscillating_beam/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_owsc/src/CMakeLists.txt b/tests/2d_examples/test_2d_owsc/src/CMakeLists.txt index 3d4b0dc897..689d62b392 100644 --- a/tests/2d_examples/test_2d_owsc/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_owsc/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_particle_generator_single_resolution/CMakeLists.txt b/tests/2d_examples/test_2d_particle_generator_single_resolution/CMakeLists.txt index 823b8beca3..1e46ff496d 100644 --- a/tests/2d_examples/test_2d_particle_generator_single_resolution/CMakeLists.txt +++ b/tests/2d_examples/test_2d_particle_generator_single_resolution/CMakeLists.txt @@ -23,7 +23,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_plate/src/CMakeLists.txt b/tests/2d_examples/test_2d_plate/src/CMakeLists.txt index 6d1d678de7..d15ad20ca2 100644 --- a/tests/2d_examples/test_2d_plate/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_plate/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_poiseuille_flow/src/CMakeLists.txt b/tests/2d_examples/test_2d_poiseuille_flow/src/CMakeLists.txt index 6d1d678de7..d15ad20ca2 100644 --- a/tests/2d_examples/test_2d_poiseuille_flow/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_poiseuille_flow/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_self_contact/src/CMakeLists.txt b/tests/2d_examples/test_2d_self_contact/src/CMakeLists.txt index 6d1d678de7..d15ad20ca2 100644 --- a/tests/2d_examples/test_2d_self_contact/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_self_contact/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_shell/src/CMakeLists.txt b/tests/2d_examples/test_2d_shell/src/CMakeLists.txt index 6d1d678de7..d15ad20ca2 100644 --- a/tests/2d_examples/test_2d_shell/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_shell/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_sliding/src/CMakeLists.txt b/tests/2d_examples/test_2d_sliding/src/CMakeLists.txt index 7c41d09d48..b35ce4f59a 100644 --- a/tests/2d_examples/test_2d_sliding/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_sliding/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_square_droplet/src/CMakeLists.txt b/tests/2d_examples/test_2d_square_droplet/src/CMakeLists.txt index 7c41d09d48..b35ce4f59a 100644 --- a/tests/2d_examples/test_2d_square_droplet/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_square_droplet/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_static_confinement/src/CMakeLists.txt b/tests/2d_examples/test_2d_static_confinement/src/CMakeLists.txt index 7c41d09d48..b35ce4f59a 100644 --- a/tests/2d_examples/test_2d_static_confinement/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_static_confinement/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_taylor_green/src/CMakeLists.txt b/tests/2d_examples/test_2d_taylor_green/src/CMakeLists.txt index 4e870b41a2..c9aec3a5c4 100644 --- a/tests/2d_examples/test_2d_taylor_green/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_taylor_green/src/CMakeLists.txt @@ -15,7 +15,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME} --i=true) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_tethered_dead_fish_in_flow/src/CMakeLists.txt b/tests/2d_examples/test_2d_tethered_dead_fish_in_flow/src/CMakeLists.txt index ffa856d55e..849def5262 100644 --- a/tests/2d_examples/test_2d_tethered_dead_fish_in_flow/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_tethered_dead_fish_in_flow/src/CMakeLists.txt @@ -12,7 +12,7 @@ ADD_EXECUTABLE(${PROJECT_NAME} ${DIR_SRCS}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_throat/src/CMakeLists.txt b/tests/2d_examples/test_2d_throat/src/CMakeLists.txt index 6d1d678de7..d15ad20ca2 100644 --- a/tests/2d_examples/test_2d_throat/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_throat/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_two_phase_dambreak/src/CMakeLists.txt b/tests/2d_examples/test_2d_two_phase_dambreak/src/CMakeLists.txt index 7c41d09d48..b35ce4f59a 100644 --- a/tests/2d_examples/test_2d_two_phase_dambreak/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_two_phase_dambreak/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/2d_examples/test_2d_wetting_effects/src/CMakeLists.txt b/tests/2d_examples/test_2d_wetting_effects/src/CMakeLists.txt index 7c41d09d48..b35ce4f59a 100644 --- a/tests/2d_examples/test_2d_wetting_effects/src/CMakeLists.txt +++ b/tests/2d_examples/test_2d_wetting_effects/src/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES}) - add_dependencies(${PROJECT_NAME} sphinxsys_2d sphinxsys_static_2d) + add_dependencies(${PROJECT_NAME} sphinxsys_2d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_2d ${TBB_LIBRARYS} ${Simbody_LIBRARIES} ${Boost_LIBRARIES} stdc++) diff --git a/tests/3d_examples/test_3d_arch/src/CMakeLists.txt b/tests/3d_examples/test_3d_arch/src/CMakeLists.txt index 3a9bd0f30f..889f0c52c4 100644 --- a/tests/3d_examples/test_3d_arch/src/CMakeLists.txt +++ b/tests/3d_examples/test_3d_arch/src/CMakeLists.txt @@ -16,7 +16,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_bernoulli_beam/src/CMakeLists.txt b/tests/3d_examples/test_3d_bernoulli_beam/src/CMakeLists.txt index eb668a2d6d..dd220d0d10 100644 --- a/tests/3d_examples/test_3d_bernoulli_beam/src/CMakeLists.txt +++ b/tests/3d_examples/test_3d_bernoulli_beam/src/CMakeLists.txt @@ -16,7 +16,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_3d gtest gtest_main) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++ gtest gtest_main) diff --git a/tests/3d_examples/test_3d_dambreak/src/CMakeLists.txt b/tests/3d_examples/test_3d_dambreak/src/CMakeLists.txt index b6601ac6cd..69337e09a2 100644 --- a/tests/3d_examples/test_3d_dambreak/src/CMakeLists.txt +++ b/tests/3d_examples/test_3d_dambreak/src/CMakeLists.txt @@ -15,7 +15,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_heart_electromechanics/CMakeLists.txt b/tests/3d_examples/test_3d_heart_electromechanics/CMakeLists.txt index eafcef5d46..3fae0d1f8b 100644 --- a/tests/3d_examples/test_3d_heart_electromechanics/CMakeLists.txt +++ b/tests/3d_examples/test_3d_heart_electromechanics/CMakeLists.txt @@ -31,7 +31,7 @@ if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_load_image/CMakeLists.txt b/tests/3d_examples/test_3d_load_image/CMakeLists.txt index 633cd83a21..6aeb385b19 100644 --- a/tests/3d_examples/test_3d_load_image/CMakeLists.txt +++ b/tests/3d_examples/test_3d_load_image/CMakeLists.txt @@ -31,7 +31,7 @@ if(NOT SPH_ONLY_STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_muscle_compression/src/CMakeLists.txt b/tests/3d_examples/test_3d_muscle_compression/src/CMakeLists.txt index e87cdaa0ab..6e5c02f531 100644 --- a/tests/3d_examples/test_3d_muscle_compression/src/CMakeLists.txt +++ b/tests/3d_examples/test_3d_muscle_compression/src/CMakeLists.txt @@ -16,7 +16,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_muscle_compression_soft_body_contact/src/CMakeLists.txt b/tests/3d_examples/test_3d_muscle_compression_soft_body_contact/src/CMakeLists.txt index 3a9bd0f30f..889f0c52c4 100644 --- a/tests/3d_examples/test_3d_muscle_compression_soft_body_contact/src/CMakeLists.txt +++ b/tests/3d_examples/test_3d_muscle_compression_soft_body_contact/src/CMakeLists.txt @@ -16,7 +16,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_myocaridum/src/CMakeLists.txt b/tests/3d_examples/test_3d_myocaridum/src/CMakeLists.txt index 3a9bd0f30f..889f0c52c4 100644 --- a/tests/3d_examples/test_3d_myocaridum/src/CMakeLists.txt +++ b/tests/3d_examples/test_3d_myocaridum/src/CMakeLists.txt @@ -16,7 +16,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_network/CMakeLists.txt b/tests/3d_examples/test_3d_network/CMakeLists.txt index 55594d66bf..8bb49d853a 100644 --- a/tests/3d_examples/test_3d_network/CMakeLists.txt +++ b/tests/3d_examples/test_3d_network/CMakeLists.txt @@ -27,7 +27,7 @@ if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_particle_generation/CMakeLists.txt b/tests/3d_examples/test_3d_particle_generation/CMakeLists.txt index 7ae44d74b9..62d4098e22 100644 --- a/tests/3d_examples/test_3d_particle_generation/CMakeLists.txt +++ b/tests/3d_examples/test_3d_particle_generation/CMakeLists.txt @@ -29,7 +29,7 @@ if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_particle_generator_single_resolution/CMakeLists.txt b/tests/3d_examples/test_3d_particle_generator_single_resolution/CMakeLists.txt index 226d5c04b0..2f949ac9c1 100644 --- a/tests/3d_examples/test_3d_particle_generator_single_resolution/CMakeLists.txt +++ b/tests/3d_examples/test_3d_particle_generator_single_resolution/CMakeLists.txt @@ -29,7 +29,7 @@ if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_passive_cantilever/src/CMakeLists.txt b/tests/3d_examples/test_3d_passive_cantilever/src/CMakeLists.txt index 6dd12d41de..80abbca238 100644 --- a/tests/3d_examples/test_3d_passive_cantilever/src/CMakeLists.txt +++ b/tests/3d_examples/test_3d_passive_cantilever/src/CMakeLists.txt @@ -16,7 +16,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_passive_cantilever_neohookean/src/CMakeLists.txt b/tests/3d_examples/test_3d_passive_cantilever_neohookean/src/CMakeLists.txt index e3bdd1045b..bdae0a29eb 100644 --- a/tests/3d_examples/test_3d_passive_cantilever_neohookean/src/CMakeLists.txt +++ b/tests/3d_examples/test_3d_passive_cantilever_neohookean/src/CMakeLists.txt @@ -20,7 +20,7 @@ else() if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_pkj_lv_electrocontraction/CMakeLists.txt b/tests/3d_examples/test_3d_pkj_lv_electrocontraction/CMakeLists.txt index a80b5e88ad..e01d972224 100644 --- a/tests/3d_examples/test_3d_pkj_lv_electrocontraction/CMakeLists.txt +++ b/tests/3d_examples/test_3d_pkj_lv_electrocontraction/CMakeLists.txt @@ -31,7 +31,7 @@ if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_play_simbody/src/CMakeLists.txt b/tests/3d_examples/test_3d_play_simbody/src/CMakeLists.txt index 82f4ca5bc6..11454d3b4c 100644 --- a/tests/3d_examples/test_3d_play_simbody/src/CMakeLists.txt +++ b/tests/3d_examples/test_3d_play_simbody/src/CMakeLists.txt @@ -13,7 +13,7 @@ ADD_EXECUTABLE(${PROJECT_NAME} ${DIR_SRCS}) if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_roof/src/CMakeLists.txt b/tests/3d_examples/test_3d_roof/src/CMakeLists.txt index 7b97c368ae..c75151074f 100644 --- a/tests/3d_examples/test_3d_roof/src/CMakeLists.txt +++ b/tests/3d_examples/test_3d_roof/src/CMakeLists.txt @@ -16,7 +16,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_self_contact/CMakeLists.txt b/tests/3d_examples/test_3d_self_contact/CMakeLists.txt index 3ee5bf7852..9e650b685b 100644 --- a/tests/3d_examples/test_3d_self_contact/CMakeLists.txt +++ b/tests/3d_examples/test_3d_self_contact/CMakeLists.txt @@ -31,7 +31,7 @@ if(NOT SPH_ONLY_STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_taylor_bar/src/CMakeLists.txt b/tests/3d_examples/test_3d_taylor_bar/src/CMakeLists.txt index 67929c3a11..4ca15feba1 100644 --- a/tests/3d_examples/test_3d_taylor_bar/src/CMakeLists.txt +++ b/tests/3d_examples/test_3d_taylor_bar/src/CMakeLists.txt @@ -17,7 +17,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME} --r=false --i=true) if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_thin_plate/src/CMakeLists.txt b/tests/3d_examples/test_3d_thin_plate/src/CMakeLists.txt index 7b97c368ae..c75151074f 100644 --- a/tests/3d_examples/test_3d_thin_plate/src/CMakeLists.txt +++ b/tests/3d_examples/test_3d_thin_plate/src/CMakeLists.txt @@ -16,7 +16,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/3d_examples/test_3d_twisting_column/src/CMakeLists.txt b/tests/3d_examples/test_3d_twisting_column/src/CMakeLists.txt index 7b97c368ae..c75151074f 100644 --- a/tests/3d_examples/test_3d_twisting_column/src/CMakeLists.txt +++ b/tests/3d_examples/test_3d_twisting_column/src/CMakeLists.txt @@ -16,7 +16,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) if(NOT STATIC_BUILD) # usual dynamic build if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(${PROJECT_NAME} sphinxsys_3d) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) diff --git a/tests/unit_tests_src/shared/common/CMakeLists.txt b/tests/unit_tests_src/shared/common/CMakeLists.txt index 5397b47e8a..cfd535a38b 100644 --- a/tests/unit_tests_src/shared/common/CMakeLists.txt +++ b/tests/unit_tests_src/shared/common/CMakeLists.txt @@ -28,10 +28,10 @@ if(NOT SPH_ONLY_STATIC_BUILD) # usual dynamic build set_target_properties(${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}") IF(${CMAKE_BUILD_TYPE} MATCHES "Release") target_link_libraries(${PROJECT_NAME} sphinxsys_3d gtest gtest_main) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) elseif(${CMAKE_BUILD_TYPE} MATCHES "Debug") target_link_libraries(${PROJECT_NAME} sphinxsys_3d gtestd gtest_maind) - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) endif() else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") @@ -46,7 +46,7 @@ if(NOT SPH_ONLY_STATIC_BUILD) # usual dynamic build endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") else() # static build only if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d) target_link_libraries(${PROJECT_NAME} sphinxsys_static_3d gtest gtest_main) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") From 694b9d464262fb8b8d0a262fa146c78244dbb1cc Mon Sep 17 00:00:00 2001 From: Xiangyu Hu Date: Thu, 23 Sep 2021 19:26:05 +0200 Subject: [PATCH 02/41] -werror not valid for windows --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4fc69b795c..20bc032f35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,7 +94,9 @@ else() endif() if(NOT BUILD_WITH_SIMBODY) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") + if(NOT MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") + endif() endif() add_compile_definitions(TBB_SUPPRESS_DEPRECATED_MESSAGES=1) From 22cba7fb8eb132826952cd2ea0ab84ce1708b93f Mon Sep 17 00:00:00 2001 From: Xiangyu Hu Date: Thu, 23 Sep 2021 19:56:00 +0200 Subject: [PATCH 03/41] function incompatibility between windows and linux --- .../particle_dynamics/solid_dynamics/solid_dynamics.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SPHINXsys/src/shared/particle_dynamics/solid_dynamics/solid_dynamics.cpp b/SPHINXsys/src/shared/particle_dynamics/solid_dynamics/solid_dynamics.cpp index 411ff8bcc4..7e4b049fe9 100644 --- a/SPHINXsys/src/shared/particle_dynamics/solid_dynamics/solid_dynamics.cpp +++ b/SPHINXsys/src/shared/particle_dynamics/solid_dynamics/solid_dynamics.cpp @@ -6,6 +6,8 @@ #include "solid_dynamics.h" #include "general_dynamics.h" +#include + using namespace SimTK; namespace SPH @@ -537,7 +539,7 @@ namespace SPH void ForceInBodyRegion::Update(size_t index_i, Real dt) { try{ - Real time_factor = std::min(GlobalStaticVariables::physical_time_ / end_time_, 1.0); + Real time_factor = SMIN(GlobalStaticVariables::physical_time_ / end_time_, 1.0); dvel_dt_prior_[index_i] = acceleration_ * time_factor; } catch(out_of_range& e){ From ced32844c88fd5b9857edc985361ea9c1d411b02 Mon Sep 17 00:00:00 2001 From: Xiangyu Hu Date: Fri, 24 Sep 2021 13:00:11 +0200 Subject: [PATCH 04/41] windows compile pass --- SPHINXsys/src/for_2D_build/CMakeLists.txt | 7 +++---- SPHINXsys/src/for_3D_build/CMakeLists.txt | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/SPHINXsys/src/for_2D_build/CMakeLists.txt b/SPHINXsys/src/for_2D_build/CMakeLists.txt index 3e61835501..cdfdce1a83 100644 --- a/SPHINXsys/src/for_2D_build/CMakeLists.txt +++ b/SPHINXsys/src/for_2D_build/CMakeLists.txt @@ -50,12 +50,11 @@ FOREACH(srcdir_path ${sourcedirs}) ENDFOREACH() if(NOT STATIC_BUILD) - ### SPHinXsys dynamic lib ### - ADD_LIBRARY(sphinxsys_2d SHARED ${SCR_FILES}) - if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - #target_link_libraries(sphinxsys_3d) + ADD_LIBRARY(sphinxsys_2d ${SCR_FILES}) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + ### SPHinXsys dynamic lib ### + ADD_LIBRARY(sphinxsys_2d SHARED ${SCR_FILES}) if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(sphinxsys_2d stdc++) else(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") diff --git a/SPHINXsys/src/for_3D_build/CMakeLists.txt b/SPHINXsys/src/for_3D_build/CMakeLists.txt index 692cd083fe..eabd97cdf1 100644 --- a/SPHINXsys/src/for_3D_build/CMakeLists.txt +++ b/SPHINXsys/src/for_3D_build/CMakeLists.txt @@ -41,12 +41,11 @@ ENDFOREACH() SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) if(NOT STATIC_BUILD) - ### SPHinXsys dynamic lib ### - ADD_LIBRARY(sphinxsys_3d SHARED ${SCR_FILES}) - if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - #target_link_libraries(sphinxsys_3d) + ADD_LIBRARY(sphinxsys_3d ${SCR_FILES}) else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + ### SPHinXsys dynamic lib ### + ADD_LIBRARY(sphinxsys_3d SHARED ${SCR_FILES}) if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(sphinxsys_3d stdc++) else(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") From faa88cab07866f9ba5e370654ab3b515c46c6432 Mon Sep 17 00:00:00 2001 From: Bence Rochlitz <78215583+BenceVirtonomy@users.noreply.github.com> Date: Fri, 22 Oct 2021 18:04:43 +0200 Subject: [PATCH 05/41] Pull webassembly and recent changes (#67) * Verification cases thesis (#15) * ConstrainSolidBody renamed * constrain solid body reagion added * force boundary condition * force BC edited * Pressure bc (#16) * SurfacePressureFromSource added * SurfacePressureFromSource::Update * BC prob works but the particle normals are missing * time dependent surface pressure works * cube case moved to source tests * Add test folder (#18) * Translate body part (#45) * Feature/contact stent 2 (#10) * PositionSolidBody added * boundary condition works but breaks numerically * no message * first unit test added * indentation change * PositionSolidBody test * remove file * small fixes * position constraint changed works between start and end time * scaling boundary condition * PositionScaleSolidBody unit test * particel adaptation changed * system resolution ratio added to particle adaptation * add googletest to docker and workflow * unit test removed temporarily * unit rest removed * SolidParticleRelaxation added to update initial particle position * gtest added again * gtest install changed * gtest * gtest * gtest * gtest * cd path updated * change to shared pointers * unit test pointers changed * gtest added to docker * initialization changed * disable tests for simbody * errors fixed * TranslationSolidBody added; translation cylinder * whitespace * fixes * TranslateSolidBody corrected * writeToFile update * change SET to set * catch(out_of_range& e) added * change to size_t * cmake minimum removed * BoundingBox test changed * fix writeToFIle * test change * Feature/position bc stent (#34) * PositionSolidBody added * boundary condition works but breaks numerically * no message * first unit test added * indentation change * PositionSolidBody test * remove file * small fixes * position constraint changed works between start and end time * scaling boundary condition * PositionScaleSolidBody unit test * particel adaptation changed * system resolution ratio added to particle adaptation * add googletest to docker and workflow * unit test removed temporarily * unit rest removed * SolidParticleRelaxation added to update initial particle position * gtest added again * gtest install changed * gtest * gtest * gtest * gtest * cd path updated * change to shared pointers * unit test pointers changed * gtest added to docker * initialization changed * errors fixed * TranslationSolidBody added; translation cylinder * whitespace * fixes * TranslateSolidBody corrected * writeToFile update * change SET to set * catch(out_of_range& e) added * change to size_t * cmake minimum removed * BoundingBox test changed * fix writeToFIle * test change Co-authored-by: JohnVirtonomy * -Werror only works for linux * TEST TranslateSolidBodyTuple * Update CMakeLists.txt remove werror flag for msvc * update from bitbucket 01.07.2021 * delete repeated files * brief information on google test in repo readme * delete clapack and simbody folder in root * google test works for windows but the unit test case did not copy stl file right in windows * now test_3d_unit works in windows. * information on installing google test in windows * add a comment on install ing for VS in windows * translation with same scale&unit test update * skip testing when [ci skip] in the commit message * update test_3d_unit - TranslateSolidBody not work * time-dependent-contact * number of time dep. contacts fixed * setup unit test for time dependent contact * Translate Solid Body fixed but tolerance is only 0.01 * output changed to 100 files always * 07.13.2021 update * typo * new files from bitbucket * update 07.13.2021 * time dependent contact fixed * time dep contact fixed * remove cout * time dep. contact tests finished * renaming * fix naming * move test class into seperate header * cmake changes * changing function names to lower case * change cmake list * small fix Co-authored-by: Ubuntu Co-authored-by: JohnVirtonomy Co-authored-by: Xiangyu Hu Co-authored-by: Wen-Yang Chu Co-authored-by: Xiangyu Hu Co-authored-by: Xiangyu Hu <37415154+Xiangyu-Hu@users.noreply.github.com> * TranslateSolidBodyPart added * particle relaxation fixed * change Get_ to get_ * checkIfPointInBoundingBox moved Co-authored-by: Ubuntu Co-authored-by: JohnVirtonomy Co-authored-by: Xiangyu Hu Co-authored-by: Wen-Yang Chu Co-authored-by: Xiangyu Hu Co-authored-by: Xiangyu Hu <37415154+Xiangyu-Hu@users.noreply.github.com> * update from bitbucket 07-30-2021 * replace the wrong gpuSPHinXsys * Simbody artifacts instead of installation * simbody variable added to cmake command * change path * conflict resolved * remove doubled test Co-authored-by: Ubuntu Co-authored-by: JohnVirtonomy Co-authored-by: Xiangyu Hu Co-authored-by: Wen-Yang Chu Co-authored-by: Xiangyu Hu Co-authored-by: Xiangyu Hu <37415154+Xiangyu-Hu@users.noreply.github.com> * Pressure bc (#20) * SurfacePressureFromSource added * SurfacePressureFromSource::Update * BC prob works but the particle normals are missing * stress relaxation changed to Kirchhof * time dependent surface pressure works * cube case moved to source tests * cube test removed * add overtime to position based tests * go back to last working state * back to working version Co-authored-by: Ubuntu * simulation class remvoed (#21) * fix numerical damping (#23) * Simbody lib seperate (#26) * remove submodules * simbody added on no lapack * simbody * cases user moved * scripts removed * simbody set to master * variables removed * 3d lib cmake * boost option * simbody linking to built libraries * renaming + 2D cmake * option subdir * werror * eigen in simbody * eigen added * eigen * eigen include * eigen * add wasmtbb * working wasm example * cmake changes * restore working wasm build * change memory pool for wasm * work on eigen Co-authored-by: wen-yang chu * update simbody * Replace clapack (#27) * work on eigen * all tests pass with Eigen * macro renamed simbody * all SPH tests pass for static build * remove wasm files * first setup of spring on surface normal direction (#22) * first setup of spring on surface normal direction * adjusted combi of spring and pressure BC * correction of damping coefficient * simulation runs but too small time steps, only one vtu-file * consideration normal portion in opposite direction * creation of tests for vector calculations * simplification of vector norm calculation * small vector test working, but failing * small vector tests passing * angle tests added * correction of Vector Projection more test examples * correction of normal spring beam still spinning * adding of functions for vector calculations * change of spring force in right direction * debugging, still spinning after timestep 18 * change of vector calculation example * correction of normal spring force * for-loop removed, checking of spring & damping * area moved and considered in damping * adding gtest to CMakeLists * simplified dot_product_2 calculation * change from Vecd to Vec3d for calculations * changed Vector declaration and functions * correction of Spring and Damping Co-authored-by: JohnVirtonomy.io * emscripten option to disable gtest (#28) * emscripten option to disable gtest * comment out compiling flags * bug fix Co-authored-by: wen-yang chu * Fix zero pos particles (#31) * change pressure BC to be define by body part * SpringNormalOnSurfaceParticles with body part * option to use inner or outer surface for spring * zero position of particles fixed * fix BodyPartByParticle (#34) * Dynamic heart (#29) * change pressure BC to be define by body part * SpringNormalOnSurfaceParticles with body part * option to use inner or outer surface for spring * zero position of particles fixed * adding function to avoid LevelSetComplexShape * "virtual" added to comply with github CI test * both options for normalDirectionCalculation * "virtual" removed since no change in CI test * additional findNormalDirection dor 2D_build * comment to see if geometry_level_set is called * accelaration output added to vtu * adding displacement output & removing density * Vec3d to Vecd * adding normal vectors to vtu-File * von Mises Strain implemented * CMake name change to differentiate BUILD_TEST * test for strain calculation * correction of von Mises strain calculation * displ., normal, strain output calc. added in 2D Co-authored-by: JohnVirtonomy * Fix wasm merge2 (#37) * add EMSCRIPTEN macro to disable macro * remove image stuff with emscripten * simbody static lib with emscripten Co-authored-by: Wen-Yang Chu Co-authored-by: JohnVirtonomy * Production 1 freatures (#32) * cherry pick fixing zero position * option to write levelset data * fix BodyPartByParticle * small_shift changed * small shift changed back * fix normal calculation bug Co-authored-by: JohnVirtonomy * vtu ouput update (#39) * SurfaceOnlyBodyStatesRecordingToVtu class * class, functions for only surface particles output * comment out cout of number of surface particles * ShapeSurface in constructor only called at start * correction of surface ouput; still some issues * final correction of surface particle output Co-authored-by: JohnVirtonomy * add writer for vtu file to string * revert commit * add writer for vtu file to string (#40) * add small shift option to level set (#38) * add small shift option to level set * throw exceptions if instability occurs * fix comment * Kirchhof relaxation stability improved, removed B_ * fix 2D error * 2d self contact changed Co-authored-by: JohnVirtonomy * Triangle mesh from buffer constructor (#44) * triangle mesh buffer constructor * Triangle mesh from buffer only for emcc * structural simulation to gitHub (#41) * structural simulation to gitHub * change class * fix wasm compilation Co-authored-by: JohnVirtonomy Co-authored-by: BenceVirtonomy * Surface spring (#45) * surface spring constraint added with test * add surface fixation * surface spring * better exception * findTBB edit * change error message Co-authored-by: JohnVirtonomy Co-authored-by: Ubuntu Co-authored-by: JohnVirtonomy Co-authored-by: Xiangyu Hu Co-authored-by: Wen-Yang Chu Co-authored-by: Xiangyu Hu Co-authored-by: Xiangyu Hu <37415154+Xiangyu-Hu@users.noreply.github.com> Co-authored-by: Ubuntu Co-authored-by: JohnVirtonomy <85166600+JohnVirtonomy@users.noreply.github.com> Co-authored-by: JohnVirtonomy.io Co-authored-by: Antonov548 Co-authored-by: mrezavandVirtonomy <91728881+mrezavandVirtonomy@users.noreply.github.com> --- 3rd_party/simbody | 2 +- CMakeLists.txt | 8 +- .../geometries/level_set_supplementary.cpp | 4 +- .../solid_particles_supplementary.cpp | 30 + .../geometries/complex_shape_image_mesh.cpp | 6 +- .../geometries/complex_shape_image_mesh.h | 4 + .../src/for_3D_build/geometries/geometry.cpp | 12 + .../src/for_3D_build/geometries/geometry.h | 12 +- .../geometries/image_mesh_shape.cpp | 4 + .../geometries/image_mesh_shape.h | 4 + .../geometries/level_set_supplementary.cpp | 7 +- .../solid_particles_supplementary.cpp | 30 + SPHINXsys/src/shared/bodies/base_body.cpp | 10 +- SPHINXsys/src/shared/bodies/base_body.h | 21 +- SPHINXsys/src/shared/common/image_mhd.h | 4 + SPHINXsys/src/shared/common/image_mhd.hpp | 10 +- .../shared/geometries/geometry_level_set.cpp | 10 +- .../shared/geometries/geometry_level_set.h | 2 +- SPHINXsys/src/shared/geometries/level_set.cpp | 5 +- SPHINXsys/src/shared/geometries/level_set.h | 5 +- SPHINXsys/src/shared/io_system/in_output.cpp | 92 +- SPHINXsys/src/shared/io_system/in_output.h | 38 + .../relax_dynamics/relax_dynamics.h | 2 - .../solid_dynamics/solid_dynamics.cpp | 99 +- .../solid_dynamics/solid_dynamics.h | 48 + .../src/shared/particles/base_particles.cpp | 114 +- .../src/shared/particles/base_particles.h | 5 +- .../shared/particles/particle_adaptation.cpp | 8 +- .../shared/particles/particle_adaptation.h | 4 +- .../src/shared/particles/solid_particles.cpp | 135 ++- .../src/shared/particles/solid_particles.h | 19 +- cmake/FindSIMBODY.cmake | 2 +- cmake/FindTBB.cmake | 28 +- modules/CMakeLists.txt | 18 + .../structural_simulation_class.cpp | 1010 +++++++++++++++++ .../structural_simulation_class.h | 292 +++++ .../test_2d_self_contact/src/self_contact.cpp | 2 +- tests/CMakeLists.txt | 4 +- tests/modules/CMakeLists.txt | 5 + .../bernoulli_beam_struct_sim/CMakeLists.txt | 65 ++ .../bernoulli_beam_struct_sim.cpp | 62 + .../input/bernoulli_beam.stl | Bin 0 -> 684 bytes .../input/bernoulli_beam_20x.stl | Bin 0 -> 684 bytes .../CMakeLists.txt | 65 ++ .../input/ball_mass.stl | Bin 0 -> 256084 bytes ...mass_spring_damper_response_struct_sim.cpp | 60 + .../shared/test_vonMisesStrain/CMakeLists.txt | 61 + .../test_vonMisesStrain.cpp | 45 + 48 files changed, 2382 insertions(+), 91 deletions(-) create mode 100755 modules/CMakeLists.txt create mode 100755 modules/structural_simulation/structural_simulation_class.cpp create mode 100755 modules/structural_simulation/structural_simulation_class.h create mode 100755 tests/modules/CMakeLists.txt create mode 100755 tests/modules/bernoulli_beam_struct_sim/CMakeLists.txt create mode 100755 tests/modules/bernoulli_beam_struct_sim/bernoulli_beam_struct_sim.cpp create mode 100755 tests/modules/bernoulli_beam_struct_sim/input/bernoulli_beam.stl create mode 100755 tests/modules/bernoulli_beam_struct_sim/input/bernoulli_beam_20x.stl create mode 100644 tests/modules/mass_spring_damper_response_struct_sim/CMakeLists.txt create mode 100755 tests/modules/mass_spring_damper_response_struct_sim/input/ball_mass.stl create mode 100755 tests/modules/mass_spring_damper_response_struct_sim/mass_spring_damper_response_struct_sim.cpp create mode 100644 tests/unit_tests_src/shared/test_vonMisesStrain/CMakeLists.txt create mode 100644 tests/unit_tests_src/shared/test_vonMisesStrain/test_vonMisesStrain.cpp diff --git a/3rd_party/simbody b/3rd_party/simbody index 7ef1b38ad3..fcc20c3476 160000 --- a/3rd_party/simbody +++ b/3rd_party/simbody @@ -1 +1 @@ -Subproject commit 7ef1b38ad35a6b71cd2083a73b093a20313f9aa1 +Subproject commit fcc20c347644282f2e75c462deff47d9951540a8 diff --git a/CMakeLists.txt b/CMakeLists.txt index 20bc032f35..10ac3d55a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,13 +12,13 @@ option(STATIC_BUILD "STATIC_BUILD" 0) option(ONLY_3D "ONLY_3D" 0) option(BUILD_WITH_SIMBODY "BUILD_WITH_SIMBODY" 0) option(EMSCRIPTEN "EMSCRIPTEN" 0) -option(BUILD_TESTS "BUILD_TESTS" 1) +option(BUILD_SPHINXSYS_TESTS "BUILD_SPHINXSYS_TESTS" 1) if(EMSCRIPTEN) set(STATIC_BUILD 1) set(BUILD_WITH_SIMBODY 1) set(ONLY_3D 1) - set(BUILD_TESTS 1) + set(BUILD_SPHINXSYS_TESTS 1) add_definitions(-D__SIMBODY_WITHOUT_LAPACK__) add_definitions(-D__EIGEN__) add_definitions(-D__EMSCRIPTEN__) @@ -128,10 +128,12 @@ endif() add_subdirectory(SPHINXsys) -if(BUILD_TESTS) +if(BUILD_SPHINXSYS_TESTS) add_subdirectory(tests) endif() if(ACTIVATE_CUDA) add_subdirectory(cases_test_gpu) endif() + +add_subdirectory(modules) diff --git a/SPHINXsys/src/for_2D_build/geometries/level_set_supplementary.cpp b/SPHINXsys/src/for_2D_build/geometries/level_set_supplementary.cpp index 65896b3219..55433237e2 100644 --- a/SPHINXsys/src/for_2D_build/geometries/level_set_supplementary.cpp +++ b/SPHINXsys/src/for_2D_build/geometries/level_set_supplementary.cpp @@ -88,9 +88,9 @@ namespace SPH { } } //=================================================================================================// - void LevelSetDataPackage::markNearInterface() + void LevelSetDataPackage::markNearInterface(Real small_shift_factor) { - Real small_shift = 0.75 * grid_spacing_; + Real small_shift = small_shift_factor * grid_spacing_; //corner averages, note that the first row and first column are not used PackageTemporaryData corner_averages; for (int i = 1; i != AddressSize(); ++i) diff --git a/SPHINXsys/src/for_2D_build/particles/solid_particles_supplementary.cpp b/SPHINXsys/src/for_2D_build/particles/solid_particles_supplementary.cpp index 6e1f01da34..e7954e49d3 100644 --- a/SPHINXsys/src/for_2D_build/particles/solid_particles_supplementary.cpp +++ b/SPHINXsys/src/for_2D_build/particles/solid_particles_supplementary.cpp @@ -32,4 +32,34 @@ namespace SPH { + 3.0 * sigmaxy * sigmaxy); } //=================================================================================================// + Vecd ElasticSolidParticles::displacement(size_t particle_i) //not tested in 2D + { + Vecd disp = pos_n_[particle_i] - pos_0_[particle_i]; + return disp; + } + //=================================================================================================// + Vecd ElasticSolidParticles::normal(size_t particle_i) //not tested in 2D + { + Vecd normal_vec = n_[particle_i]; + return normal_vec; + } + //=================================================================================================// + Real ElasticSolidParticles::von_Mises_strain(size_t particle_i) //not tested in 2D + { + + Mat2d F = F_[particle_i]; + Mat2d epsilon = 0.5 * (~F * F - Mat2d(1.0)); //calculation of the Green-Lagrange strain tensor + + + Real epsilonxx = epsilon(0, 0); + Real epsilonyy = epsilon(1, 1); + Real epsilonzz = 0; //z-components zero for 2D measures + Real epsilonxy = epsilon(0, 1); + Real epsilonxz = 0; //z-components zero for 2D measures + Real epsilonyz = 0; //z-components zero for 2D measures + + return sqrt( (1.0 / 3.0) * (std::pow(epsilonxx - epsilonyy, 2.0) + std::pow(epsilonyy - epsilonzz, 2.0) + std::pow(epsilonzz - epsilonxx, 2.0)) + + 2.0 * (std::pow(epsilonxy, 2.0) + std::pow(epsilonyz, 2.0) + std::pow(epsilonxz, 2.0))); + } + //=================================================================================================// } diff --git a/SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.cpp b/SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.cpp index 5186465489..1d13c7ae10 100644 --- a/SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.cpp +++ b/SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.cpp @@ -1,3 +1,5 @@ +#ifndef __EMSCRIPTEN__ + #include "complex_shape_image_mesh.h" #include "image_mesh_shape.h" @@ -161,4 +163,6 @@ namespace SPH return BoundingBox(lower_bound, upper_bound); } //=================================================================================================// -} \ No newline at end of file +} + +#endif // __EMSCRIPTEN__ \ No newline at end of file diff --git a/SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.h b/SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.h index 49a1497025..903a267ce4 100644 --- a/SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.h +++ b/SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.h @@ -31,6 +31,8 @@ #ifndef COMPLEX_SHAPE_IMAGE_MESH_H #define COMPLEX_SHAPE_IMAGE_MESH_H +#ifndef __EMSCRIPTEN__ + #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING #include "base_geometry.h" @@ -88,3 +90,5 @@ namespace SPH } #endif //COMPLEX_SHAPE_IMAGE_MESH_H + +#endif // __EMSCRIPTEN__ \ No newline at end of file diff --git a/SPHINXsys/src/for_3D_build/geometries/geometry.cpp b/SPHINXsys/src/for_3D_build/geometries/geometry.cpp index a448356dec..53edf2626f 100644 --- a/SPHINXsys/src/for_3D_build/geometries/geometry.cpp +++ b/SPHINXsys/src/for_3D_build/geometries/geometry.cpp @@ -17,6 +17,17 @@ namespace SPH polymesh.scaleMesh(scale_factor); triangle_mesh_ = generateTriangleMesh(polymesh.transformMesh(translation)); } +#ifdef __EMSCRIPTEN__ + //=================================================================================================// + TriangleMeshShape::TriangleMeshShape(const uint8_t* buffer, Vec3d translation, Real scale_factor) + : Shape("TriangleMeshShape") + { + SimTK::PolygonalMesh polymesh; + polymesh.loadStlBuffer(buffer); + polymesh.scaleMesh(scale_factor); + triangle_mesh_ = generateTriangleMesh(polymesh.transformMesh(translation)); + } +#endif //=================================================================================================// TriangleMeshShape::TriangleMeshShape(Vec3d halfsize, int resolution, Vec3d translation) : Shape("TriangleMeshShape") @@ -146,6 +157,7 @@ namespace SPH //=================================================================================================// Vec3d ComplexShape::findClosestPoint(const Vec3d &input_pnt) { + //std::cout << "ComplexShape::findSignedDistance(const Vec3d &input_pnt) called"; return complex_shape_mesh_->findClosestPoint(input_pnt); } //=================================================================================================// diff --git a/SPHINXsys/src/for_3D_build/geometries/geometry.h b/SPHINXsys/src/for_3D_build/geometries/geometry.h index 4530843c7a..b72472437b 100644 --- a/SPHINXsys/src/for_3D_build/geometries/geometry.h +++ b/SPHINXsys/src/for_3D_build/geometries/geometry.h @@ -69,6 +69,10 @@ namespace SPH public: //constructor for load stl file from out side TriangleMeshShape(std::string file_path_name, Vec3d translation, Real scale_factor); +#ifdef __EMSCRIPTEN__ + //constructor for load stl file from buffer + TriangleMeshShape(const uint8_t* buffer, Vec3d translation, Real scale_factor); +#endif // constructor for brick geometry TriangleMeshShape(Vec3d halfsize, int resolution, Vec3d translation); // constructor for sphere geometry @@ -90,12 +94,10 @@ namespace SPH class ComplexShape : public Shape { - Vec3d findClosestPoint(const Vec3d &input_pnt); - public: ComplexShape() : Shape("ComplexShape") { complex_shape_mesh_ = nullptr; }; ComplexShape(std::string complex_shape_name) : Shape(complex_shape_name) { complex_shape_mesh_ = nullptr; }; - ComplexShape(ComplexShapeMesh*complex_shape_mesh) : Shape("ComplexShape") { complex_shape_mesh_ = complex_shape_mesh; }; + ComplexShape(ComplexShapeMesh* complex_shape_mesh) : Shape("ComplexShape") { complex_shape_mesh_ = complex_shape_mesh; }; virtual ~ComplexShape() {}; virtual BoundingBox findBounds() override; @@ -125,11 +127,13 @@ namespace SPH virtual bool checkNearSurface(const Vec3d &input_pnt, Real threshold); /** Signed distance is negative for point within the complex shape. */ virtual Real findSignedDistance(const Vec3d &input_pnt); + /** find closest point on the surface */ + virtual Vec3d findClosestPoint(const Vec3d &input_pnt); /** Normal direction point toward outside of the complex shape. */ virtual Vec3d findNormalDirection(const Vec3d &input_pnt); protected: - /** shape container */ + /** shape container */ ComplexShapeMesh* complex_shape_mesh_; }; diff --git a/SPHINXsys/src/for_3D_build/geometries/image_mesh_shape.cpp b/SPHINXsys/src/for_3D_build/geometries/image_mesh_shape.cpp index af0124a54c..92cdfbce3f 100644 --- a/SPHINXsys/src/for_3D_build/geometries/image_mesh_shape.cpp +++ b/SPHINXsys/src/for_3D_build/geometries/image_mesh_shape.cpp @@ -1,3 +1,5 @@ +#ifndef __EMSCRIPTEN__ + #include "image_mesh_shape.h" namespace SPH @@ -69,3 +71,5 @@ namespace SPH //=================================================================================================// } + +#endif // __EMSCRIPTEN__ \ No newline at end of file diff --git a/SPHINXsys/src/for_3D_build/geometries/image_mesh_shape.h b/SPHINXsys/src/for_3D_build/geometries/image_mesh_shape.h index e69da75836..2c19264acf 100644 --- a/SPHINXsys/src/for_3D_build/geometries/image_mesh_shape.h +++ b/SPHINXsys/src/for_3D_build/geometries/image_mesh_shape.h @@ -31,6 +31,8 @@ #ifndef IMAGE_MESH_SHAPE_H #define IMAGE_MESH_SHAPE_H +#ifndef __EMSCRIPTEN__ + #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING #include "base_geometry.h" @@ -85,4 +87,6 @@ namespace SPH }; } +#endif // __EMSCRIPTEN__ + #endif //IMAGE_MESH_SHAPE_H diff --git a/SPHINXsys/src/for_3D_build/geometries/level_set_supplementary.cpp b/SPHINXsys/src/for_3D_build/geometries/level_set_supplementary.cpp index 9ebf6c21dc..df0cbbbc84 100644 --- a/SPHINXsys/src/for_3D_build/geometries/level_set_supplementary.cpp +++ b/SPHINXsys/src/for_3D_build/geometries/level_set_supplementary.cpp @@ -106,9 +106,10 @@ namespace SPH { } } //=================================================================================================// - void LevelSetDataPackage::markNearInterface() - { - Real small_shift = 0.75 * grid_spacing_; + void LevelSetDataPackage::markNearInterface(Real small_shift_factor) + { + // small_shift_factor = 0.75 by default, can be increased for difficult geometries for smoothing + Real small_shift = small_shift_factor * grid_spacing_; //corner averages, note that the first row and first column are not used PackageTemporaryData corner_averages; for (int i = 1; i != AddressSize(); ++i) diff --git a/SPHINXsys/src/for_3D_build/particles/solid_particles_supplementary.cpp b/SPHINXsys/src/for_3D_build/particles/solid_particles_supplementary.cpp index 3d44f71ce1..6bcfb0fa2d 100644 --- a/SPHINXsys/src/for_3D_build/particles/solid_particles_supplementary.cpp +++ b/SPHINXsys/src/for_3D_build/particles/solid_particles_supplementary.cpp @@ -31,4 +31,34 @@ namespace SPH { + 3.0 * (sigmaxy * sigmaxy + sigmaxz * sigmaxz + sigmayz * sigmayz)); } //=================================================================================================// + Vecd ElasticSolidParticles::displacement(size_t particle_i) + { + Vecd disp = pos_n_[particle_i] - pos_0_[particle_i]; + return disp; + } + //=================================================================================================// + Vecd ElasticSolidParticles::normal(size_t particle_i) + { + Vecd normal_vec = n_[particle_i]; + return normal_vec; + } + //=================================================================================================// + Real ElasticSolidParticles::von_Mises_strain(size_t particle_i) + { + + Mat3d F = F_[particle_i]; + Mat3d epsilon = 0.5 * (~F * F - Matd(1.0)); //calculation of the Green-Lagrange strain tensor + + + Real epsilonxx = epsilon(0, 0); + Real epsilonyy = epsilon(1, 1); + Real epsilonzz = epsilon(2, 2); + Real epsilonxy = epsilon(0, 1); + Real epsilonxz = epsilon(0, 2); + Real epsilonyz = epsilon(1, 2); + + return sqrt( (1.0 / 3.0) * (std::pow(epsilonxx - epsilonyy, 2.0) + std::pow(epsilonyy - epsilonzz, 2.0) + std::pow(epsilonzz - epsilonxx, 2.0)) + + 2.0 * (std::pow(epsilonxy, 2.0) + std::pow(epsilonyz, 2.0) + std::pow(epsilonxz, 2.0))); + } + //=================================================================================================// } diff --git a/SPHINXsys/src/shared/bodies/base_body.cpp b/SPHINXsys/src/shared/bodies/base_body.cpp index b157de9ea8..a621fbfa26 100644 --- a/SPHINXsys/src/shared/bodies/base_body.cpp +++ b/SPHINXsys/src/shared/bodies/base_body.cpp @@ -74,12 +74,18 @@ namespace SPH return body_domain_bounds_; } //=================================================================================================// - void SPHBody::writeParticlesToVtuFile(std::ofstream &output_file) + void SPHBody::writeParticlesToVtuFile(std::ostream &output_file) { base_particles_->writeParticlesToVtuFile(output_file); newly_updated_ = false; } //=================================================================================================// + void SPHBody::writeSurfaceParticlesToVtuFile(std::ofstream &output_file, ShapeSurface& surface_particles) + { + base_particles_->writeSurfaceParticlesToVtuFile(output_file, surface_particles); + newly_updated_ = false; + } + //=================================================================================================// void SPHBody::writeParticlesToPltFile(std::ofstream &output_file) { if (newly_updated_) @@ -184,7 +190,7 @@ namespace SPH if (fabs(phi) < particle_spacing_min_) tagAParticle(i); } - std::cout << "Number of surface particles : " << body_part_particles_.size() << std::endl; + //std::cout << "Number of surface particles : " << body_part_particles_.size() << std::endl; } //=================================================================================================// ShapeSurfaceLayer::ShapeSurfaceLayer(SPHBody *body, Real layer_thickness) diff --git a/SPHINXsys/src/shared/bodies/base_body.h b/SPHINXsys/src/shared/bodies/base_body.h index 166989f73e..a316d2f203 100644 --- a/SPHINXsys/src/shared/bodies/base_body.h +++ b/SPHINXsys/src/shared/bodies/base_body.h @@ -52,6 +52,7 @@ namespace SPH class BaseParticles; class BaseCellLinkedList; class SPHBodyRelation; + class ShapeSurface; /** * @class SPHBody @@ -110,7 +111,8 @@ namespace SPH virtual void assignBaseParticles(BaseParticles *base_particles); void allocateConfigurationMemoriesForBufferParticles(); - virtual void writeParticlesToVtuFile(std::ofstream &output_file); + virtual void writeParticlesToVtuFile(std::ostream &output_file); + virtual void writeSurfaceParticlesToVtuFile(std::ofstream &output_file, ShapeSurface& surface_particles); virtual void writeParticlesToPltFile(std::ofstream &output_file); virtual void writeParticlesToXmlForRestart(std::string &filefullpath); virtual void readParticlesFromXmlForRestart(std::string &filefullpath); @@ -207,13 +209,28 @@ namespace SPH IndexVector body_part_particles_; /**< Collection particle in this body part. */ BodyPartByParticle(SPHBody *body, std::string body_part_name) - : BodyPartByShape(body, body_part_name){}; + : BodyPartByShape(body, body_part_name), + body_part_bounds_(Vecd(0), Vecd(0)), body_part_bounds_set_(false) + {}; virtual ~BodyPartByParticle(){}; + void setBodyPartBounds(BoundingBox bbox){ + body_part_bounds_ = bbox; + body_part_bounds_set_ = true; + }; + + BoundingBox getBodyPartBounds(){ + if (!body_part_bounds_set_) std::cout << "WARNING: the body part bounds are not set for BodyPartByParticle." << std::endl; + return body_part_bounds_; + } + protected: void tagAParticle(size_t particle_index); virtual void tagBodyPart() override; + + BoundingBox body_part_bounds_; + bool body_part_bounds_set_; }; /** diff --git a/SPHINXsys/src/shared/common/image_mhd.h b/SPHINXsys/src/shared/common/image_mhd.h index c0d75bd5a1..d9ae0cb7c8 100644 --- a/SPHINXsys/src/shared/common/image_mhd.h +++ b/SPHINXsys/src/shared/common/image_mhd.h @@ -30,6 +30,8 @@ #ifndef IMAGE_MHD_H #define IMAGE_MHD_H +#ifndef __EMSCRIPTEN__ + #include "small_vectors.h" #include "sph_data_containers.h" @@ -161,4 +163,6 @@ namespace SPH { #include "image_mhd.hpp" +#endif //__EMSCRIPTEN__ + #endif //IMAGE_MHD_H \ No newline at end of file diff --git a/SPHINXsys/src/shared/common/image_mhd.hpp b/SPHINXsys/src/shared/common/image_mhd.hpp index 37738e645c..721c303d5b 100644 --- a/SPHINXsys/src/shared/common/image_mhd.hpp +++ b/SPHINXsys/src/shared/common/image_mhd.hpp @@ -21,13 +21,16 @@ * * * --------------------------------------------------------------------------*/ /** -* @file image_mesh_shape.h +* @file image_mhd.hpp * @brief x * @details x * x * @author Yijin Mao */ -#pragma once +#ifndef IMAGE_MHD_HPP +#define IMAGE_MHD_HPP + +#ifndef __EMSCRIPTEN__ #include "image_mhd.h" #include "boost/algorithm/string.hpp" @@ -521,3 +524,6 @@ namespace SPH { } } +#endif __EMSCRIPTEN__ + +#endif IMAGE_MHD_HPP \ No newline at end of file diff --git a/SPHINXsys/src/shared/geometries/geometry_level_set.cpp b/SPHINXsys/src/shared/geometries/geometry_level_set.cpp index 10c0f5c937..723c567739 100644 --- a/SPHINXsys/src/shared/geometries/geometry_level_set.cpp +++ b/SPHINXsys/src/shared/geometries/geometry_level_set.cpp @@ -14,7 +14,7 @@ namespace SPH { //=================================================================================================// LevelSetComplexShape:: - LevelSetComplexShape(SPHBody *sph_body, ComplexShape &complex_shape, bool isCleaned) + LevelSetComplexShape(SPHBody *sph_body, ComplexShape &complex_shape, bool isCleaned, bool write_level_set) : ComplexShape(complex_shape), level_set_(nullptr) { name_ = sph_body->getBodyName(); @@ -23,8 +23,11 @@ namespace SPH level_set_->cleanInterface(); In_Output *in_output = sph_body->getSPHSystem().in_output_; - MeshRecordingToPlt write_level_set(*in_output, sph_body, level_set_); - write_level_set.writeToFile(0); + if (write_level_set) + { + MeshRecordingToPlt write_level_set(*in_output, sph_body, level_set_); + write_level_set.writeToFile(0); + } } //=================================================================================================// bool LevelSetComplexShape::checkContain(const Vecd &input_pnt, bool BOUNDARY_INCLUDED) @@ -49,6 +52,7 @@ namespace SPH //=================================================================================================// Vecd LevelSetComplexShape::findNormalDirection(const Vecd &input_pnt) { + //std::cout << "LevelSetComplexShape::findNormalDirection called" << std::endl; //to check if LevelSetComplexShape::findNormalDirection is called return level_set_->probeNormalDirection(input_pnt); } //=================================================================================================// diff --git a/SPHINXsys/src/shared/geometries/geometry_level_set.h b/SPHINXsys/src/shared/geometries/geometry_level_set.h index 48576c6c83..ff3513a969 100644 --- a/SPHINXsys/src/shared/geometries/geometry_level_set.h +++ b/SPHINXsys/src/shared/geometries/geometry_level_set.h @@ -24,7 +24,7 @@ namespace SPH class LevelSetComplexShape : public ComplexShape { public: - LevelSetComplexShape(SPHBody *sph_body, ComplexShape &complex_shape, bool isCleaned = false); + LevelSetComplexShape(SPHBody *sph_body, ComplexShape &complex_shape, bool isCleaned = false, bool write_level_set = true); virtual ~LevelSetComplexShape(){}; virtual bool checkContain(const Vecd &input_pnt, bool BOUNDARY_INCLUDED = true) override; diff --git a/SPHINXsys/src/shared/geometries/level_set.cpp b/SPHINXsys/src/shared/geometries/level_set.cpp index 36356a6c0a..ae13ab80ab 100644 --- a/SPHINXsys/src/shared/geometries/level_set.cpp +++ b/SPHINXsys/src/shared/geometries/level_set.cpp @@ -51,10 +51,11 @@ namespace SPH } //=================================================================================================// LevelSet::LevelSet(BoundingBox tentative_bounds, Real data_spacing, - ComplexShape &complex_shape, ParticleAdaptation &particle_adaptation) + ComplexShape &complex_shape, ParticleAdaptation &particle_adaptation, Real small_shift_factor) : MeshWithDataPackages(tentative_bounds, data_spacing, 4, complex_shape, particle_adaptation), global_h_ratio_(particle_adaptation.ReferenceSpacing() / data_spacing), + small_shift_factor_(small_shift_factor), kernel_(*particle_adaptation.getKernel()) { Real far_field_distance = grid_spacing_ * (Real)buffer_width_; @@ -157,7 +158,7 @@ namespace SPH //=================================================================================================// void LevelSet::markNearInterfaceForAPackage(LevelSetDataPackage *core_data_pkg, Real dt) { - core_data_pkg->markNearInterface(); + core_data_pkg->markNearInterface(small_shift_factor_); } //=================================================================================================// void LevelSet::redistanceInterface() diff --git a/SPHINXsys/src/shared/geometries/level_set.h b/SPHINXsys/src/shared/geometries/level_set.h index 67e3a4a5f1..e63aa5a13c 100644 --- a/SPHINXsys/src/shared/geometries/level_set.h +++ b/SPHINXsys/src/shared/geometries/level_set.h @@ -77,7 +77,7 @@ namespace SPH void computeKernelIntegrals(LevelSet &level_set); void computeNormalDirection(); void stepReinitialization(); - void markNearInterface(); + void markNearInterface(Real small_shift_factor); }; /** @@ -117,9 +117,10 @@ namespace SPH public: ConcurrentVector core_data_pkgs_; /**< packages near to zero level set. */ Real global_h_ratio_; + Real small_shift_factor_; LevelSet(BoundingBox tentative_bounds, Real data_spacing, - ComplexShape &complex_shape, ParticleAdaptation &particle_adaptation); + ComplexShape &complex_shape, ParticleAdaptation &particle_adaptation, Real small_shift_factor = 0.75); virtual ~LevelSet(){}; virtual bool probeIsWithinMeshBound(const Vecd &position) override; diff --git a/SPHINXsys/src/shared/io_system/in_output.cpp b/SPHINXsys/src/shared/io_system/in_output.cpp index 6acb4ada56..99bea50e88 100644 --- a/SPHINXsys/src/shared/io_system/in_output.cpp +++ b/SPHINXsys/src/shared/io_system/in_output.cpp @@ -81,6 +81,91 @@ namespace SPH { for (SPHBody* body : bodies_) { + if (body->checkNewlyUpdated()) + { + std::string filefullpath = in_output_.output_folder_ + "/SPHBody_" + body->getBodyName() + "_" + sequence + ".vtu"; + if (fs::exists(filefullpath)) + { + fs::remove(filefullpath); + } + std::ofstream out_file{filefullpath.c_str(), std::ios::trunc}; + //begin of the XML file + writeVtu(out_file, body); + out_file.close(); + } + body->setNotNewlyUpdated(); + } + } + //=============================================================================================// + void BodyStatesRecordingToVtu::writeVtu(std::ostream& stream, SPHBody* body) const + { + stream << "\n"; + stream << "\n"; + stream << " \n"; + + BaseParticles* base_particles = body->base_particles_; + size_t total_real_particles = base_particles->total_real_particles_; + stream << " getBodyName() << "\" NumberOfPoints=\"" << total_real_particles << "\" NumberOfCells=\"0\">\n"; + + body->writeParticlesToVtuFile(stream); + + stream << " \n"; + + //write empty cells + stream << " \n"; + stream << " \n"; + stream << " \n"; + stream << " \n"; + stream << " \n"; + stream << " \n"; + stream << " \n"; + stream << " \n"; + + stream << " \n"; + + stream << " \n"; + stream << "\n"; + } + //=============================================================================================// + BodyStatesRecordingToVtuString::BodyStatesRecordingToVtuString(In_Output& in_output, SPHBodyVector bodies) + : BodyStatesRecordingToVtu(in_output, bodies) + { + } + //=============================================================================================// + void BodyStatesRecordingToVtuString::writeWithFileName(const std::string& sequence) + { + for (SPHBody* body : bodies_) + { + if (body->checkNewlyUpdated()) + { + const auto& vtuName = body->getBodyName() + "_" + sequence + ".vtu"; + std::stringstream sstream; + //begin of the XML file + writeVtu(sstream, body); + _vtuData[vtuName] = sstream.str(); + } + body->setNotNewlyUpdated(); + } + } + //=============================================================================================// + const BodyStatesRecordingToVtuString::VtuStringData& BodyStatesRecordingToVtuString::GetVtuData() const + { + return _vtuData; + } + //=============================================================================================// + SurfaceOnlyBodyStatesRecordingToVtu::SurfaceOnlyBodyStatesRecordingToVtu(In_Output& in_output, SPHBodyVector bodies) + : BodyStatesRecording(in_output, bodies), + surface_body_layer_vector_({}) + { + for (SPHBody* body : bodies_) surface_body_layer_vector_.push_back(ShapeSurface(body)); + } + //=============================================================================================// + void SurfaceOnlyBodyStatesRecordingToVtu::writeWithFileName(const std::string& sequence) + { + for (size_t i = 0; i < bodies_.size(); i++) + //for (size_t i = 0; surface_body_layer_vector_.size(); i++) + { + SPHBody* body = bodies_[i]; if (body->checkNewlyUpdated()) { std::string filefullpath = in_output_.output_folder_ + "/SPHBody_" + body->getBodyName() + "_" + sequence + ".vtu"; @@ -94,11 +179,10 @@ namespace SPH out_file << "\n"; out_file << " \n"; - BaseParticles* base_particles = body->base_particles_; - size_t total_real_particles = base_particles->total_real_particles_; - out_file << " getBodyName() << "\" NumberOfPoints=\"" << total_real_particles << "\" NumberOfCells=\"0\">\n"; + size_t total_surface_particles = surface_body_layer_vector_[i].body_part_particles_.size(); + out_file << " getBodyName() << "\" NumberOfPoints=\"" << total_surface_particles << "\" NumberOfCells=\"0\">\n"; - body->writeParticlesToVtuFile(out_file); + body->writeSurfaceParticlesToVtuFile(out_file, surface_body_layer_vector_[i]); out_file << " \n"; diff --git a/SPHINXsys/src/shared/io_system/in_output.h b/SPHINXsys/src/shared/io_system/in_output.h index 7f9fd24485..0934ee6051 100644 --- a/SPHINXsys/src/shared/io_system/in_output.h +++ b/SPHINXsys/src/shared/io_system/in_output.h @@ -206,6 +206,44 @@ namespace SPH { protected: virtual void writeWithFileName(const std::string& sequence) override; + virtual void writeVtu(std::ostream& stream, SPHBody* body) const; + }; + + /** + * @class BodyStatesRecordingToVtuString + * @brief Write strings for bodies + * the output is map of strings with VTK XML format can visualized by ParaView + * the data type vtkUnstructedGrid + */ + class BodyStatesRecordingToVtuString : public BodyStatesRecordingToVtu + { + public: + BodyStatesRecordingToVtuString(In_Output& in_output, SPHBodyVector bodies); + virtual ~BodyStatesRecordingToVtuString() = default; + + using VtuStringData = std::map; + + const VtuStringData& GetVtuData() const; + protected: + virtual void writeWithFileName(const std::string& sequence) override; + private: + VtuStringData _vtuData; + }; + + /** + * @class SurfaceOnlyBodyStatesRecordingToVtu + * @brief Write files for surface particles of bodies + * the output file is VTK XML format can visualized by ParaView + * the data type vtkUnstructedGrid + */ + class SurfaceOnlyBodyStatesRecordingToVtu : public BodyStatesRecording + { + public: + SurfaceOnlyBodyStatesRecordingToVtu(In_Output& in_output, SPHBodyVector bodies); + + protected: + virtual void writeWithFileName(const std::string& sequence) override; + StdVec surface_body_layer_vector_; }; /** diff --git a/SPHINXsys/src/shared/particle_dynamics/relax_dynamics/relax_dynamics.h b/SPHINXsys/src/shared/particle_dynamics/relax_dynamics/relax_dynamics.h index 27d203b85e..739cb645b9 100644 --- a/SPHINXsys/src/shared/particle_dynamics/relax_dynamics/relax_dynamics.h +++ b/SPHINXsys/src/shared/particle_dynamics/relax_dynamics/relax_dynamics.h @@ -31,8 +31,6 @@ #ifndef RELAX_DYNAMICS_H #define RELAX_DYNAMICS_H - - #include "math.h" #include "all_particle_dynamics.h" diff --git a/SPHINXsys/src/shared/particle_dynamics/solid_dynamics/solid_dynamics.cpp b/SPHINXsys/src/shared/particle_dynamics/solid_dynamics/solid_dynamics.cpp index 7e4b049fe9..08d30ec8b4 100644 --- a/SPHINXsys/src/shared/particle_dynamics/solid_dynamics/solid_dynamics.cpp +++ b/SPHINXsys/src/shared/particle_dynamics/solid_dynamics/solid_dynamics.cpp @@ -81,6 +81,30 @@ namespace SPH dvel_dt_ave_[index_i] = dvel_dt_[index_i]; } //=================================================================================================// + ConstrainSolidBodySurfaceRegion:: + ConstrainSolidBodySurfaceRegion(SPHBody *body, BodyPartByParticle *body_part) + : PartSimpleDynamicsByParticle(body, body_part), SolidDataSimple(body), + pos_n_(particles_->pos_n_), pos_0_(particles_->pos_0_), + vel_n_(particles_->vel_n_), dvel_dt_(particles_->dvel_dt_), + apply_constrain_to_particle_(StdLargeVec(pos_0_.size(), false)) + { + // get the surface layer of particles + ShapeSurface surface_layer(body); + // select which particles the spring is applied to + // if the particle is in the surface layer, the force is applied + for (size_t particle_i: surface_layer.body_part_particles_) apply_constrain_to_particle_[particle_i] = true; + } + //=================================================================================================// + void ConstrainSolidBodySurfaceRegion::Update(size_t index_i, Real dt) + { + if(apply_constrain_to_particle_[index_i]) + { + pos_n_[index_i] = pos_0_[index_i]; + vel_n_[index_i] = Vecd(0); + dvel_dt_[index_i] = Vecd(0); + } + } + //=================================================================================================// PositionSolidBody:: PositionSolidBody(SPHBody *body, BodyPartByParticle *body_part, Real start_time, Real end_time, Vecd pos_end_center) @@ -90,7 +114,8 @@ namespace SPH vel_ave_(particles_->vel_ave_), dvel_dt_ave_(particles_->dvel_dt_ave_), start_time_(start_time), end_time_(end_time), pos_end_center_(pos_end_center) { - BoundingBox bounds = body->getBodyDomainBounds(); + // it's important we call the bounds of the body part + BoundingBox bounds = body_part->getBodyPartBounds(); pos_0_center_ = (bounds.first + bounds.second) * 0.5; translation_ = pos_end_center_ - pos_0_center_; } @@ -122,10 +147,6 @@ namespace SPH { pos_n_[index_i] = pos_n_[index_i] + getDisplacement(index_i, dt); // displacement from the initial position vel_n_[index_i] = getVelocity(); - dvel_dt_[index_i] = getAcceleration(); - /** the average values are prescirbed also. */ - vel_ave_[index_i] = vel_n_[index_i]; - dvel_dt_ave_[index_i] = dvel_dt_[index_i]; } } catch (out_of_range &e) @@ -143,7 +164,8 @@ namespace SPH vel_ave_(particles_->vel_ave_), dvel_dt_ave_(particles_->dvel_dt_ave_), start_time_(start_time), end_time_(end_time), end_scale_(end_scale) { - BoundingBox bounds = body->getBodyDomainBounds(); + // it's important we call the bounds of the body part + BoundingBox bounds = body_part->getBodyPartBounds(); pos_0_center_ = (bounds.first + bounds.second) * 0.5; } //=================================================================================================// @@ -173,10 +195,6 @@ namespace SPH { pos_n_[index_i] = pos_n_[index_i] + getDisplacement(index_i, dt); // displacement from the initial position vel_n_[index_i] = getVelocity(); - dvel_dt_[index_i] = getAcceleration(); - /** the average values are prescirbed also. */ - vel_ave_[index_i] = vel_n_[index_i]; - dvel_dt_ave_[index_i] = dvel_dt_[index_i]; } } catch (out_of_range &e) @@ -424,7 +442,7 @@ namespace SPH { // get the surface layer of particles ShapeSurface surface_layer(body); - // select which paricles the spring is applied to + // select which particles the spring is applied to for (size_t particle_i: surface_layer.body_part_particles_) { // vector to the source point from the particle @@ -497,6 +515,45 @@ namespace SPH } } //=================================================================================================// + SpringOnSurfaceParticles:: + SpringOnSurfaceParticles(SolidBody *body, Real stiffness, Real damping_ratio) + : ParticleDynamicsSimple(body), SolidDataSimple(body), + pos_n_(particles_->pos_n_), + pos_0_(particles_->pos_0_), + vel_n_(particles_->vel_n_), + dvel_dt_prior_(particles_->dvel_dt_prior_), + mass_(particles_->mass_), + apply_spring_force_to_particle_(StdLargeVec(pos_0_.size(), false)) + { + // get the surface layer of particles + ShapeSurface surface_layer(body); + // select which particles the spring is applied to + // if the particle is in the surface layer, the force is applied + for (size_t particle_i: surface_layer.body_part_particles_) apply_spring_force_to_particle_[particle_i] = true; + + // scale stiffness and damping by area here, so it's not necessary in each iteration + // we take the area of the first particle, assuming they are uniform + Real area = std::pow(particles_->Vol_[0], 2.0 / 3.0); + stiffness_ = stiffness * area; + damping_coeff_ = stiffness_ * damping_ratio; + + particles_->total_ghost_particles_ = 0; + } + //=================================================================================================// + void SpringOnSurfaceParticles::Update(size_t index_i, Real dt) + { + try{ + if (apply_spring_force_to_particle_[index_i]) + { + dvel_dt_prior_[index_i] += -stiffness_ * (pos_n_[index_i] - pos_0_[index_i]) / mass_[index_i]; + dvel_dt_prior_[index_i] += -damping_coeff_ * vel_n_[index_i] / mass_[index_i]; + } + } + catch(out_of_range& e){ + throw runtime_error(string("SpringOnSurfaceParticles::Update: particle index out of bounds") + to_string(index_i)); + } + } + //=================================================================================================// AccelerationForBodyPartInBoundingBox:: AccelerationForBodyPartInBoundingBox(SolidBody* body, BoundingBox& bounding_box, Vecd acceleration) : ParticleDynamicsSimple(body), SolidDataSimple(body), @@ -760,15 +817,26 @@ namespace SPH pos_n_[index_i] += vel_n_[index_i] * dt * 0.5; F_[index_i] += dF_dt_[index_i] * dt * 0.5; Real J = det(F_[index_i]); + //throw an exception if the determinant becomes negative + if (J <= 0) throw std::runtime_error(std::string("Determinant of F_ became negative! SPHBody: ") + this->body_->getBodyName() + + " particle ID: " + std::to_string(index_i)); Real one_over_J = 1.0 / J; rho_n_[index_i] = rho0_ * one_over_J; J_to_minus_2_over_dimension_[index_i] = pow(one_over_J, 2.0 * one_over_dimensions_); inverse_F_T_[index_i] = ~SimTK::inverse(F_[index_i]); - stress_on_particle_[index_i] = inverse_F_T_[index_i] * (material_->VolumetricKirchhoff(J) * B_[index_i] - + stress_on_particle_[index_i] = inverse_F_T_[index_i] * (material_->VolumetricKirchhoff(J) * Matd(1.0) - Matd(correction_factor_) * material_->ShearModulus() * J_to_minus_2_over_dimension_[index_i] * (F_[index_i] * ~F_[index_i]).trace() * one_over_dimensions_) + material_->NumericalDampingLeftCauchy(F_[index_i], dF_dt_[index_i], smoothing_length_, index_i) * inverse_F_T_[index_i]; stress_PK1_[index_i] = F_[index_i] * material_->ConstitutiveRelation(F_[index_i], index_i); + + for (int i = 0; i < 3; i++){ + for (int j = 0; j < 3; j++){ + if (std::isnan(stress_on_particle_[index_i][i][j])){ + throw std::runtime_error(std::string("stress_on_particle_ is Not A Number")); + } + } + } } //=================================================================================================// void KirchhoffStressRelaxationFirstHalf::Interaction(size_t index_i, Real dt) @@ -786,6 +854,13 @@ namespace SPH inner_neighborhood.dW_ij_[n] * Vol_[index_j] * inv_rho0_; } dvel_dt_[index_i] = acceleration; + + for (int i = 0; i < 3; i++){ + if (std::isnan(acceleration[i])){ + throw std::runtime_error(std::string("acceleration is Not A Number! SPHBody: ") + this->body_->getBodyName() + + " particle ID: " + std::to_string(index_i)); + } + } } //=================================================================================================// void StressRelaxationSecondHalf::Initialization(size_t index_i, Real dt) diff --git a/SPHINXsys/src/shared/particle_dynamics/solid_dynamics/solid_dynamics.h b/SPHINXsys/src/shared/particle_dynamics/solid_dynamics/solid_dynamics.h index f9831035bf..19f97aeec8 100644 --- a/SPHINXsys/src/shared/particle_dynamics/solid_dynamics/solid_dynamics.h +++ b/SPHINXsys/src/shared/particle_dynamics/solid_dynamics/solid_dynamics.h @@ -103,6 +103,27 @@ namespace SPH virtual void Update(size_t index_i, Real dt = 0.0) override; }; + /** + * @class ConstrainSolidBodySurfaceRegion + * @brief Constrain the surface particles of a solid body part with prescribed motion. + */ + class ConstrainSolidBodySurfaceRegion : + public PartSimpleDynamicsByParticle, public SolidDataSimple + { + public: + ConstrainSolidBodySurfaceRegion(SPHBody* body, BodyPartByParticle* body_part); + virtual ~ConstrainSolidBodySurfaceRegion() {}; + + StdLargeVec& GetApplyConstrainToParticle(){ return apply_constrain_to_particle_; } + protected: + StdLargeVec& pos_n_, & pos_0_; + StdLargeVec& vel_n_, & dvel_dt_; + StdLargeVec apply_constrain_to_particle_; + + virtual Vecd getDisplacement(Vecd& pos_0, Vecd& pos_n) { return pos_n; }; + virtual void Update(size_t index_i, Real dt = 0.0) override; + }; + /** * @class PositionSolidBody * @brief Moves the body into a defined position in a given time interval - position driven boundary condition @@ -322,6 +343,7 @@ namespace SPH * Can be used for outer or inner surface of a shell structure ofr example. * The spring force is calculated based on the difference from the particle's initial position. * Only for 3D applications + * Only for uniform surface particle size. */ class SpringNormalOnSurfaceParticles : public PartSimpleDynamicsByParticle, public SolidDataSimple @@ -342,6 +364,32 @@ namespace SPH virtual void Update(size_t index_i, Real dt = 0.0) override; }; /** + * @class SpringOnSurfaceParticles + * @brief Exerts spring force force on the surface in the form of acceleration to each particle. + * The input stiffness should be defined in Pa/m. The stiffness is scaled by the surface area of the particle to get N/m + * The force is applied to all the surface particles. + * The spring force is calculated based on the difference from the particle's initial position. + * Only for 3D applications + * BodyPartByParticle define the ody part that the spring is applied to. + * Only for uniform surface particle size. + */ + class SpringOnSurfaceParticles + : public ParticleDynamicsSimple, public SolidDataSimple + { + public: + SpringOnSurfaceParticles(SolidBody* body, Real stiffness, Real damping_ratio = 0.05); + + StdLargeVec& GetApplySpringForceToParticle(){ return apply_spring_force_to_particle_; } + protected: + StdLargeVec& pos_n_,& pos_0_,& vel_n_,& dvel_dt_prior_; + StdLargeVec& mass_; + Real stiffness_; + Real damping_coeff_; // damping component parallel to the spring force component + StdLargeVec apply_spring_force_to_particle_; + + virtual void Update(size_t index_i, Real dt = 0.0) override; + }; + /** * @class AccelerationForBodyPartInBoundingBox * @brief Adds acceleration to the part of the body that's inside a bounding box */ diff --git a/SPHINXsys/src/shared/particles/base_particles.cpp b/SPHINXsys/src/shared/particles/base_particles.cpp index 5ac814f803..6e5e03d24d 100644 --- a/SPHINXsys/src/shared/particles/base_particles.cpp +++ b/SPHINXsys/src/shared/particles/base_particles.cpp @@ -37,14 +37,14 @@ namespace SPH // add basic output particle data //---------------------------------------------------------------------- addAVariableToWrite("Velocity"); - addAVariableToWrite("Density"); + addAVariableToWrite("Acceleration"); //---------------------------------------------------------------------- // add restart output particle data //---------------------------------------------------------------------- addAVariableNameToList(variables_to_restart_, "Position"); addAVariableNameToList(variables_to_restart_, "Velocity"); + addAVariableNameToList(variables_to_restart_, "Acceleration"); addAVariableNameToList(variables_to_restart_, "Volume"); - addAVariableNameToList(variables_to_restart_, "Density"); ParticleGenerator* particle_generator = body_->particle_generator_; particle_generator->initialize(body_); @@ -131,11 +131,11 @@ namespace SPH total_real_particles_ -= 1; } //=================================================================================================// - void BaseParticles::writeParticlesToVtuFile(std::ofstream& output_file) + void BaseParticles::writeParticlesToVtuFile(std::ostream& output_file) { size_t total_real_particles = total_real_particles_; - //write particle positions first + //write current/final particle positions first output_file << " \n"; output_file << " \n"; output_file << " "; @@ -230,6 +230,112 @@ namespace SPH } } //=================================================================================================// + void BaseParticles::writeSurfaceParticlesToVtuFile(std::ofstream& output_file, ShapeSurface& surface_particles) + { + size_t total_surface_particles = surface_particles.body_part_particles_.size(); + + //write current/final particle positions first + output_file << " \n"; + output_file << " \n"; + output_file << " "; + for (size_t i = 0; i != total_surface_particles; ++i) { + size_t particle_i = surface_particles.body_part_particles_[i]; + Vec3d particle_position = upgradeToVector3D(pos_n_[particle_i]); + output_file << particle_position[0] << " " << particle_position[1] << " " << particle_position[2] << " "; + } + output_file << std::endl; + output_file << " \n"; + output_file << " \n"; + + //write header of particles data + output_file << " \n"; + + //write sorted particles ID + output_file << " \n"; + output_file << " "; + for (size_t i = 0; i != total_surface_particles; ++i) { + size_t particle_i = surface_particles.body_part_particles_[i]; + output_file << particle_i << " "; + } + output_file << std::endl; + output_file << " \n"; + + //write unsorted particles ID + output_file << " \n"; + output_file << " "; + for (size_t i = 0; i != total_surface_particles; ++i) { + size_t particle_i = surface_particles.body_part_particles_[i]; + output_file << unsorted_id_[particle_i] << " "; + } + output_file << std::endl; + output_file << " \n"; + + //write matrices + for (std::pair& name_index : variables_to_write_[indexMatrix]) + { + std::string variable_name = name_index.first; + StdLargeVec& variable = *(std::get(all_particle_data_)[name_index.second]); + output_file << " \n"; + output_file << " "; + for (size_t i = 0; i != total_surface_particles; ++i) { + size_t particle_i = surface_particles.body_part_particles_[i]; + Mat3d matrix_value = upgradeToMatrix3D(variable[particle_i]); + for (int k = 0; k != 3; ++k) { + Vec3d col_vector = matrix_value.col(k); + output_file << std::fixed << std::setprecision(9) << col_vector[0] << " " << col_vector[1] << " " << col_vector[2] << " "; + } + } + output_file << std::endl; + output_file << " \n"; + } + + //write vectors + for (std::pair& name_index : variables_to_write_[indexVector]) + { + std::string variable_name = name_index.first; + StdLargeVec& variable = *(std::get(all_particle_data_)[name_index.second]); + output_file << " \n"; + output_file << " "; + for (size_t i = 0; i != total_surface_particles; ++i) { + size_t particle_i = surface_particles.body_part_particles_[i]; + Vec3d vector_value = upgradeToVector3D(variable[particle_i]); + output_file << std::fixed << std::setprecision(9) << vector_value[0] << " " << vector_value[1] << " " << vector_value[2] << " "; + } + output_file << std::endl; + output_file << " \n"; + } + + //write scalars + for (std::pair& name_index : variables_to_write_[indexScalar]) + { + std::string variable_name = name_index.first; + StdLargeVec& variable = *(std::get(all_particle_data_)[name_index.second]); + output_file << " \n"; + output_file << " "; + for (size_t i = 0; i != total_surface_particles; ++i) { + size_t particle_i = surface_particles.body_part_particles_[i]; + output_file << std::fixed << std::setprecision(9) << variable[particle_i] << " "; + } + output_file << std::endl; + output_file << " \n"; + } + + //write integers + for (std::pair& name_index : variables_to_write_[indexInteger]) + { + std::string variable_name = name_index.first; + StdLargeVec& variable = *(std::get(all_particle_data_)[name_index.second]); + output_file << " \n"; + output_file << " "; + for (size_t i = 0; i != total_surface_particles; ++i) { + size_t particle_i = surface_particles.body_part_particles_[i]; + output_file << std::fixed << std::setprecision(9) << variable[particle_i] << " "; + } + output_file << std::endl; + output_file << " \n"; + } + } + //=================================================================================================// void BaseParticles::writePltFileHeader(std::ofstream& output_file) { output_file << " VARIABLES = \"x\",\"y\",\"z\",\"ID\""; diff --git a/SPHINXsys/src/shared/particles/base_particles.h b/SPHINXsys/src/shared/particles/base_particles.h index 888f30546d..45d1dbfa0b 100644 --- a/SPHINXsys/src/shared/particles/base_particles.h +++ b/SPHINXsys/src/shared/particles/base_particles.h @@ -44,6 +44,7 @@ namespace SPH class SPHBody; class BaseMaterial; + class ShapeSurface; /** * @class BaseParticles @@ -258,7 +259,9 @@ namespace SPH void switchToBufferParticle(size_t index_i); /** Write particle data in VTU format for Paraview. */ - virtual void writeParticlesToVtuFile(std::ofstream& output_file); + virtual void writeParticlesToVtuFile(std::ostream& output_file); + /** Write only surface particle data in VTU format for Paraview. */ + virtual void writeSurfaceParticlesToVtuFile(std::ofstream& output_file, ShapeSurface& surface_particles); /** Write particle data in PLT format for Tecplot. */ void writeParticlesToPltFile(std::ofstream& output_file); diff --git a/SPHINXsys/src/shared/particles/particle_adaptation.cpp b/SPHINXsys/src/shared/particles/particle_adaptation.cpp index fd9d1a5278..43df505958 100644 --- a/SPHINXsys/src/shared/particles/particle_adaptation.cpp +++ b/SPHINXsys/src/shared/particles/particle_adaptation.cpp @@ -16,7 +16,7 @@ namespace SPH { //=================================================================================================// - ParticleAdaptation::ParticleAdaptation(Real h_spacing_ratio, Real system_resolution_ratio) + ParticleAdaptation::ParticleAdaptation(Real h_spacing_ratio, Real system_resolution_ratio, Real small_shift_factor) : h_spacing_ratio_(h_spacing_ratio), system_resolution_ratio_(system_resolution_ratio), local_refinement_level_(0), @@ -27,7 +27,9 @@ namespace SPH number_density_min_(1.0), number_density_max_(1.0), kernel_(new KernelWendlandC2()), sph_body_(nullptr), system_domain_bounds_(), - base_particles_(nullptr){}; + base_particles_(nullptr), + small_shift_factor_(small_shift_factor) + {}; //=================================================================================================// void ParticleAdaptation::initialize(SPHBody *sph_body) { @@ -117,7 +119,7 @@ namespace SPH //=================================================================================================// BaseLevelSet *ParticleAdaptation::createLevelSet(ComplexShape &complex_shape) { - return new LevelSet(complex_shape.findBounds(), ReferenceSpacing(), complex_shape, *this); + return new LevelSet(complex_shape.findBounds(), ReferenceSpacing(), complex_shape, *this, small_shift_factor_); } //=================================================================================================// ParticleWithLocalRefinement:: diff --git a/SPHINXsys/src/shared/particles/particle_adaptation.h b/SPHINXsys/src/shared/particles/particle_adaptation.h index 05087d47f4..5c4c4fd5b6 100644 --- a/SPHINXsys/src/shared/particles/particle_adaptation.h +++ b/SPHINXsys/src/shared/particles/particle_adaptation.h @@ -73,8 +73,10 @@ namespace SPH BoundingBox system_domain_bounds_; BaseParticles *base_particles_; + Real small_shift_factor_; + public: - ParticleAdaptation(Real h_spacing_ratio = 1.3, Real system_resolution_ratio = 1.0); + ParticleAdaptation(Real h_spacing_ratio = 1.3, Real system_resolution_ratio = 1.0, Real small_shift_factor = 0.75); virtual ~ParticleAdaptation(){}; /** Note: called after construction of this and derived classes. */ virtual void initialize(SPHBody *sph_body); diff --git a/SPHINXsys/src/shared/particles/solid_particles.cpp b/SPHINXsys/src/shared/particles/solid_particles.cpp index 290be5ecd8..4b69511406 100644 --- a/SPHINXsys/src/shared/particles/solid_particles.cpp +++ b/SPHINXsys/src/shared/particles/solid_particles.cpp @@ -61,10 +61,9 @@ namespace SPH { //=================================================================================================// void SolidParticles::initializeNormalDirectionFromGeometry() { - ComplexShape* body_shape = body_->body_shape_; for (size_t i = 0; i != total_real_particles_; ++i) { - Vecd normal_direction = body_shape->findNormalDirection(pos_n_[i]); + Vecd normal_direction = body_->body_shape_->findNormalDirection(pos_n_[i]); n_[i] = normal_direction; n_0_[i] = normal_direction; } @@ -120,12 +119,57 @@ namespace SPH { return von_Mises_stress_max; } //=================================================================================================// - void ElasticSolidParticles::writeParticlesToVtuFile(std::ofstream& output_file) + StdLargeVec ElasticSolidParticles::getDisplacement() + { + StdLargeVec displacement_vector = {}; + for (size_t index_i = 0; index_i < pos_0_.size(); index_i++) + { + displacement_vector.push_back(displacement(index_i)); + } + return displacement_vector; + } + //=================================================================================================// + StdLargeVec ElasticSolidParticles::getNormal() + { + StdLargeVec normal_vector = {}; + for (size_t index_i = 0; index_i < pos_0_.size(); index_i++) + { + normal_vector.push_back(normal(index_i)); + } + return normal_vector; + } + //=================================================================================================// + StdLargeVec ElasticSolidParticles::getVonMisesStrain() + { + StdLargeVec von_Mises_strain_vector = {}; + for (size_t index_i = 0; index_i < pos_0_.size(); index_i++) + { + von_Mises_strain_vector.push_back(von_Mises_strain(index_i)); + } + return von_Mises_strain_vector; + } + //=================================================================================================// + Real ElasticSolidParticles::getMaxVonMisesStrain() + { + Real von_Mises_strain_max = 0; + for (size_t index_i = 0; index_i < pos_0_.size(); index_i++) + { + Real von_Mises_strain_i = von_Mises_strain(index_i); + if (von_Mises_strain_max < von_Mises_strain_i) + { + von_Mises_strain_max = von_Mises_strain_i; + } + } + return von_Mises_strain_max; + } + //=================================================================================================// + void ElasticSolidParticles::writeParticlesToVtuFile(std::ostream& output_file) { SolidParticles::writeParticlesToVtuFile(output_file); size_t total_real_particles = total_real_particles_; + //write von Mises stress output_file << " \n"; output_file << " "; for (size_t i = 0; i != total_real_particles; ++i) { @@ -133,6 +177,84 @@ namespace SPH { } output_file << std::endl; output_file << " \n"; + + //write Displacement + output_file << " \n"; + output_file << " "; + for (size_t i = 0; i != total_real_particles; ++i) { + Vecd displacement_vector = displacement(i); + output_file << displacement_vector[0] << " " << displacement_vector[1] << " " << displacement_vector[2] << " "; + } + output_file << std::endl; + output_file << " \n"; + + //write Normal Vectors + output_file << " \n"; + output_file << " "; + for (size_t i = 0; i != total_real_particles; ++i) { + Vecd normal_vector = normal(i); + output_file << normal_vector[0] << " " << normal_vector[1] << " " << normal_vector[2] << " "; + } + output_file << std::endl; + output_file << " \n"; + + //write von Mises strain + output_file << " \n"; + output_file << " "; + for (size_t i = 0; i != total_real_particles; ++i) { + output_file << std::fixed << std::setprecision(9) << von_Mises_strain(i) << " "; + } + output_file << std::endl; + output_file << " \n"; + } + //=================================================================================================// + void ElasticSolidParticles::writeSurfaceParticlesToVtuFile(std::ofstream& output_file, ShapeSurface& surface_particles) + { + SolidParticles::writeSurfaceParticlesToVtuFile(output_file, surface_particles); + + size_t total_surface_particles = surface_particles.body_part_particles_.size(); + + //write von Mises stress + output_file << " \n"; + output_file << " "; + for (size_t i = 0; i != total_surface_particles; ++i) { + size_t particle_i = surface_particles.body_part_particles_[i]; + output_file << std::fixed << std::setprecision(9) << von_Mises_stress(particle_i) << " "; + } + output_file << std::endl; + output_file << " \n"; + + //write Displacement + output_file << " \n"; + output_file << " "; + for (size_t i = 0; i != total_surface_particles; ++i) { + size_t particle_i = surface_particles.body_part_particles_[i]; + Vecd displacement_vector = displacement(particle_i); + output_file << displacement_vector[0] << " " << displacement_vector[1] << " " << displacement_vector[2] << " "; + } + output_file << std::endl; + output_file << " \n"; + + //write Normal Vectors + output_file << " \n"; + output_file << " "; + for (size_t i = 0; i != total_surface_particles; ++i) { + size_t particle_i = surface_particles.body_part_particles_[i]; + Vecd normal_vector = normal(particle_i); + output_file << normal_vector[0] << " " << normal_vector[1] << " " << normal_vector[2] << " "; + } + output_file << std::endl; + output_file << " \n"; + + //write von Mises strain + output_file << " \n"; + output_file << " "; + for (size_t i = 0; i != total_surface_particles; ++i) { + size_t particle_i = surface_particles.body_part_particles_[i]; + output_file << std::fixed << std::setprecision(9) << von_Mises_strain(particle_i) << " "; + } + output_file << std::endl; + output_file << " \n"; } //=================================================================================================// void ElasticSolidParticles::writePltFileHeader(std::ofstream& output_file) @@ -140,6 +262,9 @@ namespace SPH { SolidParticles::writePltFileHeader(output_file); output_file << ",\" von Mises stress \""; + output_file << ",\" Displacement \""; + output_file << ",\" Normal Vectors \""; + output_file << ",\" von Mises strain \""; } //=================================================================================================// void ElasticSolidParticles::writePltFileParticleData(std::ofstream& output_file, size_t index_i) @@ -147,6 +272,10 @@ namespace SPH { SolidParticles::writePltFileParticleData(output_file, index_i); output_file << von_Mises_stress(index_i) << " "; + Vecd displacement_vector = displacement(index_i); + output_file << displacement_vector[0] << " " << displacement_vector[1] << " " << displacement_vector[2] << " " + << index_i << " "; + output_file << von_Mises_strain(index_i) << " "; } //=============================================================================================// void ActiveMuscleParticles::initializeActiveMuscleParticleData() diff --git a/SPHINXsys/src/shared/particles/solid_particles.h b/SPHINXsys/src/shared/particles/solid_particles.h index d3db3c17b6..3e6b3950ca 100644 --- a/SPHINXsys/src/shared/particles/solid_particles.h +++ b/SPHINXsys/src/shared/particles/solid_particles.h @@ -31,7 +31,7 @@ #include "base_particles.h" - + namespace SPH { //---------------------------------------------------------------------- @@ -41,6 +41,7 @@ namespace SPH { class ElasticSolid; class PlasticSolid; template class ActiveMuscle; + class ShapeSurface; /** * @class SolidParticles @@ -104,8 +105,22 @@ namespace SPH { StdLargeVec getVonMisesStress(); Real getMaxVonMisesStress(); - virtual void writeParticlesToVtuFile(std::ofstream &output_file) override; + /**< Computing displacemnt. */ + Vecd displacement(size_t particle_i); + StdLargeVec getDisplacement(); + + /**< Computing normal vector. */ + Vecd normal (size_t particle_i); + StdLargeVec getNormal(); + + /**< Computing von Mises equivalent stress. */ + Real von_Mises_strain (size_t particle_i); + StdLargeVec getVonMisesStrain(); + Real getMaxVonMisesStrain(); + virtual void writeParticlesToVtuFile(std::ostream &output_file) override; + /** Write only surface particle data in VTU format for Paraview. */ + virtual void writeSurfaceParticlesToVtuFile(std::ofstream& output_file, ShapeSurface& surface_particles); virtual ElasticSolidParticles* ThisObjectPtr() override {return this;}; }; diff --git a/cmake/FindSIMBODY.cmake b/cmake/FindSIMBODY.cmake index 58a8326a66..cea285342b 100644 --- a/cmake/FindSIMBODY.cmake +++ b/cmake/FindSIMBODY.cmake @@ -202,4 +202,4 @@ mark_as_advanced( Simbody_LIBRARIES Simbody_RELEASE_LIBRARIES Simbody_DEBUG_LIBRARIES -) +) \ No newline at end of file diff --git a/cmake/FindTBB.cmake b/cmake/FindTBB.cmake index 1597479546..84def3f8ae 100644 --- a/cmake/FindTBB.cmake +++ b/cmake/FindTBB.cmake @@ -264,34 +264,8 @@ find_package_handle_standard_args(TBB DEFAULT_MSG TBB_INCLUDE_DIR TBB_LIB_DIR TBB_LIBRARYS) #============================================================================= -#parse all the version numbers from tbb -if(NOT TBB_VERSION) -#only read the start of the file -file(READ - "${TBB_INCLUDE_DIR}/tbb/tbb_stddef.h" - TBB_VERSION_CONTENTS - LIMIT 2048) - - string(REGEX REPLACE - ".*#define TBB_VERSION_MAJOR ([0-9]+).*" "\\1" - TBB_VERSION_MAJOR "${TBB_VERSION_CONTENTS}") - - string(REGEX REPLACE - ".*#define TBB_VERSION_MINOR ([0-9]+).*" "\\1" - TBB_VERSION_MINOR "${TBB_VERSION_CONTENTS}") - - string(REGEX REPLACE - ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" - TBB_INTERFACE_VERSION "${TBB_VERSION_CONTENTS}") - - string(REGEX REPLACE - ".*#define TBB_COMPATIBLE_INTERFACE_VERSION ([0-9]+).*" "\\1" - TBB_COMPATIBLE_INTERFACE_VERSION "${TBB_VERSION_CONTENTS}") - -endif() - -if (TBB_FOUND) +if(TBB_FOUND) set(TBB_LIBRARYS ${TBB_LIBRARYS} ) set(TBB_INCLUDE_DIR ${TBB_INCLUDE_DIR} ) set(TBB_LIB_DIR ${TBB_LIB_DIR} ) diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt new file mode 100755 index 0000000000..80dd2fdc83 --- /dev/null +++ b/modules/CMakeLists.txt @@ -0,0 +1,18 @@ +include(ImportSPHINXsysFromSource_for_3D_build) + +if(NOT STATIC_BUILD) + add_library(structural_simulation_module SHARED structural_simulation/structural_simulation_class.cpp) + target_link_libraries(structural_simulation_module sphinxsys_3d) +else() + add_library(structural_simulation_module STATIC structural_simulation/structural_simulation_class.cpp) + target_link_libraries(structural_simulation_module sphinxsys_static_3d) +endif() + +target_include_directories(structural_simulation_module PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/structural_simulation ${SPHINXsysHeaderPath}) + +if(BUILD_WITH_SIMBODY) + include("${SPHINXSYS_PROJECT_DIR}/SPHINXsys/cmake/Simbody_header_directories.cmake") + target_include_directories(structural_simulation_module PUBLIC ${SIMBODY_HEADER_DIRECTORIES}) +endif() + + diff --git a/modules/structural_simulation/structural_simulation_class.cpp b/modules/structural_simulation/structural_simulation_class.cpp new file mode 100755 index 0000000000..c6ac39a45b --- /dev/null +++ b/modules/structural_simulation/structural_simulation_class.cpp @@ -0,0 +1,1010 @@ +/** +* @file structural_simulation_class.cpp +* @brief The structural simulation module is licensed under the Aladdin Free Public License (https://spdx.org/licenses/Aladdin.html) regarding usage for medical device development. +* Commercial use for medical device development is not permitted. This does not apply to applications in other fields. +* @details solid structural simulation class for general structural simulations +* @author Bence Z. Rochlitz - Virtonomy GmbH +*/ + +#include "structural_simulation_class.h" + +//////////////////////////////////////////////////// +/* global functions in StructuralSimulation */ +//////////////////////////////////////////////////// + +BodyPartByParticleTriMesh::BodyPartByParticleTriMesh(SPHBody* body, string body_part_name, TriangleMeshShape* triangle_mesh_shape) +: BodyPartByParticle(body, body_part_name) +{ + std::unique_ptr mesh(new ComplexShapeTriangleMesh()); + body_part_shape_ = new ComplexShape(mesh.get()); + mesh->addTriangleMeshShape(triangle_mesh_shape, ShapeBooleanOps::add); + + // set the body domain bounds because it is not set by default + BoundingBox bounds = mesh->findBounds(); + setBodyPartBounds(bounds); + + tagBodyPart(); +} + +BodyPartByParticleTriMesh::~BodyPartByParticleTriMesh() +{ + delete body_part_shape_; +} + +ImportedModel::ImportedModel( + SPHSystem &system, string body_name, TriangleMeshShape* triangle_mesh_shape, + ParticleAdaptation* particle_adaptation, StdLargeVec& pos_0, StdLargeVec& volume) + : SolidBody(system, body_name, particle_adaptation, new ParticleGeneratorDirect()) +{ + // the particles are generated by the direct generator + std::unique_ptr mesh(new ComplexShapeTriangleMesh()); + ComplexShape original_body_shape(mesh.get()); + mesh->addTriangleMeshShape(triangle_mesh_shape, ShapeBooleanOps::add); + + body_shape_ = new LevelSetComplexShape(this, original_body_shape, true, false); + + // set the body domain bounds because it is not set by default + BoundingBox bounds = mesh->findBounds(); + setBodyDomainBounds(bounds); + + for(size_t particle_i = 0; particle_i < pos_0.size(); particle_i++) + { + body_input_points_volumes_.push_back(std::make_pair(pos_0[particle_i], volume[particle_i])); + } +} + +ImportedModel::~ImportedModel() +{ + delete body_shape_; +} + +SolidBodyForSimulation::SolidBodyForSimulation( + SPHSystem &system, string body_name, TriangleMeshShape& triangle_mesh_shape, ParticleAdaptation& particle_adaptation, + Real physical_viscosity, LinearElasticSolid& material_model, StdLargeVec& pos_0, StdLargeVec& volume): + + imported_model_(ImportedModel(system, body_name, &triangle_mesh_shape, &particle_adaptation, pos_0, volume)), + //material_model_(material_model), + elastic_solid_particles_(ElasticSolidParticles(&imported_model_, &material_model)), + inner_body_relation_(BodyRelationInner(&imported_model_)), + + correct_configuration_(solid_dynamics::CorrectConfiguration(&inner_body_relation_)), + stress_relaxation_first_half_(solid_dynamics::StressRelaxationFirstHalf(&inner_body_relation_)), + stress_relaxation_second_half_(solid_dynamics::StressRelaxationSecondHalf(&inner_body_relation_)), + damping_random_(DampingWithRandomChoice>(&inner_body_relation_, 0.2, "Velocity", physical_viscosity)) +{} + +void expandBoundingBox(BoundingBox* original, BoundingBox* additional) +{ + for(int i = 0; i < original->first.size(); i++) + { + if ( additional->first[i] < original->first[i] ) + { + original->first[i] = additional->first[i]; + } + if ( additional->second[i] > original->second[i] ) + { + original->second[i] = additional->second[i]; + } + } +} + +void relaxParticlesSingleResolution(In_Output* in_output, + bool write_particle_relaxation_data, + SolidBody* imported_model, + BodyRelationInner* imported_model_inner) +{ + BodyStatesRecordingToVtu write_imported_model_to_vtu(*in_output, { imported_model }); + + //---------------------------------------------------------------------- + // Methods used for particle relaxation. + //---------------------------------------------------------------------- + RandomizePartilePosition random_imported_model_particles(imported_model); + /** A Physics relaxation step. */ + relax_dynamics::SolidRelaxationStepInner relaxation_step_inner(imported_model_inner, true); + //---------------------------------------------------------------------- + // Particle relaxation starts here. + //---------------------------------------------------------------------- + random_imported_model_particles.parallel_exec(0.25); + relaxation_step_inner.surface_bounding_.parallel_exec(); + if (write_particle_relaxation_data) + { + write_imported_model_to_vtu.writeToFile(0.0); + } + imported_model->updateCellLinkedList(); + //---------------------------------------------------------------------- + // Particle relaxation time stepping start here. + //---------------------------------------------------------------------- + int ite_p = 0; + while (ite_p < 1000) + { + relaxation_step_inner.parallel_exec(); + ite_p += 1; + if (ite_p % 100 == 0) + { + std::cout << std::fixed << std::setprecision(9) << "Relaxation steps for the imported model N = " << ite_p << "\n"; + if (write_particle_relaxation_data) + { + write_imported_model_to_vtu.writeToFile(ite_p); + } + } + } + std::cout << "The physics relaxation process of the imported model finished !" << std::endl; +} + +std::tuple, StdLargeVec> getParticlesFromTriangleMeshShape(TriangleMeshShape* triangle_mesh_shape, Real resolution, bool particle_relaxation, bool write_particle_relaxation_data) +{ + BoundingBox bb = triangle_mesh_shape->findBounds(); + SPHSystem system(bb, resolution); + + ParticleAdaptation particle_adaptation(1.15, 1.0); + + std::string name = "model"; + SolidBody model(system, name, &particle_adaptation); + + std::unique_ptr mesh(new ComplexShapeTriangleMesh()); + ComplexShape original_body_shape(mesh.get()); + mesh->addTriangleMeshShape(triangle_mesh_shape, ShapeBooleanOps::add); + + LevelSetComplexShape body_shape(&model, original_body_shape, true, false); + model.body_shape_ = &body_shape; + + // set the body domain bounds because it is not set by default + BoundingBox bounds = mesh->findBounds(); + model.setBodyDomainBounds(bounds); + + SolidParticles particles(&model); + + if (particle_relaxation) + { + In_Output in_output(system); + BodyRelationInner inner_relation(&model); + relaxParticlesSingleResolution(&in_output, write_particle_relaxation_data, &model, &inner_relation); + } + + return std::tuple, StdLargeVec>(particles.pos_0_, particles.Vol_); +} + +StructuralSimulationInput::StructuralSimulationInput( + string relative_input_path, + vector imported_stl_list, + Real scale_stl, + vector translation_list, + vector resolution_list, + vector material_model_list, + StdVec physical_viscosity, + StdVec contacting_bodies_list + ): + relative_input_path_(relative_input_path), + imported_stl_list_(imported_stl_list), + scale_stl_(scale_stl), + translation_list_(translation_list), + resolution_list_(resolution_list), + material_model_list_(material_model_list), + physical_viscosity_(physical_viscosity), + contacting_body_pairs_list_(contacting_bodies_list) +{ + //time dependent contact + time_dep_contacting_body_pairs_list_ = {}; + // particle_relaxation option + particle_relaxation_list_ = {}; + for (size_t i = 0; i < resolution_list_.size(); i++){ particle_relaxation_list_.push_back(true); } + write_particle_relaxation_data_ = false; + // scale system boundaries + scale_system_boundaries_ = 1; + // boundary conditions + non_zero_gravity_ = {}; + acceleration_bounding_box_tuple_ = {}; + force_in_body_region_tuple_ = {}; + surface_pressure_tuple_ = {}; + spring_damper_tuple_ = {}; + surface_spring_tuple_ = {}; + body_indeces_fixed_constraint_ = {}; + body_indeces_fixed_constraint_region_ = {}; + position_solid_body_tuple_ = {}; + position_scale_solid_body_tuple_ = {}; + translation_solid_body_tuple_ = {}; + translation_solid_body_part_tuple_ = {}; + surface_particles_only_to_vtu_ = false; +}; + +/////////////////////////////////////// +/* StructuralSimulation members */ +/////////////////////////////////////// + +StructuralSimulation::StructuralSimulation(StructuralSimulationInput& input): + // generic input + relative_input_path_(input.relative_input_path_), + imported_stl_list_(input.imported_stl_list_), + scale_stl_(input.scale_stl_), + translation_list_(input.translation_list_), + resolution_list_(input.resolution_list_), + material_model_list_(input.material_model_list_), + physical_viscosity_(input.physical_viscosity_), + contacting_body_pairs_list_(input.contacting_body_pairs_list_), + time_dep_contacting_body_pairs_list_(input.time_dep_contacting_body_pairs_list_), + + // default system, optional: particle relaxation, scale_system_boundaries + particle_relaxation_list_(input.particle_relaxation_list_), + write_particle_relaxation_data_(input.write_particle_relaxation_data_), + system_resolution_(0.0), + system_(SPHSystem(BoundingBox(Vec3d(0), Vec3d(0)), system_resolution_)), + scale_system_boundaries_(input.scale_system_boundaries_), + in_output_(In_Output(system_)), + + // optional: boundary conditions + non_zero_gravity_(input.non_zero_gravity_), + acceleration_bounding_box_tuple_(input.acceleration_bounding_box_tuple_), + force_in_body_region_tuple_(input.force_in_body_region_tuple_), + surface_pressure_tuple_(input.surface_pressure_tuple_), + spring_damper_tuple_(input.spring_damper_tuple_), + surface_spring_tuple_(input.surface_spring_tuple_), + body_indeces_fixed_constraint_(input.body_indeces_fixed_constraint_), + body_indeces_fixed_constraint_region_(input.body_indeces_fixed_constraint_region_), + position_solid_body_tuple_(input.position_solid_body_tuple_), + position_scale_solid_body_tuple_(input.position_scale_solid_body_tuple_), + translation_solid_body_tuple_(input.translation_solid_body_tuple_), + translation_solid_body_part_tuple_(input.translation_solid_body_part_tuple_), + surface_particles_only_to_vtu_(input.surface_particles_only_to_vtu_), + + // iterators + iteration_(0), + + // data storage + von_mises_stress_max_({}), + von_mises_stress_particles_({}) + +{ + // scaling of translation and resolution + scaleTranslationAndResolution(); + // set the default resolution to the max in the resolution list + setSystemResolutionMax(); + // create the body mesh list for triangular mesh shapes storage + createBodyMeshList(); + // create the particle adaptions for the bodies + createParticleAdaptationList(); + // set up the system + calculateSystemBoundaries(); + system_.run_particle_relaxation_ = true; + // initialize solid bodies with their properties + initializeElasticSolidBodies(); + // contacts + initializeAllContacts(); + + // boundary conditions + initializeGravity(); + initializeAccelerationForBodyPartInBoundingBox(); + initializeForceInBodyRegion(); + initializeSurfacePressure(); + initializeSpringDamperConstraintParticleWise(); + initializeSpringNormalOnSurfaceParticles(); + initializeConstrainSolidBody(); + initializeConstrainSolidBodyRegion(); + initializePositionSolidBody(); + initializePositionScaleSolidBody(); + initializeTranslateSolidBody(); + initializeTranslateSolidBodyPart(); + + // initialize simulation + initializeSimulation(); +} + +StructuralSimulation::~StructuralSimulation() +{} + +void StructuralSimulation::scaleTranslationAndResolution() +{ + // scale the translation_list_, system_resolution_ and resolution_list_ + for (size_t i = 0; i < translation_list_.size(); i++) + { + translation_list_[i] *= scale_stl_; + } + system_resolution_ *= scale_stl_; + for (size_t i = 0; i < resolution_list_.size(); i++) + { + resolution_list_[i] *= scale_stl_; + } +} + +void StructuralSimulation::setSystemResolutionMax() +{ + system_resolution_ = 0.0; + for (size_t i = 0; i < resolution_list_.size(); i++) + { + if (system_resolution_ < resolution_list_[i]) + { + system_resolution_ = resolution_list_[i]; + } + } + system_.resolution_ref_ = system_resolution_; +} + +void StructuralSimulation::calculateSystemBoundaries() +{ + // calculate system bounds from all bodies + for (size_t i = 0; i < body_mesh_list_.size(); i++) + { + BoundingBox additional = body_mesh_list_[i].findBounds(); + expandBoundingBox(&system_.system_domain_bounds_, &additional); + } + // scale the system bounds around the center point + Vecd center_point = (system_.system_domain_bounds_.first + system_.system_domain_bounds_.second) * 0.5; + + Vecd distance_first = system_.system_domain_bounds_.first - center_point; + Vecd distance_second = system_.system_domain_bounds_.second - center_point; + + system_.system_domain_bounds_.first = center_point + distance_first * scale_system_boundaries_; + system_.system_domain_bounds_.second = center_point + distance_second * scale_system_boundaries_; +} + +void StructuralSimulation::createBodyMeshList() +{ + body_mesh_list_ = {}; + for (size_t i = 0; i < imported_stl_list_.size(); i++) + { + string relative_input_path_copy = relative_input_path_; + body_mesh_list_.push_back(TriangleMeshShape(relative_input_path_copy.append(imported_stl_list_[i]), translation_list_[i], scale_stl_)); + } +} + +void StructuralSimulation::createParticleAdaptationList() +{ + particle_adaptation_list_ = {}; + for (size_t i = 0; i < resolution_list_.size(); i++) + { + Real system_resolution_ratio = system_resolution_ / resolution_list_[i]; + // for solid bodies, slightly small h_spaing_ratio is used + particle_adaptation_list_.push_back(ParticleAdaptation(1.15, system_resolution_ratio)); + } +} + +void StructuralSimulation::initializeElasticSolidBodies() +{ + solid_body_list_ = {}; + particle_normal_update_ = {}; + for (size_t i = 0; i < body_mesh_list_.size(); i++) + { + // create the initial particles from the triangle mesh shape with particle relaxation option + std::tuple, StdLargeVec> particles = getParticlesFromTriangleMeshShape(&body_mesh_list_[i], resolution_list_[i], particle_relaxation_list_[i], write_particle_relaxation_data_); + + // get the particles' initial position and their volume + StdLargeVec& pos_0 = std::get<0>(particles); + StdLargeVec& volume = std::get<1>(particles); + + // create the SolidBodyForSimulation + solid_body_list_.emplace_back(make_shared( + system_, imported_stl_list_[i], body_mesh_list_[i], particle_adaptation_list_[i], physical_viscosity_[i], material_model_list_[i], pos_0, volume)); + + // update initial normal direction of particles + solid_body_list_[i]->getElasticSolidParticles()->initializeNormalDirectionFromGeometry(); + std::cout << " normal initialization done" << std::endl; + particle_normal_update_.emplace_back(make_shared(solid_body_list_[i]->getImportedModel())); + } +} + +void StructuralSimulation::initializeContactBetweenTwoBodies(int first, int second) +{ + ImportedModel* first_body = solid_body_list_[first]->getImportedModel(); + ImportedModel* second_body = solid_body_list_[second]->getImportedModel(); + + SolidBodyRelationContact* first_contact = new SolidBodyRelationContact(first_body, {second_body}); + SolidBodyRelationContact* second_contact = new SolidBodyRelationContact(second_body, {first_body}); + + contact_list_.emplace_back(first_contact); + contact_list_.emplace_back(second_contact); + + contact_density_list_.emplace_back(make_shared(first_contact)); + contact_density_list_.emplace_back(make_shared(second_contact)); + + contact_force_list_.emplace_back(make_shared(first_contact)); + contact_force_list_.emplace_back(make_shared(second_contact)); +} + +void StructuralSimulation::initializeAllContacts() +{ + contact_list_ = {}; + contact_density_list_ = {}; + contact_force_list_ = {}; + // first place all the regular contacts into the lists + for (size_t i = 0; i < contacting_body_pairs_list_.size(); i++) + { + ImportedModel* contact_body = solid_body_list_[i]->getImportedModel(); + RealBodyVector target_list= {}; + for (size_t target_i: contacting_body_pairs_list_[i]) + { + target_list.emplace_back(solid_body_list_[target_i]->getImportedModel()); + } + + SolidBodyRelationContact* contact = new SolidBodyRelationContact(contact_body, target_list); + + contact_list_.emplace_back(contact); + contact_density_list_.emplace_back(make_shared(contact)); + contact_force_list_.emplace_back(make_shared(contact)); + } + // continue appending the lists with the time dependent contacts + for (size_t i = 0; i < time_dep_contacting_body_pairs_list_.size(); i++) + { + int body_1 = time_dep_contacting_body_pairs_list_[i].first[0]; + int body_2 = time_dep_contacting_body_pairs_list_[i].first[1]; + initializeContactBetweenTwoBodies(body_1, body_2); //vector with first element being array with indices + } +} + +void StructuralSimulation::initializeGravity() +{ + // collect all the body indeces with non-zero gravity + vector gravity_indeces = {}; + for (size_t i = 0; i < non_zero_gravity_.size(); i++) + { + gravity_indeces.push_back(non_zero_gravity_[i].first); + } + // initialize gravity + initialize_gravity_ = {}; + size_t gravity_index_i = 0; // iterating through gravity_indeces + for (size_t i = 0; i < solid_body_list_.size(); i++) + { + // check if i is in indeces_gravity + if ( count(gravity_indeces.begin(), gravity_indeces.end(), i) ) + { + initialize_gravity_.emplace_back(make_shared(solid_body_list_[i]->getImportedModel(), new Gravity(non_zero_gravity_[gravity_index_i].second))); + gravity_index_i++; + } + else + { + initialize_gravity_.emplace_back(make_shared(solid_body_list_[i]->getImportedModel())); + } + } +} + +void StructuralSimulation::initializeAccelerationForBodyPartInBoundingBox() +{ + acceleration_bounding_box_ = {}; + for (size_t i = 0; i < acceleration_bounding_box_tuple_.size(); i++) + { + SolidBody* solid_body = solid_body_list_[get<0>(acceleration_bounding_box_tuple_[i])]->getImportedModel(); + acceleration_bounding_box_.emplace_back(make_shared + (solid_body, get<1>(acceleration_bounding_box_tuple_[i]), get<2>(acceleration_bounding_box_tuple_[i]))); + } +} + +void StructuralSimulation::initializeForceInBodyRegion() +{ + force_in_body_region_ = {}; + for (size_t i = 0; i < force_in_body_region_tuple_.size(); i++) + { + int body_index = get<0>(force_in_body_region_tuple_[i]); + BoundingBox bbox = get<1>(force_in_body_region_tuple_[i]); + Vec3d force = get<2>(force_in_body_region_tuple_[i]); + Real end_time = get<3>(force_in_body_region_tuple_[i]); + + // get the length of each side to create the box + Real x_side = bbox.second[0] - bbox.first[0]; + Real y_side = bbox.second[1] - bbox.first[1]; + Real z_side = bbox.second[2] - bbox.first[2]; + Vec3d halfsize_bbox(0.5 * x_side, 0.5 * y_side, 0.5 * z_side); + // get the center point for translation from the origin + Vec3d center = (bbox.second + bbox.first) * 0.5; + // SimTK geometric modeling resolution + int resolution(20); + // create the triangle mesh of the box + TriangleMeshShape* tmesh = new TriangleMeshShape(halfsize_bbox, resolution, center); + + BodyPartByParticleTriMesh* bp = new BodyPartByParticleTriMesh(solid_body_list_[body_index]->getImportedModel(), imported_stl_list_[body_index], tmesh); + force_in_body_region_.emplace_back(make_shared(solid_body_list_[body_index]->getImportedModel(), bp, force, end_time)); + } +} + +void StructuralSimulation::initializeSurfacePressure() +{ + surface_pressure_ = {}; + for (size_t i = 0; i < surface_pressure_tuple_.size(); i++) + { + int body_index = get<0>(surface_pressure_tuple_[i]); + TriangleMeshShape* tmesh =get<1>(surface_pressure_tuple_[i]); + Vec3d point = get<2>(surface_pressure_tuple_[i]); + StdVec> pressure_over_time = get<3>(surface_pressure_tuple_[i]); + + BodyPartByParticle* bp = new BodyPartByParticleTriMesh(solid_body_list_[body_index]->getImportedModel(), imported_stl_list_[body_index], tmesh); + surface_pressure_.emplace_back(make_shared(solid_body_list_[body_index]->getImportedModel(), bp, point, pressure_over_time)); + } +} + +void StructuralSimulation::initializeSpringDamperConstraintParticleWise() +{ + spring_damper_constraint_ = {}; + for (size_t i = 0; i < spring_damper_tuple_.size(); i++) + { + SolidBody* solid_body = solid_body_list_[get<0>(spring_damper_tuple_[i])]->getImportedModel(); + spring_damper_constraint_.emplace_back(make_shared(solid_body, get<1>(spring_damper_tuple_[i]), get<2>(spring_damper_tuple_[i]))); + } +} + +void StructuralSimulation::initializeSpringNormalOnSurfaceParticles() +{ + surface_spring_ = {}; + for (size_t i = 0; i < surface_spring_tuple_.size(); i++) + { + int body_index = get<0>(surface_spring_tuple_[i]); + TriangleMeshShape* tmesh = get<1>(surface_spring_tuple_[i]); + bool inner_outer = get<2>(surface_spring_tuple_[i]); + Vec3d point = get<3>(surface_spring_tuple_[i]); + Real spring_stiffness = get<4>(surface_spring_tuple_[i]); + Real damping_coefficient = get<5>(surface_spring_tuple_[i]); + + BodyPartByParticle* bp = new BodyPartByParticleTriMesh(solid_body_list_[body_index]->getImportedModel(), imported_stl_list_[body_index], tmesh); + surface_spring_.emplace_back(make_shared(solid_body_list_[body_index]->getImportedModel(), bp, inner_outer, point, spring_stiffness, damping_coefficient)); + } +} + +void StructuralSimulation::initializeConstrainSolidBody() +{ + fixed_constraint_body_ = {}; + for (size_t i = 0; i < body_indeces_fixed_constraint_.size(); i++) + { + int body_index = body_indeces_fixed_constraint_[i]; + BodyPartByParticleTriMesh* bp = new BodyPartByParticleTriMesh(solid_body_list_[body_index]->getImportedModel(), imported_stl_list_[body_index], &body_mesh_list_[body_index]); + fixed_constraint_body_.emplace_back(make_shared(solid_body_list_[body_index]->getImportedModel(), bp)); + } +} + +void StructuralSimulation::initializeConstrainSolidBodyRegion() +{ + fixed_constraint_region_ = {}; + for (size_t i = 0; i < body_indeces_fixed_constraint_region_.size(); i++) + { + int body_index = body_indeces_fixed_constraint_region_[i].first; + BoundingBox bbox = body_indeces_fixed_constraint_region_[i].second; + + // get the length of each side to create the box + Real x_side = bbox.second[0] - bbox.first[0]; + Real y_side = bbox.second[1] - bbox.first[1]; + Real z_side = bbox.second[2] - bbox.first[2]; + Vec3d halfsize_bbox(0.5 * x_side, 0.5 * y_side, 0.5 * z_side); + // get the center point for translation from the origin + Vec3d center = (bbox.second + bbox.first) * 0.5; + // SimTK geometric modeling resolution + int resolution(20); + // create the triangle mesh of the box + TriangleMeshShape* tmesh = new TriangleMeshShape(halfsize_bbox, resolution, center); + + BodyPartByParticleTriMesh* bp = new BodyPartByParticleTriMesh(solid_body_list_[body_index]->getImportedModel(), imported_stl_list_[body_index], tmesh); + fixed_constraint_region_.emplace_back(make_shared(solid_body_list_[body_index]->getImportedModel(), bp)); + } +} + +void StructuralSimulation::initializePositionSolidBody() +{ + position_solid_body_ = {}; + for (size_t i = 0; i < position_solid_body_tuple_.size(); i++) + { + int body_index = get<0>(position_solid_body_tuple_[i]); + Real start_time = get<1>(position_solid_body_tuple_[i]); + Real end_time = get<2>(position_solid_body_tuple_[i]); + Vecd pos_end_center = get<3>(position_solid_body_tuple_[i]); + BodyPartByParticleTriMesh* bp = new BodyPartByParticleTriMesh(solid_body_list_[body_index]->getImportedModel(), imported_stl_list_[body_index], &body_mesh_list_[body_index]); + + position_solid_body_.emplace_back(make_shared(solid_body_list_[body_index]->getImportedModel(), bp, start_time, end_time, pos_end_center)); + } +} + +void StructuralSimulation::initializePositionScaleSolidBody() +{ + position_scale_solid_body_ = {}; + for (size_t i = 0; i < position_scale_solid_body_tuple_.size(); i++) + { + int body_index = get<0>(position_scale_solid_body_tuple_[i]); + Real start_time = get<1>(position_scale_solid_body_tuple_[i]); + Real end_time = get<2>(position_scale_solid_body_tuple_[i]); + Real scale = get<3>(position_scale_solid_body_tuple_[i]); + BodyPartByParticleTriMesh* bp = new BodyPartByParticleTriMesh(solid_body_list_[body_index]->getImportedModel(), imported_stl_list_[body_index], &body_mesh_list_[body_index]); + + position_scale_solid_body_.emplace_back(make_shared(solid_body_list_[body_index]->getImportedModel(), bp, start_time, end_time, scale)); + } +} + +void StructuralSimulation::initializeTranslateSolidBody() +{ + translation_solid_body_ = {}; + for (size_t i = 0; i < translation_solid_body_tuple_.size(); i++) + { + int body_index = get<0>(translation_solid_body_tuple_[i]); + Real start_time = get<1>(translation_solid_body_tuple_[i]); + Real end_time = get<2>(translation_solid_body_tuple_[i]); + Vecd translation = get<3>(translation_solid_body_tuple_[i]); + BodyPartByParticleTriMesh* bp = new BodyPartByParticleTriMesh( + solid_body_list_[body_index]->getImportedModel(), imported_stl_list_[body_index], &body_mesh_list_[body_index]); + + translation_solid_body_.emplace_back(make_shared( + solid_body_list_[body_index]->getImportedModel(), bp, start_time, end_time, translation)); + } +} + +void StructuralSimulation::initializeTranslateSolidBodyPart() +{ + translation_solid_body_part_ = {}; + for (size_t i = 0; i < translation_solid_body_part_tuple_.size(); i++) + { + int body_index = get<0>(translation_solid_body_part_tuple_[i]); + Real start_time = get<1>(translation_solid_body_part_tuple_[i]); + Real end_time = get<2>(translation_solid_body_part_tuple_[i]); + Vecd translation = get<3>(translation_solid_body_part_tuple_[i]); + BoundingBox bbox = get<4>(translation_solid_body_part_tuple_[i]); + BodyPartByParticleTriMesh* bp = new BodyPartByParticleTriMesh( + solid_body_list_[body_index]->getImportedModel(), imported_stl_list_[body_index], &body_mesh_list_[body_index]); + + translation_solid_body_part_.emplace_back(make_shared( + solid_body_list_[body_index]->getImportedModel(), bp, start_time, end_time, translation, bbox)); + } +} + +void StructuralSimulation::executeCorrectConfiguration() +{ + for (size_t i = 0; i < solid_body_list_.size(); i++) + { + solid_body_list_[i]->getCorrectConfiguration()->parallel_exec(); + } +} + +void StructuralSimulation::executeUpdateElasticNormalDirection() +{ + for (size_t i = 0; i < particle_normal_update_.size(); i++) + { + particle_normal_update_[i]->parallel_exec(); + } +} + +void StructuralSimulation::executeinitializeATimeStep() +{ + for (size_t i = 0; i < initialize_gravity_.size(); i++) + { + initialize_gravity_[i]->parallel_exec(); + } +} + +void StructuralSimulation::executeAccelerationForBodyPartInBoundingBox() +{ + for (size_t i = 0; i < acceleration_bounding_box_.size(); i++) + { + acceleration_bounding_box_[i]->parallel_exec(); + } +} + +void StructuralSimulation::executeForceInBodyRegion() +{ + for (size_t i = 0; i < force_in_body_region_.size(); i++) + { + force_in_body_region_[i]->parallel_exec(); + } +} + +void StructuralSimulation::executeSurfacePressure() +{ + for (size_t i = 0; i < surface_pressure_.size(); i++) + { + surface_pressure_[i]->parallel_exec(); + } +} + +void StructuralSimulation::executeSpringDamperConstraintParticleWise() +{ + for (size_t i = 0; i < spring_damper_constraint_.size(); i++) + { + spring_damper_constraint_[i]->parallel_exec(); + } +} + +void StructuralSimulation::executeSpringNormalOnSurfaceParticles() +{ + for (size_t i = 0; i < surface_spring_.size(); i++) + { + surface_spring_[i]->parallel_exec(); + } +} + +void StructuralSimulation::executeContactDensitySummation() +{ + // number of contacts that are not time dependent: contact pairs * 2 + size_t number_of_general_contacts = contacting_body_pairs_list_.size(); + for (size_t i = 0; i < contact_density_list_.size(); i++) + { + if (i < number_of_general_contacts) + { + contact_density_list_[i]->parallel_exec(); + } + else + { + // index of the time dependent contact body pair + // for i = 0, 1 --> index = 0, i = 2, 3 --> index = 1, and so on.. + int index = (i - number_of_general_contacts) / 2; + Real start_time = time_dep_contacting_body_pairs_list_[index].second[0]; + Real end_time = time_dep_contacting_body_pairs_list_[index].second[1]; + if(GlobalStaticVariables::physical_time_ >= start_time && GlobalStaticVariables::physical_time_ <= end_time) + { + contact_density_list_[i]->parallel_exec(); + } + } + } +} + +void StructuralSimulation::executeContactForce() +{ + // number of contacts that are not time dependent: contact pairs * 2 + size_t number_of_general_contacts = contacting_body_pairs_list_.size(); + for (size_t i = 0; i < contact_force_list_.size(); i++) + { + if (i < number_of_general_contacts) + { + contact_force_list_[i]->parallel_exec(); + } + else + { + // index of the time dependent contact body pair + // for i = 0, 1 --> index = 0, i = 2, 3 --> index = 1, and so on.. + int index = (i - number_of_general_contacts) / 2; + Real start_time = time_dep_contacting_body_pairs_list_[index].second[0]; + Real end_time = time_dep_contacting_body_pairs_list_[index].second[1]; + if(GlobalStaticVariables::physical_time_ >= start_time && GlobalStaticVariables::physical_time_ <= end_time) + { + contact_force_list_[i]->parallel_exec(); + } + } + } +} + +void StructuralSimulation::executeStressRelaxationFirstHalf(Real dt) +{ + for (size_t i = 0; i < solid_body_list_.size(); i++) + { + solid_body_list_[i]->getStressRelaxationFirstHalf()->parallel_exec(dt); + } +} + +void StructuralSimulation::executeConstrainSolidBody() +{ + for (size_t i = 0; i < fixed_constraint_body_.size(); i++) + { + fixed_constraint_body_[i]->parallel_exec(); + } +} + +void StructuralSimulation::executeConstrainSolidBodyRegion() +{ + for (size_t i = 0; i < fixed_constraint_region_.size(); i++) + { + fixed_constraint_region_[i]->parallel_exec(); + } +} + +void StructuralSimulation::executePositionSolidBody(Real dt) +{ + for (size_t i = 0; i < position_solid_body_.size(); i++) + { + position_solid_body_[i]->parallel_exec(dt); + } +} + +void StructuralSimulation::executePositionScaleSolidBody(Real dt) +{ + for (size_t i = 0; i < position_scale_solid_body_.size(); i++) + { + position_scale_solid_body_[i]->parallel_exec(dt); + } +} + +void StructuralSimulation::executeTranslateSolidBody(Real dt) +{ + for (size_t i = 0; i < translation_solid_body_.size(); i++) + { + translation_solid_body_[i]->parallel_exec(dt); + } +} + +void StructuralSimulation::executeTranslateSolidBodyPart(Real dt) +{ + for (size_t i = 0; i < translation_solid_body_part_.size(); i++) + { + translation_solid_body_part_[i]->parallel_exec(dt); + } +} + +void StructuralSimulation::executeDamping(Real dt) +{ + for (size_t i = 0; i < solid_body_list_.size(); i++) + { + solid_body_list_[i]->getDampingWithRandomChoice()->parallel_exec(dt); + } +} + +void StructuralSimulation::executeStressRelaxationSecondHalf(Real dt) +{ + for (size_t i = 0; i < solid_body_list_.size(); i++) + { + solid_body_list_[i]->getStressRelaxationSecondHalf()->parallel_exec(dt); + } +} + +void StructuralSimulation::executeUpdateCellLinkedList() +{ + for (size_t i = 0; i < solid_body_list_.size(); i++) + { + solid_body_list_[i]->getImportedModel()->updateCellLinkedList(); + } +} + +void StructuralSimulation::executeContactUpdateConfiguration() +{ + // number of contacts that are not time dependent: contact pairs * 2 + size_t number_of_general_contacts = contacting_body_pairs_list_.size(); + for (size_t i = 0; i < contact_list_.size(); i++) + { + // general contacts = contacting_bodies * 2 + if (i < number_of_general_contacts) + { + contact_list_[i]->updateConfiguration(); + } + // time dependent contacts = time dep. contacting_bodies * 2 + else + { + // index of the time dependent contact body pair + // for i = 0, 1 --> index = 0, i = 2, 3 --> index = 1, and so on.. + int index = (i - number_of_general_contacts) / 2; + Real start_time = time_dep_contacting_body_pairs_list_[index].second[0]; + Real end_time = time_dep_contacting_body_pairs_list_[index].second[1]; + if(GlobalStaticVariables::physical_time_ >= start_time && GlobalStaticVariables::physical_time_ <= end_time) + { + contact_list_[i]->updateConfiguration(); + } + } + } +} + +void StructuralSimulation::initializeSimulation() +{ + GlobalStaticVariables::physical_time_ = 0.0; + + /** INITIALALIZE SYSTEM */ + system_.initializeSystemCellLinkedLists(); + system_.initializeSystemConfigurations(); + + /** INITIAL CONDITION */ + executeCorrectConfiguration(); +} + +void StructuralSimulation::runSimulationStep(Real &dt, Real &integration_time) +{ + if (iteration_ % 100 == 0) cout << "N=" << iteration_ << " Time: " << GlobalStaticVariables::physical_time_ << " dt: " << dt << "\n"; + + /** UPDATE NORMAL DIRECTIONS */ + executeUpdateElasticNormalDirection(); + + /** ACTIVE BOUNDARY CONDITIONS */ + // force (acceleration) based + executeinitializeATimeStep(); + executeAccelerationForBodyPartInBoundingBox(); + executeForceInBodyRegion(); + executeSurfacePressure(); + executeSpringDamperConstraintParticleWise(); + executeSpringNormalOnSurfaceParticles(); + + /** CONTACT */ + executeContactDensitySummation(); + executeContactForce(); + + /** STRESS RELAXATOIN, DAMPING, POSITIONAL CONSTRAINTS */ + executeStressRelaxationFirstHalf(dt); + + executeConstrainSolidBody(); + executeConstrainSolidBodyRegion(); + executePositionSolidBody(dt); + executePositionScaleSolidBody(dt); + executeTranslateSolidBody(dt); + // velocity based + executeTranslateSolidBodyPart(dt); + + executeDamping(dt); + + executeConstrainSolidBody(); + executeConstrainSolidBodyRegion(); + executePositionSolidBody(dt); + executePositionScaleSolidBody(dt); + executeTranslateSolidBody(dt); + // velocity based + executeTranslateSolidBodyPart(dt); + + executeStressRelaxationSecondHalf(dt); + + /** UPDATE TIME STEP SIZE, INCREMENT */ + iteration_++; + dt = system_.getSmallestTimeStepAmongSolidBodies(); + integration_time += dt; + GlobalStaticVariables::physical_time_ += dt; + + /** UPDATE BODIES CELL LINKED LISTS */ + executeUpdateCellLinkedList(); + + /** UPDATE CONTACT CONFIGURATION */ + executeContactUpdateConfiguration(); +} + +void StructuralSimulation::runSimulation(Real end_time) +{ + BodyStatesRecordingToVtu write_states(in_output_, system_.real_bodies_); + SurfaceOnlyBodyStatesRecordingToVtu write_states_surface(in_output_, system_.real_bodies_); + + /** Statistics for computing time. */ + if(surface_particles_only_to_vtu_) write_states_surface.writeToFile(0); + else write_states.writeToFile(0); + Real output_period = end_time / 100.0; + Real dt = 0.0; + tick_count t1 = tick_count::now(); + tick_count::interval_t interval; + /** Main loop */ + while (GlobalStaticVariables::physical_time_ < end_time) + { + Real integration_time = 0.0; + while (integration_time < output_period) + { + runSimulationStep(dt, integration_time); + } + tick_count t2 = tick_count::now(); + // record data for test + von_mises_stress_max_.push_back(solid_body_list_[0].get()->getElasticSolidParticles()->getMaxVonMisesStress()); + von_mises_stress_particles_.push_back(solid_body_list_[0].get()->getElasticSolidParticles()->getVonMisesStress()); + + von_mises_strain_max_.push_back(solid_body_list_[0].get()->getElasticSolidParticles()->getMaxVonMisesStrain()); + von_mises_strain_particles_.push_back(solid_body_list_[0].get()->getElasticSolidParticles()->getVonMisesStrain()); + // write data to file + if(surface_particles_only_to_vtu_) write_states_surface.writeToFile(); + else write_states.writeToFile(); + tick_count t3 = tick_count::now(); + interval += t3 - t2; + } + tick_count t4 = tick_count::now(); + tick_count::interval_t tt; + tt = t4 - t1 - interval; + cout << "Total wall time for computation: " << tt.seconds() << " seconds." << endl; +} + +double StructuralSimulation::runSimulationFixedDurationJS(int number_of_steps) +{ + BodyStatesRecordingToVtu write_states(in_output_, system_.real_bodies_); + GlobalStaticVariables::physical_time_ = 0.0; + + /** Statistics for computing time. */ + write_states.writeToFile(0); + int output_period = 100; + Real dt = 0.0; + tick_count t1 = tick_count::now(); + tick_count::interval_t interval; + /** Main loop */ + while (iteration_ < number_of_steps) + { + Real integration_time = 0.0; + int output_step = 0; + while (output_step < output_period) + { + runSimulationStep(dt, integration_time); + output_step++; + } + tick_count t2 = tick_count::now(); + write_states.writeToFile(); + tick_count t3 = tick_count::now(); + interval += t3 - t2; + } + tick_count t4 = tick_count::now(); + tick_count::interval_t tt; + tt = t4 - t1 - interval; + return tt.seconds(); +} + +Real StructuralSimulation::getMaxDisplacement(int body_index) +{ + StdLargeVec& pos_0 = solid_body_list_[body_index].get()->getElasticSolidParticles()->pos_0_; + StdLargeVec& pos_n = solid_body_list_[body_index].get()->getElasticSolidParticles()->pos_n_; + Real displ_max = 0; + for (size_t i = 0; i < pos_0.size(); i++) + { + Real displ = (pos_n[i] - pos_0[i]).norm(); + if (displ > displ_max) displ_max = displ; + } + return displ_max; +} \ No newline at end of file diff --git a/modules/structural_simulation/structural_simulation_class.h b/modules/structural_simulation/structural_simulation_class.h new file mode 100755 index 0000000000..4e32269e0a --- /dev/null +++ b/modules/structural_simulation/structural_simulation_class.h @@ -0,0 +1,292 @@ +/** +* @file structural_simulation_class.h +* @brief The structural simulation module is licensed under the Aladdin Free Public License (https://spdx.org/licenses/Aladdin.html) regarding usage for medical device development. +* Commercial use for medical device development is not permitted. This does not apply to applications in other fields. +* @details solid structural simulation class for general structural simulations +* @author Bence Z. Rochlitz - Virtonomy GmbH +*/ + +#ifndef SOLID_STRUCTURAL_SIMULATION_CLASS_H +#define SOLID_STRUCTURAL_SIMULATION_CLASS_H + +#include "sphinxsys.h" +#include +#include +#include + +using namespace SPH; +using namespace std; +using GravityPair = pair; +using AccelTuple = tuple; +using ForceTuple = tuple; +using PressureTuple = tuple>>; +using SpringDamperTuple = tuple; +/** +* @brief SurfaceSpringTuple +* int: body index +* TriangleMeshShape*: the body part, the normal spring is applied to +* bool: if true, the "outer" surface is considered (particle normals > 90° from the particle-source point vector), if false, the "inner" surface +* Vec3d: source point to relate inner and outer surface +* Real: normal spring stiffness +* Real: damping coefficient +*/ +using SurfaceSpringTuple = tuple; +using ConstrainedRegionPair = pair; +using PositionSolidBodyTuple = tuple; +using PositionScaleSolidBodyTuple = tuple; +using TranslateSolidBodyTuple = tuple; +using TranslateSolidBodyPartTuple = tuple; + +class BodyPartByParticleTriMesh : public BodyPartByParticle +{ +public: + BodyPartByParticleTriMesh(SPHBody* body, string body_part_name, TriangleMeshShape* triangle_mesh_shape); + ~BodyPartByParticleTriMesh(); +}; + +class ImportedModel : public SolidBody +{ +public: + ImportedModel(SPHSystem &system, string body_name, TriangleMeshShape* triangle_mesh_shape, ParticleAdaptation* particle_adaptation, StdLargeVec& pos_0, StdLargeVec& volume); + ~ImportedModel(); +}; + +class SolidBodyForSimulation +{ +private: + ImportedModel imported_model_; + //LinearElasticSolid material_model_; + ElasticSolidParticles elastic_solid_particles_; + BodyRelationInner inner_body_relation_; + + solid_dynamics::CorrectConfiguration correct_configuration_; + solid_dynamics::StressRelaxationFirstHalf stress_relaxation_first_half_; + solid_dynamics::StressRelaxationSecondHalf stress_relaxation_second_half_; + DampingWithRandomChoice> damping_random_; + +public: + SolidBodyForSimulation( + SPHSystem &system, string body_name, TriangleMeshShape& triangle_mesh_shape,ParticleAdaptation& particle_adaptation, + Real physical_viscosity, LinearElasticSolid& material_model, StdLargeVec& pos_0, StdLargeVec& volume); + ~SolidBodyForSimulation(){}; + + ImportedModel* getImportedModel() { return &imported_model_; }; + //LinearElasticSolid* GetMaterialModel() { return &material_model_; }; + ElasticSolidParticles* getElasticSolidParticles() { return &elastic_solid_particles_; }; + BodyRelationInner* getInnerBodyRelation() { return &inner_body_relation_; }; + + solid_dynamics::CorrectConfiguration* getCorrectConfiguration() { return &correct_configuration_; }; + solid_dynamics::StressRelaxationFirstHalf* getStressRelaxationFirstHalf() { return &stress_relaxation_first_half_; }; + solid_dynamics::StressRelaxationSecondHalf* getStressRelaxationSecondHalf() { return &stress_relaxation_second_half_; }; + DampingWithRandomChoice>* getDampingWithRandomChoice() { return &damping_random_; }; +}; + +void expandBoundingBox(BoundingBox* original, BoundingBox* additional); + +void relaxParticlesSingleResolution(In_Output* in_output, + bool write_particles_to_file, + ImportedModel* imported_model, + ElasticSolidParticles* imported_model_particles, + BodyRelationInner* imported_model_inner); + +static inline Real getPhysicalViscosityGeneral(Real rho, Real youngs_modulus, Real length_scale, Real shape_constant = 1.0) +{ + // the physical viscosity is defined in the paper pf prof. Hu + // https://arxiv.org/pdf/2103.08932.pdf + // physical_viscosity = (beta / 4) * sqrt(rho * Young's modulus) * L + // beta: shape constant --> how to define it? - it's 1 for now.. TODO + // L: length scale of the problem --> 10 mm roughly + return shape_constant/ 4.0 * std::sqrt(rho * youngs_modulus) * length_scale; +} + +class StructuralSimulationInput +{ +public: + string relative_input_path_; + vector imported_stl_list_; + Real scale_stl_; + vector translation_list_; + vector resolution_list_; + vector material_model_list_; + StdVec physical_viscosity_; + StdVec contacting_body_pairs_list_; + vector, array>> time_dep_contacting_body_pairs_list_; + // scale system boundaries + Real scale_system_boundaries_; + // particle relaxation + vector particle_relaxation_list_; + bool write_particle_relaxation_data_; + // boundary conditions + vector non_zero_gravity_; + vector acceleration_bounding_box_tuple_; + vector force_in_body_region_tuple_; + vector surface_pressure_tuple_; + vector spring_damper_tuple_; + vector surface_spring_tuple_; + vector body_indeces_fixed_constraint_; + vector body_indeces_fixed_constraint_region_; + vector position_solid_body_tuple_; + vector position_scale_solid_body_tuple_; + vector translation_solid_body_tuple_; + vector translation_solid_body_part_tuple_; + //option to only write surface particles into vtu + bool surface_particles_only_to_vtu_; + + StructuralSimulationInput( + string relative_input_path, + vector imported_stl_list, + Real scale_stl, + vector translation_list, + vector resolution_list, + vector material_model_list, + StdVec physical_viscosity, + StdVec contacting_bodies_list + ); +}; + +class StructuralSimulation + { + protected: + // mandatory input + string relative_input_path_; + vector imported_stl_list_; + Real scale_stl_; + vector translation_list_; + vector resolution_list_; + vector material_model_list_; + StdVec physical_viscosity_; + StdVec contacting_body_pairs_list_; + vector, array>> time_dep_contacting_body_pairs_list_; //optional: time dependent contact + vector particle_relaxation_list_; // optional: particle relaxation + bool write_particle_relaxation_data_; + + // internal members + Real system_resolution_; + SPHSystem system_; + Real scale_system_boundaries_; + In_Output in_output_; + + vector body_mesh_list_; + vector particle_adaptation_list_; + vector> solid_body_list_; + vector> particle_normal_update_; + + vector> contact_list_; + vector> contact_density_list_; + vector> contact_force_list_; + + // for initializeATimeStep + vector> initialize_gravity_; + vector non_zero_gravity_; + // for AccelerationForBodyPartInBoundingBox + vector> acceleration_bounding_box_; + vector acceleration_bounding_box_tuple_; + // for ForceInBodyRegion + vector> force_in_body_region_; + vector force_in_body_region_tuple_; + // for SurfacePressureFromSource + vector> surface_pressure_; + vector surface_pressure_tuple_; + // for SpringDamperConstraintParticleWise + vector> spring_damper_constraint_; + vector spring_damper_tuple_; + // for SpringNormalOnSurfaceParticles + vector> surface_spring_; + vector surface_spring_tuple_; + // for ConstrainSolidBody + vector> fixed_constraint_body_; + vector body_indeces_fixed_constraint_; + // for ConstrainSolidBodyRegion + vector> fixed_constraint_region_; + vector body_indeces_fixed_constraint_region_; + // for PositionSolidBody + vector> position_solid_body_; + vector position_solid_body_tuple_; + // for PositionScaleSolidBody + vector> position_scale_solid_body_; + vector position_scale_solid_body_tuple_; + // for TranslateSolidBody + vector> translation_solid_body_; + vector translation_solid_body_tuple_; + // for TranslateSolidBodyPart + vector> translation_solid_body_part_; + vector translation_solid_body_part_tuple_; + //option to only write surface particles into vtu + bool surface_particles_only_to_vtu_; + + // iterators + int iteration_; + + // data storage + vector von_mises_stress_max_; + StdLargeVec> von_mises_stress_particles_; + + vector von_mises_strain_max_; + StdLargeVec> von_mises_strain_particles_; + + // for constructor, the order is important + void scaleTranslationAndResolution(); + void setSystemResolutionMax(); + void createBodyMeshList(); + void createParticleAdaptationList(); + void calculateSystemBoundaries(); + void initializeElasticSolidBodies(); + void initializeContactBetweenTwoBodies(int first, int second); + void initializeAllContacts(); + + // for initializeBoundaryConditions + void initializeGravity(); + void initializeAccelerationForBodyPartInBoundingBox(); + void initializeForceInBodyRegion(); + void initializeSurfacePressure(); + void initializeSpringDamperConstraintParticleWise(); + void initializeSpringNormalOnSurfaceParticles(); + void initializeConstrainSolidBody(); + void initializeConstrainSolidBodyRegion(); + void initializePositionSolidBody(); + void initializePositionScaleSolidBody(); + void initializeTranslateSolidBody(); + void initializeTranslateSolidBodyPart(); + + // for runSimulation, the order is important + void executeCorrectConfiguration(); + void executeUpdateElasticNormalDirection(); + void executeinitializeATimeStep(); + void executeAccelerationForBodyPartInBoundingBox(); + void executeForceInBodyRegion(); + void executeSurfacePressure(); + void executeSpringDamperConstraintParticleWise(); + void executeSpringNormalOnSurfaceParticles(); + void executeContactDensitySummation(); + void executeContactForce(); + void executeStressRelaxationFirstHalf(Real dt); + void executeConstrainSolidBody(); + void executeConstrainSolidBodyRegion(); + void executePositionSolidBody(Real dt); + void executePositionScaleSolidBody(Real dt); + void executeTranslateSolidBody(Real dt); + void executeTranslateSolidBodyPart(Real dt); + void executeDamping(Real dt); + void executeStressRelaxationSecondHalf(Real dt); + void executeUpdateCellLinkedList(); + void executeContactUpdateConfiguration(); + + void initializeSimulation(); + + void runSimulationStep(Real &dt, Real &integration_time); + + public: + StructuralSimulation(StructuralSimulationInput& input); + ~StructuralSimulation(); + + StdVec> get_solid_body_list_(){ return solid_body_list_; }; + Real getMaxDisplacement(int body_index); + + //For c++ + void runSimulation(Real end_time); + + //For JS + double runSimulationFixedDurationJS(int number_of_steps); + }; + +#endif //SOLID_STRUCTURAL_SIMULATION_CLASS_H \ No newline at end of file diff --git a/tests/2d_examples/test_2d_self_contact/src/self_contact.cpp b/tests/2d_examples/test_2d_self_contact/src/self_contact.cpp index a10bd1529c..36007d78a3 100644 --- a/tests/2d_examples/test_2d_self_contact/src/self_contact.cpp +++ b/tests/2d_examples/test_2d_self_contact/src/self_contact.cpp @@ -181,7 +181,7 @@ int main() //time step size calculation solid_dynamics::AcousticTimeStepSize computing_time_step_size(beam_body); //stress relaxation for the beam - solid_dynamics::KirchhoffStressRelaxationFirstHalf stress_relaxation_first_half(beam_body_inner); + solid_dynamics::StressRelaxationFirstHalf stress_relaxation_first_half(beam_body_inner); solid_dynamics::StressRelaxationSecondHalf stress_relaxation_second_half(beam_body_inner); // algorithms for solid self contact solid_dynamics::DynamicSelfContactForce beam_self_contact_forces(beam_self_contact); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0de3750ff2..1d31fd28e6 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -17,10 +17,10 @@ if(NOT EMSCRIPTEN) if(BUILD_UNIT_TESTS) ADD_SUBDIRECTORY(unit_tests_src) endif() + + ADD_SUBDIRECTORY(modules) endif() if(BUILD_3D_EXAMPLES) ADD_SUBDIRECTORY(3d_examples) endif() - - diff --git a/tests/modules/CMakeLists.txt b/tests/modules/CMakeLists.txt new file mode 100755 index 0000000000..25d1ef3df4 --- /dev/null +++ b/tests/modules/CMakeLists.txt @@ -0,0 +1,5 @@ +SUBDIRLIST(SUBDIRS ${CMAKE_CURRENT_SOURCE_DIR}) + +FOREACH(subdir ${SUBDIRS}) + ADD_SUBDIRECTORY(${subdir}) +ENDFOREACH() diff --git a/tests/modules/bernoulli_beam_struct_sim/CMakeLists.txt b/tests/modules/bernoulli_beam_struct_sim/CMakeLists.txt new file mode 100755 index 0000000000..85db35fcab --- /dev/null +++ b/tests/modules/bernoulli_beam_struct_sim/CMakeLists.txt @@ -0,0 +1,65 @@ +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${SPHINXSYS_PROJECT_DIR}/cmake) # main (top) cmake dir +set(CMAKE_VERBOSE_MAKEFILE on) + +STRING( REGEX REPLACE ".*/(.*)" "\\1" CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} ) +PROJECT("${CURRENT_FOLDER}") + +include(ImportSPHINXsysFromSource_for_3D_build) + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) +set(EXECUTABLE_OUTPUT_PATH "${PROJECT_BINARY_DIR}/bin/") +set(BUILD_INPUT_PATH "${EXECUTABLE_OUTPUT_PATH}/input") +set(BUILD_RELOAD_PATH "${EXECUTABLE_OUTPUT_PATH}/reload") + +file(MAKE_DIRECTORY ${BUILD_INPUT_PATH}) +execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${BUILD_INPUT_PATH}) + +file(GLOB_RECURSE FILES_STL "*.stl") +foreach(STL_FILE ${FILES_STL}) + file(COPY ${STL_FILE} DESTINATION ${BUILD_INPUT_PATH}) +endforeach() + +aux_source_directory(. DIR_SRCS) +ADD_EXECUTABLE(${PROJECT_NAME} ${DIR_SRCS}) +target_link_libraries(${PROJECT_NAME} structural_simulation_module) + +target_include_directories(${PROJECT_NAME} PUBLIC ${SPHINXSYS_PROJECT_DIR}/modules/structural_simulation) + +gtest_discover_tests(${PROJECT_NAME} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) + +if(NOT STATIC_BUILD) # usual dynamic build + if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + target_link_libraries(${PROJECT_NAME} sphinxsys_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) + else(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++ stdc++fs gtest gtest_main) + endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + + if(DEFINED BOOST_AVAILABLE) # link Boost if available (not for Windows) + target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) + endif() + endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") +else() # static build only + if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + target_link_libraries(${PROJECT_NAME} sphinxsys_static_3d) + else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + target_link_libraries(${PROJECT_NAME} sphinxsys_static_3d stdc++) + else(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + target_link_libraries(${PROJECT_NAME} sphinxsys_static_3d stdc++ stdc++fs gtest gtest_main) + endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + + if(DEFINED BOOST_AVAILABLE) # link Boost if available (not for Windows) + target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) + endif() + endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") +endif() +if(NOT BUILD_WITH_SIMBODY) # link Simbody if not built by the project +target_link_libraries(${PROJECT_NAME} ${Simbody_LIBRARIES}) +endif() +if(NOT BUILD_WITH_ONETBB) # link TBB if not built by the project +target_link_libraries(${PROJECT_NAME} ${TBB_LIBRARYS}) +endif() \ No newline at end of file diff --git a/tests/modules/bernoulli_beam_struct_sim/bernoulli_beam_struct_sim.cpp b/tests/modules/bernoulli_beam_struct_sim/bernoulli_beam_struct_sim.cpp new file mode 100755 index 0000000000..188c926121 --- /dev/null +++ b/tests/modules/bernoulli_beam_struct_sim/bernoulli_beam_struct_sim.cpp @@ -0,0 +1,62 @@ +#include +#include "structural_simulation_class.h" + +TEST(BernoulliBeam20x, Pressure) +{ + Real scale_stl = 0.001; + Real end_time = 0.15; + + Real rho_0 = 6.45e3; // Nitinol + Real poisson = 0.3; + Real Youngs_modulus = 5e8; + Real physical_viscosity = Youngs_modulus / 100; + Real pressure = 1e3; + + /** STL IMPORT PARAMETERS */ + std::string relative_input_path = "./input/"; //path definition for linux + std::vector imported_stl_list = { "bernoulli_beam_20x.stl" }; + std::vector translation_list = { Vec3d(0) }; + std::vector resolution_list = { 10.0 / 6.0 }; + LinearElasticSolid material = LinearElasticSolid(rho_0, Youngs_modulus, poisson); + std::vector material_model_list = { material }; + + TriangleMeshShape specimen("./input/bernoulli_beam_20x.stl", Vec3d(0), scale_stl); + BoundingBox fixation = specimen.findBounds(); + fixation.second[0] = fixation.first[0] + 0.01; + + StructuralSimulationInput input + { + relative_input_path, + imported_stl_list, + scale_stl, + translation_list, + resolution_list, + material_model_list, + {physical_viscosity}, + {} + }; + input.surface_particles_only_to_vtu_ = { true }; + input.body_indeces_fixed_constraint_region_ = StdVec{ ConstrainedRegionPair(0, fixation) }; + StdVec> pressure_over_time = { + {0.0, 0.0}, + {end_time * 0.1, pressure}, + {end_time, pressure } + }; + input.surface_pressure_tuple_ = StdVec{ PressureTuple(0, &specimen, Vec3d(0.1, 0.0, 0.1), pressure_over_time) }; + input.particle_relaxation_list_ = { true }; + + //=================================================================================================// + StructuralSimulation sim(input); + sim.runSimulation(end_time); + + Real displ_max = sim.getMaxDisplacement(0); + Real displ_max_analytical = 4.8e-3; // in mm, absolute max displacement + EXPECT_NEAR(displ_max, displ_max_analytical, displ_max_analytical * 0.1); + std::cout << "displ_max: " << displ_max << std::endl; +} + +int main(int argc, char* argv[]) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tests/modules/bernoulli_beam_struct_sim/input/bernoulli_beam.stl b/tests/modules/bernoulli_beam_struct_sim/input/bernoulli_beam.stl new file mode 100755 index 0000000000000000000000000000000000000000..f253e2bee62ddaed0008ff14419755d666129a2c GIT binary patch literal 684 zcmb`EK@P$&3DKs~|!h^hUL3%%*l&*}IEK@UtRO+WNUMJi6UphprC=x4?LsM%vb zhtFrqG~4)rP!DR*Adsd?Q)v=vugRix7j>J@_bb)6_o)5hr|wMXM~`^Hx+@Y*?oBo5 Otn%UBCVO4p2KoaQY^vJ; literal 0 HcmV?d00001 diff --git a/tests/modules/bernoulli_beam_struct_sim/input/bernoulli_beam_20x.stl b/tests/modules/bernoulli_beam_struct_sim/input/bernoulli_beam_20x.stl new file mode 100755 index 0000000000000000000000000000000000000000..45ebfdd1046737fcd7a78535b4d311ee3ef0c187 GIT binary patch literal 684 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 literal 0 HcmV?d00001 diff --git a/tests/modules/mass_spring_damper_response_struct_sim/mass_spring_damper_response_struct_sim.cpp b/tests/modules/mass_spring_damper_response_struct_sim/mass_spring_damper_response_struct_sim.cpp new file mode 100755 index 0000000000..a858c4d507 --- /dev/null +++ b/tests/modules/mass_spring_damper_response_struct_sim/mass_spring_damper_response_struct_sim.cpp @@ -0,0 +1,60 @@ +#include +#include "structural_simulation_class.h" + +TEST(StructuralSimulation, MassSpringDamperResponse) +{ + /** INPUT PARAMETERS */ + Real scale_stl = 0.001 / 4; // diameter of 0.025 m + Real resolution_mass = 8; + Real poisson = 0.35; + Real Youngs_modulus = 1e7; + Real physical_viscosity = 200; + // SI setup - designed + Real rho_0 = 122231; + Real gravity_force = 10; + Real spring_coeff = 200; + Real spring_damper_ratio = 0.05; + Real end_time = 2; + /** STL IMPORT PARAMETERS */ + std::string relative_input_path = "./input/"; //path definition for linux + std::vector imported_stl_list = { "ball_mass.stl" }; + std::vector translation_list = { Vec3d(0) }; + std::vector resolution_list = { resolution_mass}; + LinearElasticSolid material = LinearElasticSolid(rho_0, Youngs_modulus, poisson); + std::vector material_model_list = { material }; + /** INPUT DECLERATION */ + StructuralSimulationInput input + { + relative_input_path, + imported_stl_list, + scale_stl, + translation_list, + resolution_list, + material_model_list, + {physical_viscosity}, + {} + }; + input.non_zero_gravity_ = vector{ GravityPair(0, Vec3d(0.0, 0.0, gravity_force)) }; + input.spring_damper_tuple_ = { SpringDamperTuple(0, Vec3d(0, 0, spring_coeff), spring_damper_ratio) }; + + //=================================================================================================// + StructuralSimulation sim(input); + sim.runSimulation(end_time); + //=================================================================================================// + + StdLargeVec& pos_0 = sim.get_solid_body_list_()[0].get()->getElasticSolidParticles()->pos_0_; + StdLargeVec& pos_n = sim.get_solid_body_list_()[0].get()->getElasticSolidParticles()->pos_n_; + Real end_displ = 0.05; + + for (size_t index = 0; index < pos_0.size(); index++) + { + Real end_pos = pos_0[index][2] + end_displ; + EXPECT_NEAR(pos_n[index][2], end_pos, end_displ * 1e-2); + } +} + +int main(int argc, char* argv[]) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tests/unit_tests_src/shared/test_vonMisesStrain/CMakeLists.txt b/tests/unit_tests_src/shared/test_vonMisesStrain/CMakeLists.txt new file mode 100644 index 0000000000..714d26597b --- /dev/null +++ b/tests/unit_tests_src/shared/test_vonMisesStrain/CMakeLists.txt @@ -0,0 +1,61 @@ +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${SPHINXSYS_PROJECT_DIR}/cmake) # main (top) cmake dir +set(CMAKE_VERBOSE_MAKEFILE on) + +STRING( REGEX REPLACE ".*/(.*)" "\\1" CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} ) +PROJECT("${CURRENT_FOLDER}") + +include(ImportSPHINXsysFromSource_for_3D_build) + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) +set(EXECUTABLE_OUTPUT_PATH "${PROJECT_BINARY_DIR}/bin/") +set(BUILD_INPUT_PATH "${EXECUTABLE_OUTPUT_PATH}/input") +set(BUILD_RELOAD_PATH "${EXECUTABLE_OUTPUT_PATH}/reload") + +file(MAKE_DIRECTORY ${BUILD_INPUT_PATH}) +execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${BUILD_INPUT_PATH}) + +aux_source_directory(. DIR_SRCS) +ADD_EXECUTABLE(${PROJECT_NAME} ${EXECUTABLE_OUTPUT_PATH} ${DIR_SRCS}) + +gtest_discover_tests(${PROJECT_NAME} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) + +add_test(NAME ${PROJECT_NAME}_particle_relaxation + COMMAND ${PROJECT_NAME} --r=true + WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) + +if(NOT SPH_ONLY_STATIC_BUILD) # usual dynamic build + if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + target_link_libraries(${PROJECT_NAME} sphinxsys_3d) + add_dependencies(${PROJECT_NAME} sphinxsys_3d sphinxsys_static_3d) + else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++) + else(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + target_link_libraries(${PROJECT_NAME} sphinxsys_3d stdc++ stdc++fs gtest gtest_main) + endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + + if(DEFINED BOOST_AVAILABLE) # link Boost if available (not for Windows) + target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) + endif() + endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") +else() # static build only + if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + target_link_libraries(${PROJECT_NAME} sphinxsys_static_3d) + else(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + target_link_libraries(${PROJECT_NAME} sphinxsys_static_3d stdc++) + else(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + target_link_libraries(${PROJECT_NAME} sphinxsys_static_3d stdc++ stdc++fs gtest gtest_main) + endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + + if(DEFINED BOOST_AVAILABLE) # link Boost if available (not for Windows) + target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) + endif() + endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") +endif() +if(NOT BUILD_WITH_SIMBODY) # link Simbody if not built by the project +target_link_libraries(${PROJECT_NAME} ${Simbody_LIBRARIES}) +endif() +if(NOT BUILD_WITH_ONETBB) # link TBB if not built by the project +target_link_libraries(${PROJECT_NAME} ${TBB_LIBRARYS}) +endif() \ No newline at end of file diff --git a/tests/unit_tests_src/shared/test_vonMisesStrain/test_vonMisesStrain.cpp b/tests/unit_tests_src/shared/test_vonMisesStrain/test_vonMisesStrain.cpp new file mode 100644 index 0000000000..dc32303178 --- /dev/null +++ b/tests/unit_tests_src/shared/test_vonMisesStrain/test_vonMisesStrain.cpp @@ -0,0 +1,45 @@ +#include +#include "solid_particles.h" + +using namespace SPH; + +TEST(VonMisesStrainCalc, vonMisesStrain) +{ + Real tolerance = 1e-6; + + Matd strain_tensor_1 = Matd( Vecd(1, 2, 3), Vecd(2, 5, 6), Vecd(3, 6, 9)); + + Real epsilonxx_1 = strain_tensor_1(0, 0); + Real epsilonyy_1 = strain_tensor_1(1, 1); + Real epsilonzz_1 = strain_tensor_1(2, 2); + Real epsilonxy_1 = strain_tensor_1(0, 1); + Real epsilonxz_1 = strain_tensor_1(0, 2); + Real epsilonyz_1 = strain_tensor_1(1, 2); + + Real von_Mises_strain_1 = sqrt( (1.0 / 3.0) * (std::pow(epsilonxx_1 - epsilonyy_1, 2.0) + std::pow(epsilonyy_1 - epsilonzz_1, 2.0) + std::pow(epsilonzz_1 - epsilonxx_1, 2.0)) + + 2.0 * (std::pow(epsilonxy_1, 2.0) + std::pow(epsilonyz_1, 2.0) + std::pow(epsilonxz_1, 2.0))); + Real von_Mises_strain_ref_1 = 11.4017543; + + Matd strain_tensor_2 = Matd( Vecd(-5, 9, 1), Vecd(9, 4, -7), Vecd(1, -7, -12)); + + Real epsilonxx_2 = strain_tensor_2(0, 0); + Real epsilonyy_2 = strain_tensor_2(1, 1); + Real epsilonzz_2 = strain_tensor_2(2, 2); + Real epsilonxy_2 = strain_tensor_2(0, 1); + Real epsilonxz_2 = strain_tensor_2(0, 2); + Real epsilonyz_2 = strain_tensor_2(1, 2); + + Real von_Mises_strain_2 = sqrt( (1.0 / 3.0) * (std::pow(epsilonxx_2 - epsilonyy_2, 2.0) + std::pow(epsilonyy_2 - epsilonzz_2, 2.0) + std::pow(epsilonzz_2 - epsilonxx_2, 2.0)) + + 2.0 * (std::pow(epsilonxy_2, 2.0) + std::pow(epsilonyz_2, 2.0) + std::pow(epsilonxz_2, 2.0))); + Real von_Mises_strain_ref_2 = 19.7652894; + + EXPECT_NEAR(von_Mises_strain_1, von_Mises_strain_ref_1, tolerance); + EXPECT_NEAR(von_Mises_strain_2, von_Mises_strain_ref_2, tolerance); + +} +//=================================================================================================// +int main(int argc, char* argv[]) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file From 66522c387e5977083d74da7131bc561b9248c041 Mon Sep 17 00:00:00 2001 From: xiangyu_hu Date: Sat, 18 Dec 2021 00:12:06 +0100 Subject: [PATCH 06/41] update from bibucket on 12.18.2021 --- .../bodies/solid_body_supplementary.cpp | 14 +- .../geometries/all_geometries.h | 5 +- .../geometries/level_set_supplementary.cpp | 20 +- .../{geometry.cpp => multi_polygon_shape.cpp} | 102 +- .../{geometry.h => multi_polygon_shape.h} | 57 +- ...rticle_generator_lattice_supplementary.cpp | 8 +- .../bodies/solid_body_supplementary.cpp | 21 +- .../for_3D_build/geometries/all_geometries.h | 15 + .../geometries/complex_shape_image_mesh.cpp | 168 - .../geometries/complex_shape_image_mesh.h | 94 - .../complex_shape_triangle_mesh.cpp | 183 - .../geometries/complex_shape_triangle_mesh.h | 89 - .../src/for_3D_build/geometries/geometry.h | 142 - .../geometries/image_mesh_shape.cpp | 75 - .../for_3D_build/geometries/image_shape.cpp | 72 + .../{image_mesh_shape.h => image_shape.h} | 59 +- .../geometries/level_set_supplementary.cpp | 20 +- .../{geometry.cpp => triangle_mesh_shape.cpp} | 115 +- .../geometries/triangle_mesh_shape.h | 122 + ...rticle_generator_lattice_supplementary.cpp | 8 +- .../particle_generator_network.cpp | 137 +- .../particle_generator_network.h | 43 +- .../CMakeLists.txt | 0 .../adaptation.cpp} | 64 +- .../adaptation.h} | 77 +- SPHINXsys/src/shared/bodies/all_bodies.h | 2 + SPHINXsys/src/shared/bodies/base_body.cpp | 187 +- SPHINXsys/src/shared/bodies/base_body.h | 243 +- SPHINXsys/src/shared/bodies/body_relation.cpp | 148 +- SPHINXsys/src/shared/bodies/body_relation.h | 87 +- SPHINXsys/src/shared/bodies/fluid_body.cpp | 12 +- SPHINXsys/src/shared/bodies/fluid_body.h | 10 +- SPHINXsys/src/shared/bodies/observer_body.h | 52 + SPHINXsys/src/shared/bodies/solid_body.cpp | 29 +- SPHINXsys/src/shared/bodies/solid_body.h | 45 +- .../src/shared/common/array_allocation.h | 2 +- .../src/shared/common/base_data_package.h | 3 +- SPHINXsys/src/shared/common/image_mhd.h | 2 +- .../src/shared/common/large_data_containers.h | 7 +- SPHINXsys/src/shared/common/ownership.h | 180 + .../src/shared/common/scalar_functions.cpp | 65 + .../src/shared/common/scalar_functions.h | 3 + .../src/shared/common/sph_data_containers.h | 97 +- ...small_vectors.cpp => vector_functions.cpp} | 4 +- .../{small_vectors.h => vector_functions.h} | 0 .../generative_structures.cpp | 12 +- .../generative_structures.h | 17 +- .../src/shared/geometries/base_geometry.cpp | 137 + .../src/shared/geometries/base_geometry.h | 94 +- .../src/shared/geometries/complex_shape.cpp | 11 + .../geometries/complex_shape.h} | 60 +- SPHINXsys/src/shared/geometries/level_set.cpp | 33 +- SPHINXsys/src/shared/geometries/level_set.h | 18 +- ...etry_level_set.cpp => level_set_shape.cpp} | 42 +- ...geometry_level_set.h => level_set_shape.h} | 32 +- SPHINXsys/src/shared/include/sphinxsys.h | 5 +- SPHINXsys/src/shared/io_system/in_output.cpp | 257 +- SPHINXsys/src/shared/io_system/in_output.h | 513 +- SPHINXsys/src/shared/kernels/all_kernels.h | 1 + SPHINXsys/src/shared/kernels/base_kernel.cpp | 48 +- SPHINXsys/src/shared/kernels/base_kernel.h | 23 +- .../shared/kernels/kernel_cubic_B_spline.cpp | 87 + .../shared/kernels/kernel_cubic_B_spline.h | 67 + .../src/shared/kernels/kernel_tabulated.hpp | 36 +- .../src/shared/materials/base_material.cpp | 54 + .../src/shared/materials/base_material.h | 117 +- .../src/shared/materials/complex_solid.h | 19 +- .../src/shared/materials/complex_solid.hpp | 39 +- .../src/shared/materials/compressible_fluid.h | 22 +- .../shared/materials/diffusion_reaction.cpp | 107 +- .../src/shared/materials/diffusion_reaction.h | 271 +- .../src/shared/materials/elastic_solid.cpp | 225 +- .../src/shared/materials/elastic_solid.h | 194 +- .../src/shared/materials/inelastic_solid.cpp | 12 +- .../src/shared/materials/inelastic_solid.h | 35 +- .../src/shared/materials/riemann_solver.cpp | 225 +- .../src/shared/materials/riemann_solver.h | 85 +- .../materials/weakly_compressible_fluid.cpp | 29 +- .../materials/weakly_compressible_fluid.h | 91 +- SPHINXsys/src/shared/meshes/base_mesh.h | 17 +- .../src/shared/meshes/cell_linked_list.cpp | 16 +- .../src/shared/meshes/cell_linked_list.h | 6 +- .../shared/meshes/mesh_with_data_packages.h | 34 +- .../active_muscle_dynamics.cpp | 16 +- .../active_muscle_dynamics.h | 6 +- .../base_particle_dynamics.h | 184 +- .../base_particle_dynamics.hpp | 30 +- .../particle_dynamics_diffusion_reaction.h | 327 +- .../particle_dynamics_diffusion_reaction.hpp | 326 +- .../particle_dynamics_dissipation.h | 21 +- .../particle_dynamics_dissipation.hpp | 221 +- .../electro_physiology/electro_physiology.cpp | 6 +- .../electro_physiology/electro_physiology.h | 28 +- .../fluid_dynamics/all_fluid_dynamics.h | 2 - .../eulerian_fluid_dynamics_complex.cpp | 2 - .../eulerian_fluid_dynamics_complex.h | 126 +- .../eulerian_fluid_dynamics_complex.hpp | 58 +- .../eulerian_fluid_dynamics_inner.cpp | 101 +- .../eulerian_fluid_dynamics_inner.h | 93 +- .../eulerian_fluid_dynamics_inner.hpp | 51 +- .../fluid_dynamics/fluid_dynamics_complex.cpp | 180 +- .../fluid_dynamics/fluid_dynamics_complex.h | 261 +- .../fluid_dynamics/fluid_dynamics_complex.hpp | 368 +- .../fluid_dynamics_compound.cpp | 18 - .../fluid_dynamics/fluid_dynamics_compound.h | 103 - .../fluid_dynamics_compound.hpp | 21 - .../fluid_dynamics/fluid_dynamics_inner.cpp | 496 +- .../fluid_dynamics/fluid_dynamics_inner.h | 466 +- .../fluid_dynamics/fluid_dynamics_inner.hpp | 57 +- .../fluid_dynamics_multi_phase.cpp | 64 +- .../fluid_dynamics_multi_phase.h | 34 +- .../fluid_dynamics_multi_phase.hpp | 36 +- .../general_dynamics/general_dynamics.cpp | 382 +- .../general_dynamics/general_dynamics.h | 335 +- .../observer_dynamics/observer_dynamics.cpp | 6 +- .../observer_dynamics/observer_dynamics.h | 117 +- .../particle_dynamics_algorithms.cpp | 65 +- .../particle_dynamics_algorithms.h | 76 +- .../particle_dynamics_bodypart.cpp | 120 +- .../particle_dynamics_bodypart.h | 112 +- .../relax_dynamics/relax_dynamics.cpp | 148 +- .../relax_dynamics/relax_dynamics.h | 148 +- .../solid_dynamics/contact_dynamics.cpp | 76 +- .../solid_dynamics/contact_dynamics.h | 96 +- .../fluid_structure_interaction.cpp | 83 +- .../fluid_structure_interaction.h | 161 +- .../solid_dynamics/inelastic_dynamics.cpp | 10 +- .../solid_dynamics/inelastic_dynamics.h | 9 +- .../solid_dynamics/solid_dynamics.cpp | 346 +- .../solid_dynamics/solid_dynamics.h | 389 +- .../thin_structure_dynamics.cpp | 330 +- .../solid_dynamics/thin_structure_dynamics.h | 206 +- .../base_particle_generator.cpp | 28 +- .../base_particle_generator.h | 32 +- .../particle_generator_lattice.cpp | 30 +- .../particle_generator_lattice.h | 29 +- .../src/shared/particles/all_particles.h | 1 + .../src/shared/particles/base_particles.cpp | 274 +- .../src/shared/particles/base_particles.h | 297 +- .../src/shared/particles/base_particles.hpp | 196 + .../diffusion_reaction_particles.cpp | 21 +- .../particles/diffusion_reaction_particles.h | 67 +- .../src/shared/particles/fluid_particles.cpp | 32 +- .../src/shared/particles/fluid_particles.h | 53 +- .../shared/particles/neighbor_relation.cpp | 113 +- .../src/shared/particles/neighbor_relation.h | 101 +- .../src/shared/particles/observer_particles.h | 46 + .../src/shared/particles/particle_sorting.cpp | 53 +- .../src/shared/particles/particle_sorting.h | 198 +- .../src/shared/particles/solid_particles.cpp | 114 +- .../src/shared/particles/solid_particles.h | 140 +- .../src/shared/regression_test/CMakeLists.txt | 8 + .../dyanmic_time_warping_method.hpp | 201 + .../dynamic_time_warping_method.h | 131 + .../ensemble_averaged_method.h | 116 + .../ensemble_averaged_method.hpp | 370 + .../regression_test.h} | 18 +- .../regression_test/regression_test_base.h | 121 + .../regression_test/regression_test_base.hpp | 150 + .../regression_test/time_averaged_method.h | 141 + .../regression_test/time_averaged_method.hpp | 599 + .../meanvalue_variance_method.h | 203 - .../meanvalue_variance_method.hpp | 663 - .../shared/simbody_sphinxsys/state_engine.cpp | 3 +- .../shared/simbody_sphinxsys/state_engine.h | 8 +- .../shared/simbody_sphinxsys/xml_engine.cpp | 12 +- .../shared/sphinxsys_system/sph_system.cpp | 107 +- .../src/shared/sphinxsys_system/sph_system.h | 48 +- .../structural_simulation_class.cpp | 493 +- .../structural_simulation_class.h | 358 +- .../CMakeLists.txt | 21 +- .../regression_test.cpp | 367 + .../regression_test_tool.py | 71 + .../test_1d_shock_tube/src/shock_tube.cpp | 227 +- .../test_1d_shock_tube/src/shock_tube.h | 109 - .../src/T_shaped_pipe.cpp | 386 +- .../test_2d_airfoil/airfoil_2d.cpp | 30 +- .../2d_examples/test_2d_airfoil/airfoil_2d.h | 23 +- .../test_2d_collision/CMakeLists.txt | 57 +- .../test_2d_collision/{src => }/collision.cpp | 219 +- ...pingBallObserver_Position_Run_0_result.xml | 9 + ...pingBallObserver_Position_Run_3_result.xml | 9 + ...pingBallObserver_Position_Run_5_result.xml | 9 + ...mpingBallObserver_Position_dtwdistance.xml | 4 + .../DampingBallObserver_Position_runtimes.dat | 3 + ...FreeBallObserver_Position_Run_0_result.xml | 9 + ...FreeBallObserver_Position_Run_4_result.xml | 9 + ...FreeBallObserver_Position_Run_8_result.xml | 9 + .../FreeBallObserver_Position_dtwdistance.xml | 4 + .../FreeBallObserver_Position_runtimes.dat | 3 + .../regression_test_tool.py | 88 + .../test_2d_collision/src/CMakeLists.txt | 25 - .../test_2d_dambreak/CMakeLists.txt | 57 +- .../test_2d_dambreak/{src => }/Dambreak.cpp | 212 +- .../Fluidobserver_Pressure_Run_0_result.xml | 9 + .../Fluidobserver_Pressure_Run_10_result.xml | 9 + .../Fluidobserver_Pressure_Run_19_result.xml | 9 + .../Fluidobserver_Pressure_dtwdistance.xml | 4 + .../Fluidobserver_Pressure_runtimes.dat | 3 + ...ody_TotalMechanicalEnergy_Run_0_result.xml | 9 + ...dy_TotalMechanicalEnergy_Run_11_result.xml | 9 + ...ody_TotalMechanicalEnergy_Run_5_result.xml | 9 + ...Body_TotalMechanicalEnergy_dtwdistance.xml | 4 + ...terBody_TotalMechanicalEnergy_runtimes.dat | 3 + .../regression_test_tool.py | 86 + .../test_2d_dambreak/src/CMakeLists.txt | 25 - .../test_2d_depolarization/CMakeLists.txt | 39 +- .../{src => }/depolarization.cpp | 102 +- ...oltage_ensemble_averaged_mean_variance.xml | 3209 ++ .../VoltageObserver_Voltage_runtimes.dat | 3 + .../regression_test_tool.py | 79 + .../test_2d_depolarization/src/CMakeLists.txt | 24 - .../test_2d_diffusion/CMakeLists.txt | 39 +- .../test_2d_diffusion/{src => }/diffusion.cpp | 160 +- ...er_Phi_ensemble_averaged_mean_variance.xml | 17 + .../TemperatureObserver_Phi_runtimes.dat | 3 + .../regression_test_tool.py | 79 + .../test_2d_diffusion/src/CMakeLists.txt | 24 - .../test_2d_elastic_gate/CMakeLists.txt | 45 +- .../test_2d_elastic_gate/elastic_gate.cpp | 350 + .../Observer_Position_Run_0_result.xml | 9 + .../Observer_Position_Run_4_result.xml | 9 + .../Observer_Position_Run_8_result.xml | 9 + .../Observer_Position_dtwdistance.xml | 4 + .../Observer_Position_runtimes.dat | 3 + .../regression_test_tool.py | 79 + .../test_2d_elastic_gate/src/CMakeLists.txt | 24 - .../test_2d_elastic_gate/src/elastic_gate.cpp | 418 - .../2d_eulerian_taylor_green.cpp | 223 + .../CMakeLists.txt | 43 +- ...mSpeed_ensemble_averaged_mean_variance.xml | 107 + .../WaterBody_MaximumSpeed_runtimes.dat | 3 + ...Energy_ensemble_averaged_mean_variance.xml | 109 + ...terBody_TotalMechanicalEnergy_runtimes.dat | 3 + .../regression_test_tool.py | 86 + .../src/2d_eulerian_taylor_green.cpp | 242 - .../src/CMakeLists.txt | 24 - .../test_2d_filling_tank/CMakeLists.txt | 56 +- .../{src => }/filling_tank.cpp | 210 +- .../Fluidobserver_Pressure_Run_0_result.xml | 9 + .../Fluidobserver_Pressure_Run_11_result.xml | 9 + .../Fluidobserver_Pressure_Run_22_result.xml | 9 + .../Fluidobserver_Pressure_dtwdistance.xml | 4 + .../Fluidobserver_Pressure_runtimes.dat | 3 + ...ody_TotalMechanicalEnergy_Run_0_result.xml | 9 + ...dy_TotalMechanicalEnergy_Run_13_result.xml | 9 + ...ody_TotalMechanicalEnergy_Run_6_result.xml | 9 + ...Body_TotalMechanicalEnergy_dtwdistance.xml | 4 + ...terBody_TotalMechanicalEnergy_runtimes.dat | 3 + .../regression_test_tool.py | 86 + .../test_2d_filling_tank/src/CMakeLists.txt | 25 - .../2d_flow_around_cylinder.cpp | 267 + .../2d_flow_around_cylinder.h | 145 + .../CMakeLists.txt | 43 +- .../{src => }/data/project_parameters.dat | 0 ...nder_TotalViscousForceOnSolid_runtimes.dat | 3 + ...rceOnSolid_time_averaged_mean_variance.xml | 9 + .../regression_test_tool.py | 81 + .../src/2d_flow_around_cylinder.cpp | 267 - .../src/2d_flow_around_cylinder.h | 180 - .../2d_free_stream_around_cylinder .cpp | 274 + .../2d_free_stream_around_cylinder.h | 158 + .../CMakeLists.txt | 44 +- .../{src => }/data/project_parameters.dat | 0 ...nder_TotalViscousForceOnSolid_runtimes.dat | 3 + ...rceOnSolid_time_averaged_mean_variance.xml | 9 + .../regression_test_tool.py | 81 + .../src/2d_free_stream_around_cylinder .cpp | 275 - .../src/2d_free_stream_around_cylinder.h | 239 - .../src/CMakeLists.txt | 36 - tests/2d_examples/test_2d_fsi2/CMakeLists.txt | 51 +- tests/2d_examples/test_2d_fsi2/fsi2.cpp | 315 + tests/2d_examples/test_2d_fsi2/fsi2.h | 224 + .../BeamObserver_Position_Run_0_result.xml | 9 + .../BeamObserver_Position_Run_10_result.xml | 9 + .../BeamObserver_Position_Run_5_result.xml | 9 + .../BeamObserver_Position_dtwdistance.xml | 4 + .../BeamObserver_Position_runtimes.dat | 3 + ...Body_TotalViscousForceOnSolid_runtimes.dat | 3 + ...rceOnSolid_time_averaged_mean_variance.xml | 9 + .../regression_test_tool.py | 88 + .../test_2d_fsi2/src/CMakeLists.txt | 25 - tests/2d_examples/test_2d_fsi2/src/fsi2.cpp | 313 - .../2d_examples/test_2d_fsi2/src/fsi2_case.h | 283 - .../test_2d_heat_transfer/CMakeLists.txt | 40 +- .../test_2d_heat_transfer/heat_transfer.cpp | 427 + ...er_Phi_ensemble_averaged_mean_variance.xml | 201 + .../FluidObserver_Phi_runtimes.dat | 3 + .../regression_test_tool.py | 79 + .../test_2d_heat_transfer/src/CMakeLists.txt | 24 - .../src/heat_transfer.cpp | 485 - .../test_2d_hydrostatic_fsi/CMakeLists.txt | 39 +- .../{src => }/hydrostatic_fsi.cpp | 299 +- ...sition_ensemble_averaged_mean_variance.xml | 1833 + .../Observer_Position_runtimes.dat | 3 + .../regression_test_tool.py | 79 + .../src/CMakeLists.txt | 24 - .../test_2d_oscillating_beam/CMakeLists.txt | 39 +- .../{src => }/oscillating_beam.cpp | 252 +- ...sition_ensemble_averaged_mean_variance.xml | 207 + .../BeamObserver_Position_runtimes.dat | 3 + .../regression_test_tool.py | 79 + .../src/CMakeLists.txt | 24 - tests/2d_examples/test_2d_owsc/CMakeLists.txt | 45 +- .../test_2d_owsc/{src => }/owsc.cpp | 104 +- tests/2d_examples/test_2d_owsc/owsc.h | 424 + .../Flap_TotalForceOnSolid_Run_0_result.xml | 9 + .../Flap_TotalForceOnSolid_Run_11_result.xml | 9 + .../Flap_TotalForceOnSolid_Run_6_result.xml | 9 + .../Flap_TotalForceOnSolid_dtwdistance.xml | 4 + .../Flap_TotalForceOnSolid_runtimes.dat | 3 + .../regression_test_tool.py | 86 + .../test_2d_owsc/src/CMakeLists.txt | 24 - tests/2d_examples/test_2d_owsc/src/case.h | 532 - .../particle_generator_single_resolution.cpp | 22 +- .../particle_generator_single_resolution.h | 13 +- tests/2d_examples/test_2d_plate/2d_plate.cpp | 237 + .../2d_examples/test_2d_plate/CMakeLists.txt | 45 +- .../PlateObserver_Position_Run_0_result.xml | 9 + .../PlateObserver_Position_Run_3_result.xml | 9 + .../PlateObserver_Position_Run_5_result.xml | 9 + .../PlateObserver_Position_dtwdistance.xml | 4 + .../PlateObserver_Position_runtimes.dat | 3 + .../regression_test_tool.py | 79 + .../test_2d_plate/src/2d_plate.cpp | 258 - .../test_2d_plate/src/CMakeLists.txt | 24 - .../src/poiseuille_flow.cpp | 128 +- .../test_2d_self_contact/CMakeLists.txt | 45 +- .../BeamObserver_Position_0.xml | 103 + .../BeamObserver_Position_Run_0_result.xml | 9 + .../BeamObserver_Position_Run_1_result.xml | 9 + .../BeamObserver_Position_Run_2_result.xml | 9 + .../BeamObserver_Position_Run_3_result.xml | 9 + .../BeamObserver_Position_Run_4_result.xml | 9 + .../BeamObserver_Position_Run_5_result.xml | 9 + .../BeamObserver_Position_dtwdistance.xml | 4 + .../BeamObserver_Position_runtimes.dat | 3 + .../regression_test_tool.py | 79 + .../{src => }/self_contact.cpp | 106 +- .../test_2d_self_contact/src/CMakeLists.txt | 24 - .../test_2d_shell/{src => }/2d_shell.cpp | 175 +- .../2d_examples/test_2d_shell/CMakeLists.txt | 45 +- ...CylinderObserver_Position_Run_0_result.xml | 9 + ...CylinderObserver_Position_Run_3_result.xml | 9 + ...CylinderObserver_Position_Run_5_result.xml | 9 + .../CylinderObserver_Position_dtwdistance.xml | 4 + .../CylinderObserver_Position_runtimes.dat | 3 + .../regression_test_tool.py | 79 + .../test_2d_shell/src/CMakeLists.txt | 24 - .../test_2d_sliding/CMakeLists.txt | 39 +- ...sition_ensemble_averaged_mean_variance.xml | 1741 + .../FreeBallObserver_Position_runtimes.dat | 3 + .../regression_test_tool.py | 79 + tests/2d_examples/test_2d_sliding/sliding.cpp | 222 + .../test_2d_sliding/src/CMakeLists.txt | 24 - .../test_2d_sliding/src/sliding.cpp | 227 - .../test_2d_square_droplet/src/case.h | 153 - .../test_2d_square_droplet/src/droplet.cpp | 83 +- .../test_2d_square_droplet/src/droplet.h | 121 + .../test_2d_static_confinement/CMakeLists.txt | 55 +- .../Fluidobserver_Pressure_Run_0_result.xml | 9 + .../Fluidobserver_Pressure_Run_4_result.xml | 9 + .../Fluidobserver_Pressure_Run_7_result.xml | 9 + .../Fluidobserver_Pressure_dtwdistance.xml | 4 + .../Fluidobserver_Pressure_runtimes.dat | 3 + ...ody_TotalMechanicalEnergy_Run_0_result.xml | 9 + ...ody_TotalMechanicalEnergy_Run_4_result.xml | 9 + ...ody_TotalMechanicalEnergy_Run_8_result.xml | 9 + ...Body_TotalMechanicalEnergy_dtwdistance.xml | 4 + ...terBody_TotalMechanicalEnergy_runtimes.dat | 3 + .../regression_test_tool.py | 86 + .../src/CMakeLists.txt | 24 - .../{src => }/static_confinement.cpp | 92 +- .../test_2d_taylor_green/CMakeLists.txt | 51 +- .../WaterBody_MaximumSpeed_Run_0_result.xml | 9 + .../WaterBody_MaximumSpeed_Run_3_result.xml | 9 + .../WaterBody_MaximumSpeed_Run_6_result.xml | 9 + .../WaterBody_MaximumSpeed_dtwdistance.xml | 4 + .../WaterBody_MaximumSpeed_runtimes.dat | 3 + ...Energy_ensemble_averaged_mean_variance.xml | 109 + ...terBody_TotalMechanicalEnergy_runtimes.dat | 3 + .../regression_test_tool.py | 86 + .../test_2d_taylor_green/src/CMakeLists.txt | 25 - .../{src => }/taylor_green.cpp | 156 +- .../src/fish_and_bones.h | 6 +- .../src/tethered_dead_fish_in_flow.cpp | 347 +- .../2d_examples/test_2d_throat/src/throat.cpp | 300 +- .../test_2d_two_phase_dambreak/CMakeLists.txt | 55 +- .../Fluidobserver_Pressure_Run_0_result.xml | 9 + .../Fluidobserver_Pressure_Run_11_result.xml | 9 + .../Fluidobserver_Pressure_Run_20_result.xml | 9 + .../Fluidobserver_Pressure_dtwdistance.xml | 4 + .../Fluidobserver_Pressure_runtimes.dat | 3 + ...ody_TotalMechanicalEnergy_Run_0_result.xml | 9 + ...ody_TotalMechanicalEnergy_Run_3_result.xml | 9 + ...ody_TotalMechanicalEnergy_Run_5_result.xml | 9 + ...Body_TotalMechanicalEnergy_dtwdistance.xml | 4 + ...terBody_TotalMechanicalEnergy_runtimes.dat | 3 + .../regression_test_tool.py | 86 + .../src/CMakeLists.txt | 24 - .../test_2d_two_phase_dambreak/src/case.h | 161 - .../src/two_phase_dambreak.cpp | 245 - .../two_phase_dambreak.cpp | 241 + .../two_phase_dambreak.h | 130 + .../test_2d_wetting_effects/src/case.h | 153 - .../test_2d_wetting_effects/src/wetting.cpp | 216 +- .../test_2d_wetting_effects/src/wetting.h | 116 + .../test_3d_arch/{src => }/3d_arch.cpp | 162 +- tests/3d_examples/test_3d_arch/CMakeLists.txt | 73 +- ...CylinderObserver_Position_Run_0_result.xml | 9 + ...CylinderObserver_Position_Run_3_result.xml | 9 + ...CylinderObserver_Position_Run_5_result.xml | 9 + .../CylinderObserver_Position_dtwdistance.xml | 4 + .../CylinderObserver_Position_runtimes.dat | 3 + .../regression_test_tool.py | 79 + .../src/test_3d_bernoulli_beam.cpp | 173 +- .../test_3d_dambreak/CMakeLists.txt | 76 +- .../test_3d_dambreak/{src => }/Dambreak.cpp | 179 +- .../Fluidobserver_Pressure_Run_0_result.xml | 14 + .../Fluidobserver_Pressure_Run_17_result.xml | 14 + .../Fluidobserver_Pressure_Run_8_result.xml | 14 + .../Fluidobserver_Pressure_dtwdistance.xml | 4 + .../Fluidobserver_Pressure_runtimes.dat | 3 + ...Energy_ensemble_averaged_mean_variance.xml | 49 + ...terBody_TotalMechanicalEnergy_runtimes.dat | 3 + .../regression_test_tool.py | 86 + .../test_3d_dambreak/src/CMakeLists.txt | 50 - .../CMakeLists.txt | 25 +- .../excitation-contraction.cpp | 460 +- ...ocardiumObserver_Position_Run_0_result.xml | 13 + ...ocardiumObserver_Position_Run_3_result.xml | 13 + ...ocardiumObserver_Position_Run_5_result.xml | 13 + ...yocardiumObserver_Position_dtwdistance.xml | 4 + .../MyocardiumObserver_Position_runtimes.dat | 3 + .../VoltageObserver_Voltage_Run_0_result.xml | 13 + .../VoltageObserver_Voltage_Run_3_result.xml | 13 + .../VoltageObserver_Voltage_Run_5_result.xml | 13 + .../VoltageObserver_Voltage_dtwdistance.xml | 4 + .../VoltageObserver_Voltage_runtimes.dat | 3 + .../regression_test_tool.py | 87 + .../test_3d_load_image/load_image.cpp | 43 +- .../{case.h => load_image.h} | 25 +- .../CMakeLists.txt | 0 .../src/CMakeLists.txt | 0 .../src/muscle_activation.cpp | 189 + .../src/muscle_contact_soft_body_contact.cpp | 288 - .../CMakeLists.txt | 0 .../src/CMakeLists.txt | 0 .../src/muscle_soft_body_contact.cpp | 192 + .../CMakeLists.txt | 0 .../src/CMakeLists.txt | 0 .../src/muscle_solid_contact.cpp} | 207 +- .../src/muscle_activation.cpp | 236 - .../{net_work.cpp => network.cpp} | 34 +- tests/3d_examples/test_3d_network/sphere.h | 57 - .../test_3d_particle_generation/case.h | 53 - .../particle_generator_single_resolution_3D.h | 51 - .../CMakeLists.txt | 0 .../data/teapot.stl | Bin .../input/teapot.stl | Bin .../particle_relaxation.cpp} | 69 +- .../CMakeLists.txt | 0 .../data/SPHinXsys.stl | Bin .../input/SPHinXsys.stl | Bin ...ticle_relaxation_single_resolution_3D.cpp} | 68 +- .../test_3d_passive_cantilever/CMakeLists.txt | 73 +- .../passive_cantilever.cpp | 179 + ...ntileverObserver_Position_Run_0_result.xml | 9 + ...ntileverObserver_Position_Run_3_result.xml | 9 + ...ntileverObserver_Position_Run_5_result.xml | 9 + ...antileverObserver_Position_dtwdistance.xml | 4 + .../CantileverObserver_Position_runtimes.dat | 3 + .../regression_test_tool.py | 79 + .../src/passive_cantilever.cpp | 230 - .../CMakeLists.txt | 73 +- .../passive_cantilever_neohookean.cpp | 179 + ...ntileverObserver_Position_Run_0_result.xml | 9 + ...ntileverObserver_Position_Run_3_result.xml | 9 + ...ntileverObserver_Position_Run_5_result.xml | 9 + ...antileverObserver_Position_dtwdistance.xml | 4 + .../CantileverObserver_Position_runtimes.dat | 3 + .../regression_test_tool.py | 79 + .../src/CMakeLists.txt | 50 - .../src/passive_cantilever_neohookean.cpp | 231 - .../test_3d_pkj_lv_electrocontraction/case.h | 451 - ...tion.cpp => pkj_lv_electrocontraction.cpp} | 236 +- .../pkj_lv_electrocontraction.h | 311 + .../test_3d_roof/{src => }/3d_roof.cpp | 171 +- tests/3d_examples/test_3d_roof/CMakeLists.txt | 67 +- ...sition_ensemble_averaged_mean_variance.xml | 209 + .../CylinderObserver_Position_runtimes.dat | 3 + .../regression_test_tool.py | 79 + .../test_3d_roof/src/CMakeLists.txt | 51 - .../test_3d_self_contact/3d_self_contact.cpp | 65 +- .../test_3d_self_contact/3d_self_contact.h | 72 +- .../test_3d_taylor_bar/CMakeLists.txt | 85 +- .../MyObserver_Position_Run_0_result.xml | 10 + .../MyObserver_Position_Run_3_result.xml | 10 + .../MyObserver_Position_Run_5_result.xml | 10 + .../MyObserver_Position_dtwdistance.xml | 4 + .../MyObserver_Position_runtimes.dat | 3 + .../MyObserver_Velocity_Run_0_result.xml | 10 + .../MyObserver_Velocity_Run_3_result.xml | 10 + .../MyObserver_Velocity_Run_5_result.xml | 10 + .../MyObserver_Velocity_dtwdistance.xml | 4 + .../MyObserver_Velocity_runtimes.dat | 3 + .../regression_test_tool.py | 88 + .../3d_examples/test_3d_taylor_bar/src/case.h | 136 - .../{src => }/taylor_bar.cpp | 130 +- .../test_3d_taylor_bar/taylor_bar.h | 87 + .../test_3d_thin_plate/CMakeLists.txt | 74 +- .../PlateObserver_Position_Run_0_result.xml | 9 + .../PlateObserver_Position_Run_3_result.xml | 9 + .../PlateObserver_Position_Run_5_result.xml | 9 + .../PlateObserver_Position_dtwdistance.xml | 4 + .../PlateObserver_Position_runtimes.dat | 3 + .../regression_test_tool.py | 79 + .../test_3d_thin_plate/src/CMakeLists.txt | 51 - .../{src => }/test_3d_thin_plate.cpp | 165 +- .../test_3d_twisting_column/CMakeLists.txt | 83 +- .../MyObserver_Position_Run_0_result.xml | 9 + .../MyObserver_Position_Run_3_result.xml | 9 + .../MyObserver_Position_Run_5_result.xml | 9 + .../MyObserver_Position_dtwdistance.xml | 4 + .../MyObserver_Position_runtimes.dat | 3 + .../MyObserver_Velocity_Run_0_result.xml | 9 + .../MyObserver_Velocity_Run_3_result.xml | 9 + .../MyObserver_Velocity_Run_5_result.xml | 9 + .../MyObserver_Velocity_dtwdistance.xml | 4 + .../MyObserver_Velocity_runtimes.dat | 3 + .../regression_test_tool.py | 86 + .../src/CMakeLists.txt | 51 - .../test_3d_twisting_column/src/case.h | 135 - .../{src => }/twisting_column.cpp | 56 +- .../test_3d_twisting_column/twisting_column.h | 87 + .../bernoulli_beam_struct_sim/CMakeLists.txt | 5 +- .../bernoulli_beam_struct_sim.cpp | 8 +- .../CMakeLists.txt | 5 +- ...mass_spring_damper_response_struct_sim.cpp | 4 +- .../shared/common/CMakeLists.txt | 71 +- .../test_scalar_functions}/CMakeLists.txt | 31 +- .../test_scalar_functions.cpp | 23 + .../test_vector_functions}/CMakeLists.txt | 40 +- .../test_vector_functions.cpp} | 2 +- .../shared/test_kernels/CMakeLists.txt | 5 + .../CMakeLists.txt | 32 +- .../test_kernel_cubic_B_spline.cpp | 36 + .../shared/test_vonMisesStrain/CMakeLists.txt | 5 +- tutorials/sphinx/.idea/.gitignore | 3 + .../inspectionProfiles/profiles_settings.xml | 6 + tutorials/sphinx/.idea/misc.xml | 4 + tutorials/sphinx/.idea/modules.xml | 8 + tutorials/sphinx/HowToCiteSPHinXsys.rst | 11 + tutorials/sphinx/SPHinXsysArch.rst | 58 + tutorials/sphinx/conf.py | 175 + tutorials/sphinx/contribution.rst | 58 + .../examples/example10_2D_thinPlate.rst | 383 + .../sphinx/examples/example11_3D_arch.rst | 344 + .../example12_2D_flowaroundcylinder.rst | 428 + .../sphinx/examples/example1_2D_dambreak.rst | 784 + .../sphinx/examples/example2_elasticGate.rst | 293 + ...3D_multiResolutionParticleDistribution.rst | 208 + ...2D_multiResolutionParticleDistribution.rst | 232 + .../examples/example5_2D_tayloygreen.rst | 391 + .../examples/example6_2D_heat_transfer.rst | 411 + .../sphinx/examples/example7_2D_diffusion.rst | 294 + .../examples/example8_2D_hydrostatic_fsi.rst | 534 + .../example9_2D_staticConfinement.rst | 400 + tutorials/sphinx/figures/2D_thin_plate.png | Bin 0 -> 37033 bytes .../sphinx/figures/2d_diffusion_final.png | Bin 0 -> 369140 bytes .../sphinx/figures/2d_diffusion_initial.png | Bin 0 -> 343227 bytes tutorials/sphinx/figures/2d_hydro_fsi.png | Bin 0 -> 9951 bytes tutorials/sphinx/figures/2d_hydro_result.png | Bin 0 -> 9950 bytes tutorials/sphinx/figures/2d_mrpd.png | Bin 0 -> 188990 bytes tutorials/sphinx/figures/2d_mrpd_airfoil.png | Bin 0 -> 1624 bytes tutorials/sphinx/figures/2d_mrpd_cleaned.png | Bin 0 -> 10969 bytes tutorials/sphinx/figures/2d_mrpd_levelset.png | Bin 0 -> 6110 bytes .../sphinx/figures/2d_mrpd_uncleaned.png | Bin 0 -> 8829 bytes tutorials/sphinx/figures/3D_arch.png | Bin 0 -> 226752 bytes tutorials/sphinx/figures/3d_mrpd_01.png | Bin 0 -> 655874 bytes tutorials/sphinx/figures/3d_mrpd_02.png | Bin 0 -> 419545 bytes tutorials/sphinx/figures/SPHBody.png | Bin 0 -> 275880 bytes tutorials/sphinx/figures/cmake-sphinxsys.png | Bin 0 -> 98956 bytes tutorials/sphinx/figures/configuration.png | Bin 0 -> 756120 bytes tutorials/sphinx/figures/dambreak.png | Bin 0 -> 180043 bytes tutorials/sphinx/figures/displacement.eps | Bin 0 -> 124170 bytes tutorials/sphinx/figures/displacement.png | Bin 0 -> 101934 bytes tutorials/sphinx/figures/elastic_gate.png | Bin 0 -> 213622 bytes .../sphinx/figures/flow_around_cylinder.png | Bin 0 -> 1011192 bytes tutorials/sphinx/figures/flowchart.png | Bin 0 -> 98428 bytes tutorials/sphinx/figures/force.png | Bin 0 -> 231490 bytes tutorials/sphinx/figures/fsi.eps | 35262 ++++++++++++++++ tutorials/sphinx/figures/fsi.png | Bin 0 -> 3391147 bytes .../sphinx/figures/initial_configuration.png | Bin 0 -> 606102 bytes tutorials/sphinx/figures/initialization.png | Bin 0 -> 42870 bytes tutorials/sphinx/figures/logo-32x32.ico | Bin 0 -> 1603 bytes tutorials/sphinx/figures/logo.EPS | 1157 + tutorials/sphinx/figures/logo.png | Bin 0 -> 74971 bytes tutorials/sphinx/figures/simbody.png | Bin 0 -> 23997 bytes tutorials/sphinx/figures/sph.EPS | 2308 + tutorials/sphinx/figures/sph.png | Bin 0 -> 42830 bytes .../sphinx/figures/sphinxsys-chartflow.png | Bin 0 -> 39433 bytes .../sphinx/figures/sphinxsys-simbody.png | Bin 0 -> 93688 bytes .../sphinx/figures/static_confinement.png | Bin 0 -> 12679 bytes .../figures/static_confinement_energy.png | Bin 0 -> 5421 bytes .../figures/static_confinement_geometry.png | Bin 0 -> 101073 bytes tutorials/sphinx/figures/taylor_green.png | Bin 0 -> 2978162 bytes tutorials/sphinx/installation.rst | 235 + tutorials/sphinx/introduction.rst | 152 + tutorials/sphinx/make.bat | 35 + tutorials/sphinx/publication.rst | 53 + tutorials/sphinx/sphinx_index.rst | 173 + tutorials/sphinx/theory.rst | 1206 + 613 files changed, 77092 insertions(+), 19210 deletions(-) rename SPHINXsys/src/{shared => for_2D_build}/geometries/all_geometries.h (68%) rename SPHINXsys/src/for_2D_build/geometries/{geometry.cpp => multi_polygon_shape.cpp} (83%) rename SPHINXsys/src/for_2D_build/geometries/{geometry.h => multi_polygon_shape.h} (62%) create mode 100644 SPHINXsys/src/for_3D_build/geometries/all_geometries.h delete mode 100644 SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.cpp delete mode 100644 SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.h delete mode 100644 SPHINXsys/src/for_3D_build/geometries/complex_shape_triangle_mesh.cpp delete mode 100644 SPHINXsys/src/for_3D_build/geometries/complex_shape_triangle_mesh.h delete mode 100644 SPHINXsys/src/for_3D_build/geometries/geometry.h delete mode 100644 SPHINXsys/src/for_3D_build/geometries/image_mesh_shape.cpp create mode 100644 SPHINXsys/src/for_3D_build/geometries/image_shape.cpp rename SPHINXsys/src/for_3D_build/geometries/{image_mesh_shape.h => image_shape.h} (62%) rename SPHINXsys/src/for_3D_build/geometries/{geometry.cpp => triangle_mesh_shape.cpp} (63%) create mode 100644 SPHINXsys/src/for_3D_build/geometries/triangle_mesh_shape.h rename SPHINXsys/src/shared/{regression_testing => adaptations}/CMakeLists.txt (100%) rename SPHINXsys/src/shared/{particles/particle_adaptation.cpp => adaptations/adaptation.cpp} (74%) rename SPHINXsys/src/shared/{particles/particle_adaptation.h => adaptations/adaptation.h} (64%) create mode 100644 SPHINXsys/src/shared/bodies/observer_body.h create mode 100644 SPHINXsys/src/shared/common/ownership.h rename SPHINXsys/src/shared/common/{small_vectors.cpp => vector_functions.cpp} (99%) rename SPHINXsys/src/shared/common/{small_vectors.h => vector_functions.h} (100%) create mode 100644 SPHINXsys/src/shared/geometries/base_geometry.cpp create mode 100644 SPHINXsys/src/shared/geometries/complex_shape.cpp rename SPHINXsys/src/{for_3D_build/geometries/complex_shape_mesh.h => shared/geometries/complex_shape.h} (52%) rename SPHINXsys/src/shared/geometries/{geometry_level_set.cpp => level_set_shape.cpp} (55%) rename SPHINXsys/src/shared/geometries/{geometry_level_set.h => level_set_shape.h} (56%) create mode 100644 SPHINXsys/src/shared/kernels/kernel_cubic_B_spline.cpp create mode 100644 SPHINXsys/src/shared/kernels/kernel_cubic_B_spline.h create mode 100644 SPHINXsys/src/shared/materials/base_material.cpp delete mode 100644 SPHINXsys/src/shared/particle_dynamics/fluid_dynamics/fluid_dynamics_compound.cpp delete mode 100644 SPHINXsys/src/shared/particle_dynamics/fluid_dynamics/fluid_dynamics_compound.h delete mode 100644 SPHINXsys/src/shared/particle_dynamics/fluid_dynamics/fluid_dynamics_compound.hpp create mode 100644 SPHINXsys/src/shared/particles/base_particles.hpp create mode 100644 SPHINXsys/src/shared/particles/observer_particles.h create mode 100644 SPHINXsys/src/shared/regression_test/CMakeLists.txt create mode 100644 SPHINXsys/src/shared/regression_test/dyanmic_time_warping_method.hpp create mode 100644 SPHINXsys/src/shared/regression_test/dynamic_time_warping_method.h create mode 100644 SPHINXsys/src/shared/regression_test/ensemble_averaged_method.h create mode 100644 SPHINXsys/src/shared/regression_test/ensemble_averaged_method.hpp rename SPHINXsys/src/shared/{regression_testing/regression_testing.h => regression_test/regression_test.h} (79%) create mode 100644 SPHINXsys/src/shared/regression_test/regression_test_base.h create mode 100644 SPHINXsys/src/shared/regression_test/regression_test_base.hpp create mode 100644 SPHINXsys/src/shared/regression_test/time_averaged_method.h create mode 100644 SPHINXsys/src/shared/regression_test/time_averaged_method.hpp delete mode 100644 SPHINXsys/src/shared/regression_testing/meanvalue_variance_method.h delete mode 100644 SPHINXsys/src/shared/regression_testing/meanvalue_variance_method.hpp rename tests/2d_examples/{test_2d_flow_around_cylinder/src => test_0d_regression_test}/CMakeLists.txt (62%) create mode 100644 tests/2d_examples/test_0d_regression_test/regression_test.cpp create mode 100644 tests/2d_examples/test_0d_regression_test/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_1d_shock_tube/src/shock_tube.h rename tests/2d_examples/test_2d_collision/{src => }/collision.cpp (63%) create mode 100644 tests/2d_examples/test_2d_collision/regression_test_tool/DampingBallObserver_Position_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_collision/regression_test_tool/DampingBallObserver_Position_Run_3_result.xml create mode 100644 tests/2d_examples/test_2d_collision/regression_test_tool/DampingBallObserver_Position_Run_5_result.xml create mode 100644 tests/2d_examples/test_2d_collision/regression_test_tool/DampingBallObserver_Position_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_collision/regression_test_tool/DampingBallObserver_Position_runtimes.dat create mode 100644 tests/2d_examples/test_2d_collision/regression_test_tool/FreeBallObserver_Position_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_collision/regression_test_tool/FreeBallObserver_Position_Run_4_result.xml create mode 100644 tests/2d_examples/test_2d_collision/regression_test_tool/FreeBallObserver_Position_Run_8_result.xml create mode 100644 tests/2d_examples/test_2d_collision/regression_test_tool/FreeBallObserver_Position_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_collision/regression_test_tool/FreeBallObserver_Position_runtimes.dat create mode 100644 tests/2d_examples/test_2d_collision/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_collision/src/CMakeLists.txt rename tests/2d_examples/test_2d_dambreak/{src => }/Dambreak.cpp (56%) create mode 100644 tests/2d_examples/test_2d_dambreak/regression_test_tool/Fluidobserver_Pressure_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_dambreak/regression_test_tool/Fluidobserver_Pressure_Run_10_result.xml create mode 100644 tests/2d_examples/test_2d_dambreak/regression_test_tool/Fluidobserver_Pressure_Run_19_result.xml create mode 100644 tests/2d_examples/test_2d_dambreak/regression_test_tool/Fluidobserver_Pressure_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_dambreak/regression_test_tool/Fluidobserver_Pressure_runtimes.dat create mode 100644 tests/2d_examples/test_2d_dambreak/regression_test_tool/WaterBody_TotalMechanicalEnergy_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_dambreak/regression_test_tool/WaterBody_TotalMechanicalEnergy_Run_11_result.xml create mode 100644 tests/2d_examples/test_2d_dambreak/regression_test_tool/WaterBody_TotalMechanicalEnergy_Run_5_result.xml create mode 100644 tests/2d_examples/test_2d_dambreak/regression_test_tool/WaterBody_TotalMechanicalEnergy_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_dambreak/regression_test_tool/WaterBody_TotalMechanicalEnergy_runtimes.dat create mode 100644 tests/2d_examples/test_2d_dambreak/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_dambreak/src/CMakeLists.txt rename tests/2d_examples/test_2d_depolarization/{src => }/depolarization.cpp (70%) create mode 100644 tests/2d_examples/test_2d_depolarization/regression_test_tool/VoltageObserver_Voltage_ensemble_averaged_mean_variance.xml create mode 100644 tests/2d_examples/test_2d_depolarization/regression_test_tool/VoltageObserver_Voltage_runtimes.dat create mode 100644 tests/2d_examples/test_2d_depolarization/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_depolarization/src/CMakeLists.txt rename tests/2d_examples/test_2d_diffusion/{src => }/diffusion.cpp (55%) create mode 100644 tests/2d_examples/test_2d_diffusion/regression_test_tool/TemperatureObserver_Phi_ensemble_averaged_mean_variance.xml create mode 100644 tests/2d_examples/test_2d_diffusion/regression_test_tool/TemperatureObserver_Phi_runtimes.dat create mode 100644 tests/2d_examples/test_2d_diffusion/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_diffusion/src/CMakeLists.txt create mode 100644 tests/2d_examples/test_2d_elastic_gate/elastic_gate.cpp create mode 100644 tests/2d_examples/test_2d_elastic_gate/regression_test_tool/Observer_Position_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_elastic_gate/regression_test_tool/Observer_Position_Run_4_result.xml create mode 100644 tests/2d_examples/test_2d_elastic_gate/regression_test_tool/Observer_Position_Run_8_result.xml create mode 100644 tests/2d_examples/test_2d_elastic_gate/regression_test_tool/Observer_Position_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_elastic_gate/regression_test_tool/Observer_Position_runtimes.dat create mode 100644 tests/2d_examples/test_2d_elastic_gate/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_elastic_gate/src/CMakeLists.txt delete mode 100644 tests/2d_examples/test_2d_elastic_gate/src/elastic_gate.cpp create mode 100644 tests/2d_examples/test_2d_eulerian_taylor_green/2d_eulerian_taylor_green.cpp create mode 100644 tests/2d_examples/test_2d_eulerian_taylor_green/regression_test_tool/WaterBody_MaximumSpeed_ensemble_averaged_mean_variance.xml create mode 100644 tests/2d_examples/test_2d_eulerian_taylor_green/regression_test_tool/WaterBody_MaximumSpeed_runtimes.dat create mode 100644 tests/2d_examples/test_2d_eulerian_taylor_green/regression_test_tool/WaterBody_TotalMechanicalEnergy_ensemble_averaged_mean_variance.xml create mode 100644 tests/2d_examples/test_2d_eulerian_taylor_green/regression_test_tool/WaterBody_TotalMechanicalEnergy_runtimes.dat create mode 100644 tests/2d_examples/test_2d_eulerian_taylor_green/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_eulerian_taylor_green/src/2d_eulerian_taylor_green.cpp delete mode 100644 tests/2d_examples/test_2d_eulerian_taylor_green/src/CMakeLists.txt rename tests/2d_examples/test_2d_filling_tank/{src => }/filling_tank.cpp (55%) create mode 100644 tests/2d_examples/test_2d_filling_tank/regression_test_tool/Fluidobserver_Pressure_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_filling_tank/regression_test_tool/Fluidobserver_Pressure_Run_11_result.xml create mode 100644 tests/2d_examples/test_2d_filling_tank/regression_test_tool/Fluidobserver_Pressure_Run_22_result.xml create mode 100644 tests/2d_examples/test_2d_filling_tank/regression_test_tool/Fluidobserver_Pressure_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_filling_tank/regression_test_tool/Fluidobserver_Pressure_runtimes.dat create mode 100644 tests/2d_examples/test_2d_filling_tank/regression_test_tool/WaterBody_TotalMechanicalEnergy_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_filling_tank/regression_test_tool/WaterBody_TotalMechanicalEnergy_Run_13_result.xml create mode 100644 tests/2d_examples/test_2d_filling_tank/regression_test_tool/WaterBody_TotalMechanicalEnergy_Run_6_result.xml create mode 100644 tests/2d_examples/test_2d_filling_tank/regression_test_tool/WaterBody_TotalMechanicalEnergy_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_filling_tank/regression_test_tool/WaterBody_TotalMechanicalEnergy_runtimes.dat create mode 100644 tests/2d_examples/test_2d_filling_tank/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_filling_tank/src/CMakeLists.txt create mode 100644 tests/2d_examples/test_2d_flow_around_cylinder/2d_flow_around_cylinder.cpp create mode 100644 tests/2d_examples/test_2d_flow_around_cylinder/2d_flow_around_cylinder.h rename tests/2d_examples/test_2d_flow_around_cylinder/{src => }/data/project_parameters.dat (100%) create mode 100644 tests/2d_examples/test_2d_flow_around_cylinder/regression_test_tool/Cylinder_TotalViscousForceOnSolid_runtimes.dat create mode 100644 tests/2d_examples/test_2d_flow_around_cylinder/regression_test_tool/Cylinder_TotalViscousForceOnSolid_time_averaged_mean_variance.xml create mode 100644 tests/2d_examples/test_2d_flow_around_cylinder/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_flow_around_cylinder/src/2d_flow_around_cylinder.cpp delete mode 100644 tests/2d_examples/test_2d_flow_around_cylinder/src/2d_flow_around_cylinder.h create mode 100644 tests/2d_examples/test_2d_free_stream_around_cylinder/2d_free_stream_around_cylinder .cpp create mode 100644 tests/2d_examples/test_2d_free_stream_around_cylinder/2d_free_stream_around_cylinder.h rename tests/2d_examples/test_2d_free_stream_around_cylinder/{src => }/data/project_parameters.dat (100%) create mode 100644 tests/2d_examples/test_2d_free_stream_around_cylinder/regression_test_tool/Cylinder_TotalViscousForceOnSolid_runtimes.dat create mode 100644 tests/2d_examples/test_2d_free_stream_around_cylinder/regression_test_tool/Cylinder_TotalViscousForceOnSolid_time_averaged_mean_variance.xml create mode 100644 tests/2d_examples/test_2d_free_stream_around_cylinder/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_free_stream_around_cylinder/src/2d_free_stream_around_cylinder .cpp delete mode 100644 tests/2d_examples/test_2d_free_stream_around_cylinder/src/2d_free_stream_around_cylinder.h delete mode 100644 tests/2d_examples/test_2d_free_stream_around_cylinder/src/CMakeLists.txt create mode 100644 tests/2d_examples/test_2d_fsi2/fsi2.cpp create mode 100644 tests/2d_examples/test_2d_fsi2/fsi2.h create mode 100644 tests/2d_examples/test_2d_fsi2/regression_test_tool/BeamObserver_Position_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_fsi2/regression_test_tool/BeamObserver_Position_Run_10_result.xml create mode 100644 tests/2d_examples/test_2d_fsi2/regression_test_tool/BeamObserver_Position_Run_5_result.xml create mode 100644 tests/2d_examples/test_2d_fsi2/regression_test_tool/BeamObserver_Position_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_fsi2/regression_test_tool/BeamObserver_Position_runtimes.dat create mode 100644 tests/2d_examples/test_2d_fsi2/regression_test_tool/InsertedBody_TotalViscousForceOnSolid_runtimes.dat create mode 100644 tests/2d_examples/test_2d_fsi2/regression_test_tool/InsertedBody_TotalViscousForceOnSolid_time_averaged_mean_variance.xml create mode 100644 tests/2d_examples/test_2d_fsi2/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_fsi2/src/CMakeLists.txt delete mode 100644 tests/2d_examples/test_2d_fsi2/src/fsi2.cpp delete mode 100644 tests/2d_examples/test_2d_fsi2/src/fsi2_case.h create mode 100644 tests/2d_examples/test_2d_heat_transfer/heat_transfer.cpp create mode 100644 tests/2d_examples/test_2d_heat_transfer/regression_test_tool/FluidObserver_Phi_ensemble_averaged_mean_variance.xml create mode 100644 tests/2d_examples/test_2d_heat_transfer/regression_test_tool/FluidObserver_Phi_runtimes.dat create mode 100644 tests/2d_examples/test_2d_heat_transfer/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_heat_transfer/src/CMakeLists.txt delete mode 100644 tests/2d_examples/test_2d_heat_transfer/src/heat_transfer.cpp rename tests/2d_examples/test_2d_hydrostatic_fsi/{src => }/hydrostatic_fsi.cpp (56%) create mode 100644 tests/2d_examples/test_2d_hydrostatic_fsi/regression_test_tool/Observer_Position_ensemble_averaged_mean_variance.xml create mode 100644 tests/2d_examples/test_2d_hydrostatic_fsi/regression_test_tool/Observer_Position_runtimes.dat create mode 100644 tests/2d_examples/test_2d_hydrostatic_fsi/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_hydrostatic_fsi/src/CMakeLists.txt rename tests/2d_examples/test_2d_oscillating_beam/{src => }/oscillating_beam.cpp (53%) create mode 100644 tests/2d_examples/test_2d_oscillating_beam/regression_test_tool/BeamObserver_Position_ensemble_averaged_mean_variance.xml create mode 100644 tests/2d_examples/test_2d_oscillating_beam/regression_test_tool/BeamObserver_Position_runtimes.dat create mode 100644 tests/2d_examples/test_2d_oscillating_beam/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_oscillating_beam/src/CMakeLists.txt rename tests/2d_examples/test_2d_owsc/{src => }/owsc.cpp (76%) create mode 100644 tests/2d_examples/test_2d_owsc/owsc.h create mode 100644 tests/2d_examples/test_2d_owsc/regression_test_tool/Flap_TotalForceOnSolid_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_owsc/regression_test_tool/Flap_TotalForceOnSolid_Run_11_result.xml create mode 100644 tests/2d_examples/test_2d_owsc/regression_test_tool/Flap_TotalForceOnSolid_Run_6_result.xml create mode 100644 tests/2d_examples/test_2d_owsc/regression_test_tool/Flap_TotalForceOnSolid_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_owsc/regression_test_tool/Flap_TotalForceOnSolid_runtimes.dat create mode 100644 tests/2d_examples/test_2d_owsc/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_owsc/src/CMakeLists.txt delete mode 100644 tests/2d_examples/test_2d_owsc/src/case.h create mode 100644 tests/2d_examples/test_2d_plate/2d_plate.cpp create mode 100644 tests/2d_examples/test_2d_plate/regression_test_tool/PlateObserver_Position_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_plate/regression_test_tool/PlateObserver_Position_Run_3_result.xml create mode 100644 tests/2d_examples/test_2d_plate/regression_test_tool/PlateObserver_Position_Run_5_result.xml create mode 100644 tests/2d_examples/test_2d_plate/regression_test_tool/PlateObserver_Position_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_plate/regression_test_tool/PlateObserver_Position_runtimes.dat create mode 100644 tests/2d_examples/test_2d_plate/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_plate/src/2d_plate.cpp delete mode 100644 tests/2d_examples/test_2d_plate/src/CMakeLists.txt create mode 100644 tests/2d_examples/test_2d_self_contact/regression_test_tool/BeamObserver_Position_0.xml create mode 100644 tests/2d_examples/test_2d_self_contact/regression_test_tool/BeamObserver_Position_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_self_contact/regression_test_tool/BeamObserver_Position_Run_1_result.xml create mode 100644 tests/2d_examples/test_2d_self_contact/regression_test_tool/BeamObserver_Position_Run_2_result.xml create mode 100644 tests/2d_examples/test_2d_self_contact/regression_test_tool/BeamObserver_Position_Run_3_result.xml create mode 100644 tests/2d_examples/test_2d_self_contact/regression_test_tool/BeamObserver_Position_Run_4_result.xml create mode 100644 tests/2d_examples/test_2d_self_contact/regression_test_tool/BeamObserver_Position_Run_5_result.xml create mode 100644 tests/2d_examples/test_2d_self_contact/regression_test_tool/BeamObserver_Position_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_self_contact/regression_test_tool/BeamObserver_Position_runtimes.dat create mode 100644 tests/2d_examples/test_2d_self_contact/regression_test_tool/regression_test_tool.py rename tests/2d_examples/test_2d_self_contact/{src => }/self_contact.cpp (71%) delete mode 100644 tests/2d_examples/test_2d_self_contact/src/CMakeLists.txt rename tests/2d_examples/test_2d_shell/{src => }/2d_shell.cpp (50%) create mode 100644 tests/2d_examples/test_2d_shell/regression_test_tool/CylinderObserver_Position_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_shell/regression_test_tool/CylinderObserver_Position_Run_3_result.xml create mode 100644 tests/2d_examples/test_2d_shell/regression_test_tool/CylinderObserver_Position_Run_5_result.xml create mode 100644 tests/2d_examples/test_2d_shell/regression_test_tool/CylinderObserver_Position_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_shell/regression_test_tool/CylinderObserver_Position_runtimes.dat create mode 100644 tests/2d_examples/test_2d_shell/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_shell/src/CMakeLists.txt create mode 100644 tests/2d_examples/test_2d_sliding/regression_test_tool/FreeBallObserver_Position_ensemble_averaged_mean_variance.xml create mode 100644 tests/2d_examples/test_2d_sliding/regression_test_tool/FreeBallObserver_Position_runtimes.dat create mode 100644 tests/2d_examples/test_2d_sliding/regression_test_tool/regression_test_tool.py create mode 100644 tests/2d_examples/test_2d_sliding/sliding.cpp delete mode 100644 tests/2d_examples/test_2d_sliding/src/CMakeLists.txt delete mode 100644 tests/2d_examples/test_2d_sliding/src/sliding.cpp delete mode 100644 tests/2d_examples/test_2d_square_droplet/src/case.h create mode 100644 tests/2d_examples/test_2d_square_droplet/src/droplet.h create mode 100644 tests/2d_examples/test_2d_static_confinement/regression_test_tool/Fluidobserver_Pressure_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_static_confinement/regression_test_tool/Fluidobserver_Pressure_Run_4_result.xml create mode 100644 tests/2d_examples/test_2d_static_confinement/regression_test_tool/Fluidobserver_Pressure_Run_7_result.xml create mode 100644 tests/2d_examples/test_2d_static_confinement/regression_test_tool/Fluidobserver_Pressure_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_static_confinement/regression_test_tool/Fluidobserver_Pressure_runtimes.dat create mode 100644 tests/2d_examples/test_2d_static_confinement/regression_test_tool/WaterBody_TotalMechanicalEnergy_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_static_confinement/regression_test_tool/WaterBody_TotalMechanicalEnergy_Run_4_result.xml create mode 100644 tests/2d_examples/test_2d_static_confinement/regression_test_tool/WaterBody_TotalMechanicalEnergy_Run_8_result.xml create mode 100644 tests/2d_examples/test_2d_static_confinement/regression_test_tool/WaterBody_TotalMechanicalEnergy_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_static_confinement/regression_test_tool/WaterBody_TotalMechanicalEnergy_runtimes.dat create mode 100644 tests/2d_examples/test_2d_static_confinement/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_static_confinement/src/CMakeLists.txt rename tests/2d_examples/test_2d_static_confinement/{src => }/static_confinement.cpp (76%) create mode 100644 tests/2d_examples/test_2d_taylor_green/regression_test_tool/WaterBody_MaximumSpeed_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_taylor_green/regression_test_tool/WaterBody_MaximumSpeed_Run_3_result.xml create mode 100644 tests/2d_examples/test_2d_taylor_green/regression_test_tool/WaterBody_MaximumSpeed_Run_6_result.xml create mode 100644 tests/2d_examples/test_2d_taylor_green/regression_test_tool/WaterBody_MaximumSpeed_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_taylor_green/regression_test_tool/WaterBody_MaximumSpeed_runtimes.dat create mode 100644 tests/2d_examples/test_2d_taylor_green/regression_test_tool/WaterBody_TotalMechanicalEnergy_ensemble_averaged_mean_variance.xml create mode 100644 tests/2d_examples/test_2d_taylor_green/regression_test_tool/WaterBody_TotalMechanicalEnergy_runtimes.dat create mode 100644 tests/2d_examples/test_2d_taylor_green/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_taylor_green/src/CMakeLists.txt rename tests/2d_examples/test_2d_taylor_green/{src => }/taylor_green.cpp (61%) create mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/regression_test_tool/Fluidobserver_Pressure_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/regression_test_tool/Fluidobserver_Pressure_Run_11_result.xml create mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/regression_test_tool/Fluidobserver_Pressure_Run_20_result.xml create mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/regression_test_tool/Fluidobserver_Pressure_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/regression_test_tool/Fluidobserver_Pressure_runtimes.dat create mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/regression_test_tool/WaterBody_TotalMechanicalEnergy_Run_0_result.xml create mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/regression_test_tool/WaterBody_TotalMechanicalEnergy_Run_3_result.xml create mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/regression_test_tool/WaterBody_TotalMechanicalEnergy_Run_5_result.xml create mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/regression_test_tool/WaterBody_TotalMechanicalEnergy_dtwdistance.xml create mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/regression_test_tool/WaterBody_TotalMechanicalEnergy_runtimes.dat create mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/regression_test_tool/regression_test_tool.py delete mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/src/CMakeLists.txt delete mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/src/case.h delete mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/src/two_phase_dambreak.cpp create mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/two_phase_dambreak.cpp create mode 100644 tests/2d_examples/test_2d_two_phase_dambreak/two_phase_dambreak.h delete mode 100644 tests/2d_examples/test_2d_wetting_effects/src/case.h create mode 100644 tests/2d_examples/test_2d_wetting_effects/src/wetting.h rename tests/3d_examples/test_3d_arch/{src => }/3d_arch.cpp (53%) create mode 100644 tests/3d_examples/test_3d_arch/regression_test_tool/CylinderObserver_Position_Run_0_result.xml create mode 100644 tests/3d_examples/test_3d_arch/regression_test_tool/CylinderObserver_Position_Run_3_result.xml create mode 100644 tests/3d_examples/test_3d_arch/regression_test_tool/CylinderObserver_Position_Run_5_result.xml create mode 100644 tests/3d_examples/test_3d_arch/regression_test_tool/CylinderObserver_Position_dtwdistance.xml create mode 100644 tests/3d_examples/test_3d_arch/regression_test_tool/CylinderObserver_Position_runtimes.dat create mode 100644 tests/3d_examples/test_3d_arch/regression_test_tool/regression_test_tool.py rename tests/3d_examples/test_3d_dambreak/{src => }/Dambreak.cpp (53%) create mode 100644 tests/3d_examples/test_3d_dambreak/regression_test_tool/Fluidobserver_Pressure_Run_0_result.xml create mode 100644 tests/3d_examples/test_3d_dambreak/regression_test_tool/Fluidobserver_Pressure_Run_17_result.xml create mode 100644 tests/3d_examples/test_3d_dambreak/regression_test_tool/Fluidobserver_Pressure_Run_8_result.xml create mode 100644 tests/3d_examples/test_3d_dambreak/regression_test_tool/Fluidobserver_Pressure_dtwdistance.xml create mode 100644 tests/3d_examples/test_3d_dambreak/regression_test_tool/Fluidobserver_Pressure_runtimes.dat create mode 100644 tests/3d_examples/test_3d_dambreak/regression_test_tool/WaterBody_TotalMechanicalEnergy_ensemble_averaged_mean_variance.xml create mode 100644 tests/3d_examples/test_3d_dambreak/regression_test_tool/WaterBody_TotalMechanicalEnergy_runtimes.dat create mode 100644 tests/3d_examples/test_3d_dambreak/regression_test_tool/regression_test_tool.py delete mode 100644 tests/3d_examples/test_3d_dambreak/src/CMakeLists.txt create mode 100644 tests/3d_examples/test_3d_heart_electromechanics/regression_test_tool/MyocardiumObserver_Position_Run_0_result.xml create mode 100644 tests/3d_examples/test_3d_heart_electromechanics/regression_test_tool/MyocardiumObserver_Position_Run_3_result.xml create mode 100644 tests/3d_examples/test_3d_heart_electromechanics/regression_test_tool/MyocardiumObserver_Position_Run_5_result.xml create mode 100644 tests/3d_examples/test_3d_heart_electromechanics/regression_test_tool/MyocardiumObserver_Position_dtwdistance.xml create mode 100644 tests/3d_examples/test_3d_heart_electromechanics/regression_test_tool/MyocardiumObserver_Position_runtimes.dat create mode 100644 tests/3d_examples/test_3d_heart_electromechanics/regression_test_tool/VoltageObserver_Voltage_Run_0_result.xml create mode 100644 tests/3d_examples/test_3d_heart_electromechanics/regression_test_tool/VoltageObserver_Voltage_Run_3_result.xml create mode 100644 tests/3d_examples/test_3d_heart_electromechanics/regression_test_tool/VoltageObserver_Voltage_Run_5_result.xml create mode 100644 tests/3d_examples/test_3d_heart_electromechanics/regression_test_tool/VoltageObserver_Voltage_dtwdistance.xml create mode 100644 tests/3d_examples/test_3d_heart_electromechanics/regression_test_tool/VoltageObserver_Voltage_runtimes.dat create mode 100644 tests/3d_examples/test_3d_heart_electromechanics/regression_test_tool/regression_test_tool.py rename tests/3d_examples/test_3d_load_image/{case.h => load_image.h} (62%) rename tests/3d_examples/{test_3d_muscle_compression => test_3d_muscle_activation}/CMakeLists.txt (100%) rename tests/3d_examples/{test_3d_arch => test_3d_muscle_activation}/src/CMakeLists.txt (100%) create mode 100644 tests/3d_examples/test_3d_muscle_activation/src/muscle_activation.cpp delete mode 100644 tests/3d_examples/test_3d_muscle_compression_soft_body_contact/src/muscle_contact_soft_body_contact.cpp rename tests/3d_examples/{test_3d_muscle_compression_soft_body_contact => test_3d_muscle_soft_body_contact}/CMakeLists.txt (100%) rename tests/3d_examples/{test_3d_muscle_compression_soft_body_contact => test_3d_muscle_soft_body_contact}/src/CMakeLists.txt (100%) create mode 100644 tests/3d_examples/test_3d_muscle_soft_body_contact/src/muscle_soft_body_contact.cpp rename tests/3d_examples/{test_3d_myocaridum => test_3d_muscle_solid_contact}/CMakeLists.txt (100%) rename tests/3d_examples/{test_3d_muscle_compression => test_3d_muscle_solid_contact}/src/CMakeLists.txt (100%) rename tests/3d_examples/{test_3d_muscle_compression/src/muscle_contact.cpp => test_3d_muscle_solid_contact/src/muscle_solid_contact.cpp} (50%) delete mode 100644 tests/3d_examples/test_3d_myocaridum/src/muscle_activation.cpp rename tests/3d_examples/test_3d_network/{net_work.cpp => network.cpp} (65%) delete mode 100644 tests/3d_examples/test_3d_network/sphere.h delete mode 100644 tests/3d_examples/test_3d_particle_generation/case.h delete mode 100644 tests/3d_examples/test_3d_particle_generator_single_resolution/particle_generator_single_resolution_3D.h rename tests/3d_examples/{test_3d_particle_generation => test_3d_particle_relaxation}/CMakeLists.txt (100%) rename tests/3d_examples/{test_3d_particle_generation => test_3d_particle_relaxation}/data/teapot.stl (100%) rename tests/3d_examples/{test_3d_particle_generation => test_3d_particle_relaxation}/input/teapot.stl (100%) rename tests/3d_examples/{test_3d_particle_generation/particle_generation.cpp => test_3d_particle_relaxation/particle_relaxation.cpp} (55%) rename tests/3d_examples/{test_3d_particle_generator_single_resolution => test_3d_particle_relaxation_single_resolution}/CMakeLists.txt (100%) rename tests/3d_examples/{test_3d_particle_generator_single_resolution => test_3d_particle_relaxation_single_resolution}/data/SPHinXsys.stl (100%) rename tests/3d_examples/{test_3d_particle_generator_single_resolution => test_3d_particle_relaxation_single_resolution}/input/SPHinXsys.stl (100%) rename tests/3d_examples/{test_3d_particle_generator_single_resolution/particle_generator_single_resolution_3D.cpp => test_3d_particle_relaxation_single_resolution/particle_relaxation_single_resolution_3D.cpp} (55%) create mode 100644 tests/3d_examples/test_3d_passive_cantilever/passive_cantilever.cpp create mode 100644 tests/3d_examples/test_3d_passive_cantilever/regression_test_tool/CantileverObserver_Position_Run_0_result.xml create mode 100644 tests/3d_examples/test_3d_passive_cantilever/regression_test_tool/CantileverObserver_Position_Run_3_result.xml create mode 100644 tests/3d_examples/test_3d_passive_cantilever/regression_test_tool/CantileverObserver_Position_Run_5_result.xml create mode 100644 tests/3d_examples/test_3d_passive_cantilever/regression_test_tool/CantileverObserver_Position_dtwdistance.xml create mode 100644 tests/3d_examples/test_3d_passive_cantilever/regression_test_tool/CantileverObserver_Position_runtimes.dat create mode 100644 tests/3d_examples/test_3d_passive_cantilever/regression_test_tool/regression_test_tool.py delete mode 100644 tests/3d_examples/test_3d_passive_cantilever/src/passive_cantilever.cpp create mode 100644 tests/3d_examples/test_3d_passive_cantilever_neohookean/passive_cantilever_neohookean.cpp create mode 100644 tests/3d_examples/test_3d_passive_cantilever_neohookean/regression_test_tool/CantileverObserver_Position_Run_0_result.xml create mode 100644 tests/3d_examples/test_3d_passive_cantilever_neohookean/regression_test_tool/CantileverObserver_Position_Run_3_result.xml create mode 100644 tests/3d_examples/test_3d_passive_cantilever_neohookean/regression_test_tool/CantileverObserver_Position_Run_5_result.xml create mode 100644 tests/3d_examples/test_3d_passive_cantilever_neohookean/regression_test_tool/CantileverObserver_Position_dtwdistance.xml create mode 100644 tests/3d_examples/test_3d_passive_cantilever_neohookean/regression_test_tool/CantileverObserver_Position_runtimes.dat create mode 100644 tests/3d_examples/test_3d_passive_cantilever_neohookean/regression_test_tool/regression_test_tool.py delete mode 100644 tests/3d_examples/test_3d_passive_cantilever_neohookean/src/CMakeLists.txt delete mode 100644 tests/3d_examples/test_3d_passive_cantilever_neohookean/src/passive_cantilever_neohookean.cpp delete mode 100644 tests/3d_examples/test_3d_pkj_lv_electrocontraction/case.h rename tests/3d_examples/test_3d_pkj_lv_electrocontraction/{pkj-lv-electrocontraction.cpp => pkj_lv_electrocontraction.cpp} (56%) create mode 100644 tests/3d_examples/test_3d_pkj_lv_electrocontraction/pkj_lv_electrocontraction.h rename tests/3d_examples/test_3d_roof/{src => }/3d_roof.cpp (52%) create mode 100644 tests/3d_examples/test_3d_roof/regression_test_tool/CylinderObserver_Position_ensemble_averaged_mean_variance.xml create mode 100644 tests/3d_examples/test_3d_roof/regression_test_tool/CylinderObserver_Position_runtimes.dat create mode 100644 tests/3d_examples/test_3d_roof/regression_test_tool/regression_test_tool.py delete mode 100644 tests/3d_examples/test_3d_roof/src/CMakeLists.txt create mode 100644 tests/3d_examples/test_3d_taylor_bar/regression_test_tool/MyObserver_Position_Run_0_result.xml create mode 100644 tests/3d_examples/test_3d_taylor_bar/regression_test_tool/MyObserver_Position_Run_3_result.xml create mode 100644 tests/3d_examples/test_3d_taylor_bar/regression_test_tool/MyObserver_Position_Run_5_result.xml create mode 100644 tests/3d_examples/test_3d_taylor_bar/regression_test_tool/MyObserver_Position_dtwdistance.xml create mode 100644 tests/3d_examples/test_3d_taylor_bar/regression_test_tool/MyObserver_Position_runtimes.dat create mode 100644 tests/3d_examples/test_3d_taylor_bar/regression_test_tool/MyObserver_Velocity_Run_0_result.xml create mode 100644 tests/3d_examples/test_3d_taylor_bar/regression_test_tool/MyObserver_Velocity_Run_3_result.xml create mode 100644 tests/3d_examples/test_3d_taylor_bar/regression_test_tool/MyObserver_Velocity_Run_5_result.xml create mode 100644 tests/3d_examples/test_3d_taylor_bar/regression_test_tool/MyObserver_Velocity_dtwdistance.xml create mode 100644 tests/3d_examples/test_3d_taylor_bar/regression_test_tool/MyObserver_Velocity_runtimes.dat create mode 100644 tests/3d_examples/test_3d_taylor_bar/regression_test_tool/regression_test_tool.py delete mode 100644 tests/3d_examples/test_3d_taylor_bar/src/case.h rename tests/3d_examples/test_3d_taylor_bar/{src => }/taylor_bar.cpp (52%) create mode 100644 tests/3d_examples/test_3d_taylor_bar/taylor_bar.h create mode 100644 tests/3d_examples/test_3d_thin_plate/regression_test_tool/PlateObserver_Position_Run_0_result.xml create mode 100644 tests/3d_examples/test_3d_thin_plate/regression_test_tool/PlateObserver_Position_Run_3_result.xml create mode 100644 tests/3d_examples/test_3d_thin_plate/regression_test_tool/PlateObserver_Position_Run_5_result.xml create mode 100644 tests/3d_examples/test_3d_thin_plate/regression_test_tool/PlateObserver_Position_dtwdistance.xml create mode 100644 tests/3d_examples/test_3d_thin_plate/regression_test_tool/PlateObserver_Position_runtimes.dat create mode 100644 tests/3d_examples/test_3d_thin_plate/regression_test_tool/regression_test_tool.py delete mode 100644 tests/3d_examples/test_3d_thin_plate/src/CMakeLists.txt rename tests/3d_examples/test_3d_thin_plate/{src => }/test_3d_thin_plate.cpp (53%) create mode 100644 tests/3d_examples/test_3d_twisting_column/regression_test_tool/MyObserver_Position_Run_0_result.xml create mode 100644 tests/3d_examples/test_3d_twisting_column/regression_test_tool/MyObserver_Position_Run_3_result.xml create mode 100644 tests/3d_examples/test_3d_twisting_column/regression_test_tool/MyObserver_Position_Run_5_result.xml create mode 100644 tests/3d_examples/test_3d_twisting_column/regression_test_tool/MyObserver_Position_dtwdistance.xml create mode 100644 tests/3d_examples/test_3d_twisting_column/regression_test_tool/MyObserver_Position_runtimes.dat create mode 100644 tests/3d_examples/test_3d_twisting_column/regression_test_tool/MyObserver_Velocity_Run_0_result.xml create mode 100644 tests/3d_examples/test_3d_twisting_column/regression_test_tool/MyObserver_Velocity_Run_3_result.xml create mode 100644 tests/3d_examples/test_3d_twisting_column/regression_test_tool/MyObserver_Velocity_Run_5_result.xml create mode 100644 tests/3d_examples/test_3d_twisting_column/regression_test_tool/MyObserver_Velocity_dtwdistance.xml create mode 100644 tests/3d_examples/test_3d_twisting_column/regression_test_tool/MyObserver_Velocity_runtimes.dat create mode 100644 tests/3d_examples/test_3d_twisting_column/regression_test_tool/regression_test_tool.py delete mode 100644 tests/3d_examples/test_3d_twisting_column/src/CMakeLists.txt delete mode 100644 tests/3d_examples/test_3d_twisting_column/src/case.h rename tests/3d_examples/test_3d_twisting_column/{src => }/twisting_column.cpp (63%) create mode 100644 tests/3d_examples/test_3d_twisting_column/twisting_column.h rename tests/{3d_examples/test_3d_passive_cantilever/src => unit_tests_src/shared/common/test_scalar_functions}/CMakeLists.txt (61%) create mode 100644 tests/unit_tests_src/shared/common/test_scalar_functions/test_scalar_functions.cpp rename tests/{3d_examples/test_3d_myocaridum/src => unit_tests_src/shared/common/test_vector_functions}/CMakeLists.txt (55%) rename tests/unit_tests_src/shared/common/{test_small_vector.cpp => test_vector_functions/test_vector_functions.cpp} (98%) create mode 100644 tests/unit_tests_src/shared/test_kernels/CMakeLists.txt rename tests/{3d_examples/test_3d_taylor_bar/src => unit_tests_src/shared/test_kernels/test_kernel_cubic_B_spline}/CMakeLists.txt (61%) create mode 100644 tests/unit_tests_src/shared/test_kernels/test_kernel_cubic_B_spline/test_kernel_cubic_B_spline.cpp create mode 100644 tutorials/sphinx/.idea/.gitignore create mode 100644 tutorials/sphinx/.idea/inspectionProfiles/profiles_settings.xml create mode 100644 tutorials/sphinx/.idea/misc.xml create mode 100644 tutorials/sphinx/.idea/modules.xml create mode 100644 tutorials/sphinx/HowToCiteSPHinXsys.rst create mode 100644 tutorials/sphinx/SPHinXsysArch.rst create mode 100644 tutorials/sphinx/conf.py create mode 100644 tutorials/sphinx/contribution.rst create mode 100644 tutorials/sphinx/examples/example10_2D_thinPlate.rst create mode 100644 tutorials/sphinx/examples/example11_3D_arch.rst create mode 100644 tutorials/sphinx/examples/example12_2D_flowaroundcylinder.rst create mode 100644 tutorials/sphinx/examples/example1_2D_dambreak.rst create mode 100644 tutorials/sphinx/examples/example2_elasticGate.rst create mode 100644 tutorials/sphinx/examples/example3_3D_multiResolutionParticleDistribution.rst create mode 100644 tutorials/sphinx/examples/example4_2D_multiResolutionParticleDistribution.rst create mode 100644 tutorials/sphinx/examples/example5_2D_tayloygreen.rst create mode 100644 tutorials/sphinx/examples/example6_2D_heat_transfer.rst create mode 100644 tutorials/sphinx/examples/example7_2D_diffusion.rst create mode 100644 tutorials/sphinx/examples/example8_2D_hydrostatic_fsi.rst create mode 100644 tutorials/sphinx/examples/example9_2D_staticConfinement.rst create mode 100644 tutorials/sphinx/figures/2D_thin_plate.png create mode 100644 tutorials/sphinx/figures/2d_diffusion_final.png create mode 100644 tutorials/sphinx/figures/2d_diffusion_initial.png create mode 100644 tutorials/sphinx/figures/2d_hydro_fsi.png create mode 100644 tutorials/sphinx/figures/2d_hydro_result.png create mode 100644 tutorials/sphinx/figures/2d_mrpd.png create mode 100644 tutorials/sphinx/figures/2d_mrpd_airfoil.png create mode 100644 tutorials/sphinx/figures/2d_mrpd_cleaned.png create mode 100644 tutorials/sphinx/figures/2d_mrpd_levelset.png create mode 100644 tutorials/sphinx/figures/2d_mrpd_uncleaned.png create mode 100644 tutorials/sphinx/figures/3D_arch.png create mode 100644 tutorials/sphinx/figures/3d_mrpd_01.png create mode 100644 tutorials/sphinx/figures/3d_mrpd_02.png create mode 100644 tutorials/sphinx/figures/SPHBody.png create mode 100644 tutorials/sphinx/figures/cmake-sphinxsys.png create mode 100644 tutorials/sphinx/figures/configuration.png create mode 100644 tutorials/sphinx/figures/dambreak.png create mode 100644 tutorials/sphinx/figures/displacement.eps create mode 100644 tutorials/sphinx/figures/displacement.png create mode 100644 tutorials/sphinx/figures/elastic_gate.png create mode 100644 tutorials/sphinx/figures/flow_around_cylinder.png create mode 100644 tutorials/sphinx/figures/flowchart.png create mode 100644 tutorials/sphinx/figures/force.png create mode 100644 tutorials/sphinx/figures/fsi.eps create mode 100644 tutorials/sphinx/figures/fsi.png create mode 100644 tutorials/sphinx/figures/initial_configuration.png create mode 100644 tutorials/sphinx/figures/initialization.png create mode 100644 tutorials/sphinx/figures/logo-32x32.ico create mode 100644 tutorials/sphinx/figures/logo.EPS create mode 100644 tutorials/sphinx/figures/logo.png create mode 100644 tutorials/sphinx/figures/simbody.png create mode 100644 tutorials/sphinx/figures/sph.EPS create mode 100644 tutorials/sphinx/figures/sph.png create mode 100644 tutorials/sphinx/figures/sphinxsys-chartflow.png create mode 100644 tutorials/sphinx/figures/sphinxsys-simbody.png create mode 100644 tutorials/sphinx/figures/static_confinement.png create mode 100644 tutorials/sphinx/figures/static_confinement_energy.png create mode 100644 tutorials/sphinx/figures/static_confinement_geometry.png create mode 100644 tutorials/sphinx/figures/taylor_green.png create mode 100644 tutorials/sphinx/installation.rst create mode 100644 tutorials/sphinx/introduction.rst create mode 100644 tutorials/sphinx/make.bat create mode 100644 tutorials/sphinx/publication.rst create mode 100644 tutorials/sphinx/sphinx_index.rst create mode 100644 tutorials/sphinx/theory.rst diff --git a/SPHINXsys/src/for_2D_build/bodies/solid_body_supplementary.cpp b/SPHINXsys/src/for_2D_build/bodies/solid_body_supplementary.cpp index 5729e7e3e8..9bc2ebf6f1 100644 --- a/SPHINXsys/src/for_2D_build/bodies/solid_body_supplementary.cpp +++ b/SPHINXsys/src/for_2D_build/bodies/solid_body_supplementary.cpp @@ -6,13 +6,11 @@ #include "solid_body.h" #include "solid_particles.h" -namespace SPH +namespace SPH { //=================================================================================================// - void SolidBodyPartForSimbody::tagBodyPart() + void SolidBodyPartForSimbody::setMassProperties() { - BodyPartByParticle::tagBodyPart(); - Real body_part_volume(0); Vecd mass_center = Vecd(0); for (size_t i = 0; i < body_part_particles_.size(); ++i) @@ -40,16 +38,14 @@ namespace SPH Ix += particle_volume * r_x * r_x; Real r_y = (particle_position[0] - mass_center[0]); Iy += particle_volume * r_y * r_y; - Iz += particle_volume - * (particle_position - mass_center).normSqr(); + Iz += particle_volume * (particle_position - mass_center).normSqr(); } Ix /= body_part_volume; Iy /= body_part_volume; Iz /= body_part_volume; - body_part_mass_properties_ - = new SimTK::MassProperties(body_part_volume * solid_body_density_, - Vec3d(0), SimTK::UnitInertia(Ix, Iy, Iz)); + body_part_mass_properties_ = mass_properties_ptr_keeper_.createPtr( + body_part_volume * solid_body_density_, Vec3d(0), SimTK::UnitInertia(Ix, Iy, Iz)); } //=================================================================================================// } diff --git a/SPHINXsys/src/shared/geometries/all_geometries.h b/SPHINXsys/src/for_2D_build/geometries/all_geometries.h similarity index 68% rename from SPHINXsys/src/shared/geometries/all_geometries.h rename to SPHINXsys/src/for_2D_build/geometries/all_geometries.h index 8c2adbb87f..5b63708807 100644 --- a/SPHINXsys/src/shared/geometries/all_geometries.h +++ b/SPHINXsys/src/for_2D_build/geometries/all_geometries.h @@ -6,7 +6,8 @@ This is the header file that user code should include to pick up all geometry classes used in SPHinXsys. **/ -#include "geometry.h" -#include "geometry_level_set.h" +#include "multi_polygon_shape.h" +#include "level_set_shape.h" +#include "complex_shape.h" #endif //ALL_GEOMETRIES_H \ No newline at end of file diff --git a/SPHINXsys/src/for_2D_build/geometries/level_set_supplementary.cpp b/SPHINXsys/src/for_2D_build/geometries/level_set_supplementary.cpp index 55433237e2..7115accf1e 100644 --- a/SPHINXsys/src/for_2D_build/geometries/level_set_supplementary.cpp +++ b/SPHINXsys/src/for_2D_build/geometries/level_set_supplementary.cpp @@ -4,8 +4,8 @@ */ #include "level_set.h" - -#include "particle_adaptation.h" +#include "mesh_with_data_packages.hpp" +#include "adaptation.h" #include "base_kernel.h" #include "base_particles.h" #include "base_body.h" @@ -26,13 +26,13 @@ namespace SPH { } } //=================================================================================================// - void LevelSetDataPackage::initializeBasicData(ComplexShape& complex_shape) + void LevelSetDataPackage::initializeBasicData(Shape& shape) { for (int i = 0; i != PackageSize(); ++i) for (int j = 0; j != PackageSize(); ++j) { Vec2d position = data_lower_bound_ + Vec2d((Real)i * grid_spacing_, (Real)j * grid_spacing_); - phi_[i][j] = complex_shape.findSignedDistance(position); + phi_[i][j] = shape.findSignedDistance(position); near_interface_id_[i][j] = phi_[i][j] < 0.0 ? -2 : 2; } } @@ -148,8 +148,8 @@ namespace SPH { int j = (int)cell_index[1]; Vecd cell_position = CellPositionFromIndex(cell_index); - Real signed_distance = complex_shape_.findSignedDistance(cell_position); - Vecd normal_direction = complex_shape_.findNormalDirection(cell_position); + Real signed_distance = shape_.findSignedDistance(cell_position); + Vecd normal_direction = shape_.findNormalDirection(cell_position); Real measure = getMaxAbsoluteElement(normal_direction * signed_distance); if (measure < grid_spacing_) { mutex_my_pool.lock(); @@ -157,15 +157,15 @@ namespace SPH { mutex_my_pool.unlock(); Vecd pkg_lower_bound = GridPositionFromCellPosition(cell_position); new_data_pkg->initializePackageGeometry(pkg_lower_bound, data_spacing_); - new_data_pkg->initializeBasicData(complex_shape_); + new_data_pkg->initializeBasicData(shape_); core_data_pkgs_.push_back(new_data_pkg); new_data_pkg->pkg_index_ = Vecu(i, j); new_data_pkg->is_core_pkg_ = true; data_pkg_addrs_[i][j] = new_data_pkg; } else { - data_pkg_addrs_[i][j] = complex_shape_.checkContain(cell_position) ? - singular_data_pkgs_addrs[0] : singular_data_pkgs_addrs[1]; + data_pkg_addrs_[i][j] = shape_.checkContain(cell_position) ? + singular_data_pkgs_addrs_[0] : singular_data_pkgs_addrs_[1]; } } //=============================================================================================// @@ -193,7 +193,7 @@ namespace SPH { Vecd cell_position = CellPositionFromIndex(cell_index); Vecd pkg_lower_bound = GridPositionFromCellPosition(cell_position); new_data_pkg->initializePackageGeometry(pkg_lower_bound, data_spacing_); - new_data_pkg->initializeBasicData(complex_shape_); + new_data_pkg->initializeBasicData(shape_); new_data_pkg->pkg_index_ = Vecu(i, j); new_data_pkg->is_inner_pkg_ = true; inner_data_pkgs_.push_back(new_data_pkg); diff --git a/SPHINXsys/src/for_2D_build/geometries/geometry.cpp b/SPHINXsys/src/for_2D_build/geometries/multi_polygon_shape.cpp similarity index 83% rename from SPHINXsys/src/for_2D_build/geometries/geometry.cpp rename to SPHINXsys/src/for_2D_build/geometries/multi_polygon_shape.cpp index e187c6e83a..74704cf6d6 100644 --- a/SPHINXsys/src/for_2D_build/geometries/geometry.cpp +++ b/SPHINXsys/src/for_2D_build/geometries/multi_polygon_shape.cpp @@ -1,9 +1,9 @@ /** - * @file geometry.cpp + * @file multi_polygon_shape.cpp * @author Luhui Han, Chi ZHang and Xiangyu Hu */ -#include "geometry.h" +#include "multi_polygon_shape.h" using namespace boost::geometry; @@ -98,7 +98,7 @@ namespace SPH multi_poly_ = MultiPolygonByBooleanOps(multi_poly_, multi_poly_circle, op); } //=================================================================================================// - void MultiPolygon::addAPolygon(std::vector &points, ShapeBooleanOps op) + void MultiPolygon::addAPolygon(const std::vector &points, ShapeBooleanOps op) { std::vector> pts; for (const Vecd &pnt : points) @@ -128,6 +128,32 @@ namespace SPH multi_poly_ = MultiPolygonByBooleanOps(multi_poly_, multi_poly_polygen, op); } //=================================================================================================// + void MultiPolygon:: + addAPolygonFromFile(std::string file_path_name, ShapeBooleanOps op, Vec2d translation, Real scale_factor) + { + std::fstream dataFile(file_path_name); + Vecd temp_point; + std::vector coordinates; + double temp1 = 0.0, temp2 = 0.0; + if (dataFile.fail()) + { + std::cout << "File can not open.\n" + << std::endl; + ; + } + + while (!dataFile.fail() && !dataFile.eof()) + { + dataFile >> temp1 >> temp2; + temp_point[0] = temp1 * scale_factor + translation[0]; + temp_point[1] = temp2 * scale_factor + translation[1]; + coordinates.push_back(temp_point); + } + dataFile.close(); + + addAPolygon(coordinates, op); + } + //=================================================================================================// bool MultiPolygon::checkContain(const Vec2d &pnt, bool BOUNDARY_INCLUDED /*= true*/) { if (BOUNDARY_INCLUDED) @@ -217,33 +243,33 @@ namespace SPH return BoundingBox(lower_bound, upper_bound); } //=================================================================================================// - bool ComplexShape::checkContain(const Vecd &input_pnt, bool BOUNDARY_INCLUDED) + bool MultiPolygonShape::checkContain(const Vec2d &input_pnt, bool BOUNDARY_INCLUDED) { - return multi_ploygen_.checkContain(input_pnt, BOUNDARY_INCLUDED); + return multi_polygon_.checkContain(input_pnt, BOUNDARY_INCLUDED); } //=================================================================================================// - Vec2d ComplexShape::findClosestPoint(const Vec2d &input_pnt) + Vec2d MultiPolygonShape::findClosestPoint(const Vec2d &input_pnt) { - return multi_ploygen_.findClosestPoint(input_pnt); + return multi_polygon_.findClosestPoint(input_pnt); } //=================================================================================================// - bool ComplexShape::checkNotFar(const Vec2d &input_pnt, Real threshold) + bool MultiPolygonShape::checkNotFar(const Vec2d &input_pnt, Real threshold) { - return multi_ploygen_.checkContain(input_pnt) || checkNearSurface(input_pnt, threshold) ? true : false; + return multi_polygon_.checkContain(input_pnt) || checkNearSurface(input_pnt, threshold) ? true : false; } //=================================================================================================// - bool ComplexShape::checkNearSurface(const Vec2d &input_pnt, Real threshold) + bool MultiPolygonShape::checkNearSurface(const Vec2d &input_pnt, Real threshold) { - return getMaxAbsoluteElement(input_pnt - multi_ploygen_.findClosestPoint(input_pnt)) < threshold ? true : false; + return getMaxAbsoluteElement(input_pnt - multi_polygon_.findClosestPoint(input_pnt)) < threshold ? true : false; } //=================================================================================================// - Real ComplexShape::findSignedDistance(const Vec2d &input_pnt) + Real MultiPolygonShape::findSignedDistance(const Vec2d &input_pnt) { Real distance_to_surface = (findClosestPoint(input_pnt) - input_pnt).norm(); return checkContain(input_pnt) ? -distance_to_surface : distance_to_surface; } //=================================================================================================// - Vec2d ComplexShape::findNormalDirection(const Vec2d &input_pnt) + Vec2d MultiPolygonShape::findNormalDirection(const Vec2d &input_pnt) { bool is_contain = checkContain(input_pnt); Vecd displacement_to_surface = findClosestPoint(input_pnt) - input_pnt; @@ -259,55 +285,9 @@ namespace SPH return is_contain ? direction_to_surface : -1.0 * direction_to_surface; } //=================================================================================================// - BoundingBox ComplexShape::findBounds() - { - return multi_ploygen_.findBounds(); - } - //=================================================================================================// - void ComplexShape::addAMultiPolygon(MultiPolygon &multi_polygon, ShapeBooleanOps op) - { - multi_ploygen_.addAMultiPolygon(multi_polygon, op); - } - //=================================================================================================// - void ComplexShape::addABoostMultiPoly(boost_multi_poly &boost_multi_poly, ShapeBooleanOps op) - { - multi_ploygen_.addABoostMultiPoly(boost_multi_poly, op); - } - //=================================================================================================// - void ComplexShape::addAPolygon(std::vector &points, ShapeBooleanOps op) - { - multi_ploygen_.addAPolygon(points, op); - } - //=================================================================================================// - void ComplexShape:: - addAPolygonFromFile(std::string file_path_name, ShapeBooleanOps op, Vec2d translation, Real scale_factor) - { - std::fstream dataFile(file_path_name); - Vecd temp_point; - std::vector coordinates; - double temp1 = 0.0, temp2 = 0.0; - if (dataFile.fail()) - { - std::cout << "File can not open.\n" - << std::endl; - ; - } - - while (!dataFile.fail() && !dataFile.eof()) - { - dataFile >> temp1 >> temp2; - temp_point[0] = temp1 * scale_factor + translation[0]; - temp_point[1] = temp2 * scale_factor + translation[1]; - coordinates.push_back(temp_point); - } - dataFile.close(); - - multi_ploygen_.addAPolygon(coordinates, op); - } - //=================================================================================================// - void ComplexShape::addACircle(Vec2d center, Real radius, int resolution, ShapeBooleanOps op) + BoundingBox MultiPolygonShape::findBounds() { - multi_ploygen_.addACircle(center, radius, resolution, op); + return multi_polygon_.findBounds(); } //=================================================================================================// } \ No newline at end of file diff --git a/SPHINXsys/src/for_2D_build/geometries/geometry.h b/SPHINXsys/src/for_2D_build/geometries/multi_polygon_shape.h similarity index 62% rename from SPHINXsys/src/for_2D_build/geometries/geometry.h rename to SPHINXsys/src/for_2D_build/geometries/multi_polygon_shape.h index 33880357be..2b00c5bef9 100644 --- a/SPHINXsys/src/for_2D_build/geometries/geometry.h +++ b/SPHINXsys/src/for_2D_build/geometries/multi_polygon_shape.h @@ -1,5 +1,5 @@ /** -* @file geometry.h +* @file multi_polygon_shape.h * @brief Here, we define the 2D geometric algortihms. they are based on the boost library. * @details The idea is to define complex geometry based on shapes, usually * multi-polygon using boost library. we propose only very simple combinaton @@ -10,8 +10,8 @@ * @author Luhui Han, Chi ZHang and Xiangyu Hu */ -#ifndef GEOMETRY_2D_H -#define GEOMETRY_2D_H +#ifndef MULTI_POLYGON_SHAPE_H +#define MULTI_POLYGON_SHAPE_H #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING @@ -49,19 +49,21 @@ namespace SPH * @class MultiPolygon * @brief used to define a closed region */ - class MultiPolygon : public Shape + class MultiPolygon { public: - MultiPolygon() : Shape("MultiPolygon"){}; + MultiPolygon(){}; boost_multi_poly &getBoostMultiPoly() { return multi_poly_; }; + + BoundingBox findBounds(); bool checkContain(const Vec2d &pnt, bool BOUNDARY_INCLUDED = true); Vec2d findClosestPoint(const Vec2d &input_pnt); - virtual BoundingBox findBounds() override; void addAMultiPolygon(MultiPolygon &multi_polygon, ShapeBooleanOps op); void addABoostMultiPoly(boost_multi_poly &boost_multi_poly, ShapeBooleanOps op); - void addAPolygon(std::vector &points, ShapeBooleanOps op); + void addAPolygon(const std::vector &points, ShapeBooleanOps op); void addACircle(Vec2d center, Real radius, int resolution, ShapeBooleanOps op); + void addAPolygonFromFile(std::string file_path_name, ShapeBooleanOps op, Vec2d translation = Vecd(0), Real scale_factor = 1.0); protected: boost_multi_poly multi_poly_; @@ -71,38 +73,29 @@ namespace SPH }; /** - * @class ComplexShape - * @brief gives the final geomtrical definition of the SPHBody + * @class MultiPolygonShape + * @brief A shape whose geometry is defined by a multipolygen. */ - class ComplexShape : public Shape + class MultiPolygonShape : public Shape { - Vec2d findClosestPoint(const Vec2d &input_pnt); + public: /** Default constructor. */ - ComplexShape() : Shape("ComplexShape"), multi_ploygen_(){}; - ComplexShape(std::string complex_shape_name) : Shape(complex_shape_name), multi_ploygen_(){}; - virtual ~ComplexShape(){}; + explicit MultiPolygonShape(const MultiPolygon &multi_polygon, const std::string &shape_name = "MultiPolygonShape") + : Shape(shape_name), multi_polygon_(multi_polygon){}; + virtual ~MultiPolygonShape(){}; + virtual BoundingBox findBounds() override; - void addAMultiPolygon(MultiPolygon &multi_polygon, ShapeBooleanOps op); - void addABoostMultiPoly(boost_multi_poly &boost_multi_poly, ShapeBooleanOps op); - void addAPolygon(std::vector &points, ShapeBooleanOps op); - void addACircle(Vec2d center, Real radius, int resolution, ShapeBooleanOps op); - void addAPolygonFromFile(std::string file_path_name, - ShapeBooleanOps op, - Vec2d translation = Vecd(0), - Real scale_factor = 1.0); - - virtual bool checkContain(const Vec2d &input_pnt, bool BOUNDARY_INCLUDED = true); - virtual bool checkNotFar(const Vec2d &input_pnt, Real threshold); - virtual bool checkNearSurface(const Vec2d &input_pnt, Real threshold); - /** Signed distance is negative for point within the complex shape. */ - virtual Real findSignedDistance(const Vec2d &input_pnt); - /** Normal direction point toward outside of the complex shape. */ - virtual Vec2d findNormalDirection(const Vec2d &input_pnt); + virtual bool checkContain(const Vec2d &input_pnt, bool BOUNDARY_INCLUDED = true) override; + virtual Vec2d findClosestPoint(const Vec2d &input_pnt) override; + virtual bool checkNotFar(const Vec2d &input_pnt, Real threshold) override; + virtual bool checkNearSurface(const Vec2d &input_pnt, Real threshold) override; + virtual Real findSignedDistance(const Vec2d &input_pnt) override; + virtual Vec2d findNormalDirection(const Vec2d &input_pnt) override; protected: - MultiPolygon multi_ploygen_; + MultiPolygon multi_polygon_; }; } -#endif //GEOMETRY_2D_H \ No newline at end of file +#endif //MULTI_POLYGON_SHAPE_H \ No newline at end of file diff --git a/SPHINXsys/src/for_2D_build/particle_generator/particle_generator_lattice_supplementary.cpp b/SPHINXsys/src/for_2D_build/particle_generator/particle_generator_lattice_supplementary.cpp index 40363e3c77..58a6f452c8 100644 --- a/SPHINXsys/src/for_2D_build/particle_generator/particle_generator_lattice_supplementary.cpp +++ b/SPHINXsys/src/for_2D_build/particle_generator/particle_generator_lattice_supplementary.cpp @@ -5,7 +5,7 @@ #include "particle_generator_lattice.h" -#include "geometry.h" +#include "complex_shape.h" #include "base_mesh.h" #include "base_body.h" #include "base_particles.h" @@ -14,13 +14,13 @@ namespace SPH { //=================================================================================================// void ParticleGeneratorLattice::createBaseParticles(BaseParticles* base_particles) { - std::unique_ptr mesh(new BaseMesh(domain_bounds_, lattice_spacing_, 0)); + BaseMesh mesh(domain_bounds_, lattice_spacing_, 0); Real particle_volume = lattice_spacing_ * lattice_spacing_; - Vecu number_of_lattices = mesh->NumberOfCellsFromNumberOfGridPoints(mesh->NumberOfGridPoints()); + Vecu number_of_lattices = mesh.NumberOfCellsFromNumberOfGridPoints(mesh.NumberOfGridPoints()); for (size_t i = 0; i < number_of_lattices[0]; ++i) for (size_t j = 0; j < number_of_lattices[1]; ++j) { - Vecd particle_position = mesh->CellPositionFromIndex(Vecu(i,j)); + Vecd particle_position = mesh.CellPositionFromIndex(Vecu(i,j)); if (body_shape_->checkNotFar(particle_position, lattice_spacing_)) { if (body_shape_->checkContain(particle_position)) diff --git a/SPHINXsys/src/for_3D_build/bodies/solid_body_supplementary.cpp b/SPHINXsys/src/for_3D_build/bodies/solid_body_supplementary.cpp index 75fe6b28b6..390e9843fd 100644 --- a/SPHINXsys/src/for_3D_build/bodies/solid_body_supplementary.cpp +++ b/SPHINXsys/src/for_3D_build/bodies/solid_body_supplementary.cpp @@ -6,13 +6,11 @@ #include "solid_body.h" #include "solid_particles.h" -namespace SPH +namespace SPH { //=================================================================================================// - void SolidBodyPartForSimbody::tagBodyPart() + void SolidBodyPartForSimbody::setMassProperties() { - BodyPartByParticle::tagBodyPart(); - Real body_part_volume(0); initial_mass_center_ = Vec3d(0); for (size_t i = 0; i < body_part_particles_.size(); ++i) @@ -37,23 +35,18 @@ namespace SPH Real particle_volume = solid_particles_->Vol_[index_i]; Vec3d displacement = (particle_position - initial_mass_center_); - intertia_moments[0] += particle_volume - * (displacement[1] * displacement[1] + displacement[2] * displacement[2]); - intertia_moments[1] += particle_volume - * (displacement[0] * displacement[0] + displacement[2] * displacement[2]); - intertia_moments[2] += particle_volume - * (displacement[0] * displacement[0] + displacement[1] * displacement[1]); + intertia_moments[0] += particle_volume * (displacement[1] * displacement[1] + displacement[2] * displacement[2]); + intertia_moments[1] += particle_volume * (displacement[0] * displacement[0] + displacement[2] * displacement[2]); + intertia_moments[2] += particle_volume * (displacement[0] * displacement[0] + displacement[1] * displacement[1]); intertia_products[0] -= particle_volume * displacement[0] * displacement[1]; intertia_products[1] -= particle_volume * displacement[0] * displacement[2]; intertia_products[2] -= particle_volume * displacement[1] * displacement[2]; - } intertia_moments /= body_part_volume; intertia_products /= body_part_volume; - body_part_mass_properties_ - = new SimTK::MassProperties(body_part_volume * solid_body_density_, - Vec3d(0), SimTK::UnitInertia(intertia_moments, intertia_products)); + body_part_mass_properties_ = mass_properties_ptr_keeper_.createPtr( + body_part_volume * solid_body_density_, Vec3d(0), SimTK::UnitInertia(intertia_moments, intertia_products)); } //=================================================================================================// } diff --git a/SPHINXsys/src/for_3D_build/geometries/all_geometries.h b/SPHINXsys/src/for_3D_build/geometries/all_geometries.h new file mode 100644 index 0000000000..adaa7f9e24 --- /dev/null +++ b/SPHINXsys/src/for_3D_build/geometries/all_geometries.h @@ -0,0 +1,15 @@ + +#ifndef ALL_GEOMETRIES_H +#define ALL_GEOMETRIES_H + +/** @file +This is the header file that user code should include to pick up all +geometry classes used in SPHinXsys. **/ + +#include "triangle_mesh_shape.h" +#include "image_shape.h" +#include "level_set_shape.h" +#include "complex_shape.h" + + +#endif //ALL_GEOMETRIES_H \ No newline at end of file diff --git a/SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.cpp b/SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.cpp deleted file mode 100644 index 1d13c7ae10..0000000000 --- a/SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#ifndef __EMSCRIPTEN__ - -#include "complex_shape_image_mesh.h" -#include "image_mesh_shape.h" - -namespace SPH -{ - //=================================================================================================// - bool ComplexShapeImageMesh::checkContain(const Vec3d& input_pnt, bool BOUNDARY_INCLUDED) - { - bool exist = false; - bool inside = false; - - for (auto& each_shape : image_mesh_shapes_) - { - ImageMeshShape* sp = each_shape.first; - ShapeBooleanOps operation_string = each_shape.second; - - switch (operation_string) - { - case ShapeBooleanOps::add: - { - inside = sp->checkContain(input_pnt); - exist = exist || inside; - break; - } - case ShapeBooleanOps::sub: - { - inside = sp->checkContain(input_pnt); - exist = exist && (!inside); - break; - } - default: - { - throw std::runtime_error("FAILURE: the boolean operation is not applicable!"); - break; - } - } - } - return exist; - } - //=================================================================================================// - Vec3d ComplexShapeImageMesh::findClosestPoint(const Vec3d& input_pnt) - { - //a big positive number - Real large_number(Infinity); - Real dist_min = large_number; - Vec3d pnt_closest(0); - Vec3d pnt_found(0); - - for (auto& each_shape : image_mesh_shapes_) - { - ImageMeshShape* sp = each_shape.first; - pnt_found = sp->findClosestPoint(input_pnt); - Real dist = (input_pnt - pnt_found).norm(); - - if(dist <= dist_min) - { - dist_min = dist; - pnt_closest = pnt_found; - } - } - - return pnt_closest; - } - //=================================================================================================// - Real ComplexShapeImageMesh::findSignedDistance(const Vec3d& input_pnt) - { - return image_mesh_shapes_[0].first->findValueAtPoint(input_pnt); - } - //=================================================================================================// - Vec3d ComplexShapeImageMesh::findNormalDirection(const Vec3d& input_pnt) - { - Vecd direction_to_surface = image_mesh_shapes_[0].first->findNormalAtPoint(input_pnt); - bool is_contain = image_mesh_shapes_[0].first->checkContain(input_pnt); - return is_contain ? direction_to_surface : -1.0 * direction_to_surface; - } - //=================================================================================================// - void ComplexShapeImageMesh::addImageMeshShape(ImageMeshShape* image_mesh_shape, ShapeBooleanOps op) - { - std::pair shape_and_op(image_mesh_shape, op); - image_mesh_shapes_.push_back(shape_and_op); - } - //=================================================================================================// - void ComplexShapeImageMesh::addBrick(Vec3d halfsize, int resolution, Vec3d translation, Mat3d rotation, ShapeBooleanOps op) - { - std::cout << __FILE__ << ':' << __LINE__ << std::endl; - throw std::runtime_error("addBrick is not implemented"); - } - //=================================================================================================// - void ComplexShapeImageMesh::addSphere(Real radius, int resolution, Vec3d translation, Mat3d rotation, ShapeBooleanOps op) - { - Vec3d spacings(resolution,resolution,resolution); - Vec3d center(translation); - ImageMeshShape* image_mesh_shape = new ImageMeshShape(radius, spacings, center); - std::pair shape_and_op(image_mesh_shape, op); - image_mesh_shapes_.push_back(shape_and_op); - } - //=================================================================================================// - void ComplexShapeImageMesh::addCylinder(SimTK::UnitVec3 axis, Real radius, Real halflength, int resolution, Vec3d translation, Mat3d rotation, ShapeBooleanOps op) - { - std::cout << __FILE__ << ':' << __LINE__ << std::endl; - throw std::runtime_error("addCylinder is not implemented"); - } - //=================================================================================================// - void ComplexShapeImageMesh::addComplexShapeImageMesh(ComplexShapeImageMesh* complex_shape_image_mesh, ShapeBooleanOps op) - { - switch (op) - { - case ShapeBooleanOps::add: - { - for (auto& shape_and_op : complex_shape_image_mesh->image_mesh_shapes_) - { - image_mesh_shapes_.push_back(shape_and_op); - } - break; - } - case ShapeBooleanOps::sub: - { - for (auto& shape_and_op : complex_shape_image_mesh->image_mesh_shapes_) - { - ImageMeshShape* sp = shape_and_op.first; - ShapeBooleanOps operation_string - = shape_and_op.second == ShapeBooleanOps::add ? ShapeBooleanOps::sub : ShapeBooleanOps::add; - std::pair substract_shape_and_op(sp, operation_string); - - image_mesh_shapes_.push_back(substract_shape_and_op); - } - break; - } - default: - { - throw std::runtime_error("unknown operation shape boolean operator"); - break; - } - } - } - //=================================================================================================// - bool ComplexShapeImageMesh::checkNotFar(const Vec3d& input_pnt, Real threshold) - { - return checkContain(input_pnt) || checkNearSurface(input_pnt , threshold) ? true : false; - } - //=================================================================================================// - bool ComplexShapeImageMesh::checkNearSurface(const Vec3d& input_pnt, Real threshold) - { - return getMaxAbsoluteElement(input_pnt - findClosestPoint(input_pnt)) < threshold ? true : false; - } - //=================================================================================================// - BoundingBox ComplexShapeImageMesh::findBounds() - { - //initial reference values - Vec3d lower_bound = Vec3d(Infinity); - Vec3d upper_bound = Vec3d(-Infinity); - - for (size_t i = 0; i < image_mesh_shapes_.size(); i++) - { - BoundingBox shape_bounds = image_mesh_shapes_[i].first->findBounds(); - for (int j = 0; j != 3; ++j) { - lower_bound[j] = SMIN(lower_bound[j], shape_bounds.first[j]); - upper_bound[j] = SMAX(upper_bound[j], shape_bounds.second[j]); - } - } - return BoundingBox(lower_bound, upper_bound); - } - //=================================================================================================// -} - -#endif // __EMSCRIPTEN__ \ No newline at end of file diff --git a/SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.h b/SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.h deleted file mode 100644 index 903a267ce4..0000000000 --- a/SPHINXsys/src/for_3D_build/geometries/complex_shape_image_mesh.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -------------------------------------------------------------------------* -* SPHinXsys * -* --------------------------------------------------------------------------* -* SPHinXsys (pronunciation: s'finksis) is an acronym from Smoothed Particle * -* Hydrodynamics for industrial compleX systems. It provides C++ APIs for * -* physical accurate simulation and aims to model coupled industrial dynamic * -* systems including fluid, solid, multi-body dynamics and beyond with SPH * -* (smoothed particle hydrodynamics), a meshless computational method using * -* particle discretization. * -* * -* SPHinXsys is partially funded by German Research Foundation * -* (Deutsche Forschungsgemeinschaft) DFG HU1527/6-1, HU1527/10-1 * -* and HU1527/12-1. * -* * -* Portions copyright (c) 2017-2020 Technical University of Munich and * -* the authors' affiliations. * -* * -* Licensed under the Apache License, Version 2.0 (the "License"); you may * -* not use this file except in compliance with the License. You may obtain a * -* copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * -* * -* --------------------------------------------------------------------------*/ -/** -* @file complex_shape_image_mesh.h -* @brief x -* @details x -* x -* @author Yijin Mao -*/ - -#ifndef COMPLEX_SHAPE_IMAGE_MESH_H -#define COMPLEX_SHAPE_IMAGE_MESH_H - -#ifndef __EMSCRIPTEN__ - -#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING - -#include "base_geometry.h" -#include "SimTKcommon.h" -#include "SimTKmath.h" -#include "Simbody.h" -#include "simbody_middle.h" -#include "geometry.h" -#include "complex_shape_mesh.h" -//#include "image_mesh_shape.h" - -#include -#include -#include - -/** Macro for APPLE compilers*/ -#ifdef __APPLE__ -#include -namespace fs = boost::filesystem; -#else -#include -namespace fs = std::experimental::filesystem; -#endif - -namespace SPH -{ - class ImageMeshShape; - - class ComplexShapeImageMesh : public ComplexShapeMesh - { - public: - ComplexShapeImageMesh() : ComplexShapeMesh("ComplexShapeImageMesh") {}; - ComplexShapeImageMesh(std::string complex_shape_name) : ComplexShapeMesh(complex_shape_name) {}; - virtual ~ComplexShapeImageMesh() {}; - virtual BoundingBox findBounds() override; - - void addImageMeshShape(ImageMeshShape* image_mesh_shape, ShapeBooleanOps op); - void addComplexShapeImageMesh(ComplexShapeImageMesh* complex_shape_image_mesh, ShapeBooleanOps op); - virtual void addBrick(Vec3d halfsize, int resolution, Vec3d translation, Mat3d rotation, ShapeBooleanOps op); - virtual void addSphere(Real radius, int resolution, Vec3d translation, Mat3d rotation, ShapeBooleanOps op); - virtual void addCylinder(SimTK::UnitVec3 axis, Real radius, Real halflength, int resolution, Vec3d translation, Mat3d rotation, ShapeBooleanOps op); - - virtual bool checkContain(const Vec3d& input_pnt, bool BOUNDARY_INCLUDED = true); - virtual bool checkNotFar(const Vec3d& input_pnt, Real threshold); - virtual bool checkNearSurface(const Vec3d& input_pnt, Real threshold); - /** Signed distance is negative for point within the complex shape. */ - virtual Real findSignedDistance(const Vec3d& input_pnt); - /** Normal direction point toward outside of the complex shape. */ - virtual Vec3d findNormalDirection(const Vec3d& input_pnt); - virtual Vec3d findClosestPoint(const Vec3d& input_pnt); - protected: - /** shape container */ - std::vector> image_mesh_shapes_; - }; -} - -#endif //COMPLEX_SHAPE_IMAGE_MESH_H - -#endif // __EMSCRIPTEN__ \ No newline at end of file diff --git a/SPHINXsys/src/for_3D_build/geometries/complex_shape_triangle_mesh.cpp b/SPHINXsys/src/for_3D_build/geometries/complex_shape_triangle_mesh.cpp deleted file mode 100644 index 4e752a5fe6..0000000000 --- a/SPHINXsys/src/for_3D_build/geometries/complex_shape_triangle_mesh.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include "complex_shape_triangle_mesh.h" -#include "geometry.h" - -namespace SPH -{ - //=================================================================================================// - bool ComplexShapeTriangleMesh::checkContain(const Vec3d& input_pnt, bool BOUNDARY_INCLUDED) - { - bool exist = false; - bool inside = false; - - for (auto& each_shape : triangle_mesh_shapes_) - { - TriangleMeshShape* sp = each_shape.first; - ShapeBooleanOps operation_string = each_shape.second; - - switch (operation_string) - { - case ShapeBooleanOps::add: - { - inside = sp->checkContain(input_pnt); - exist = exist || inside; - break; - } - case ShapeBooleanOps::sub: - { - inside = sp->checkContain(input_pnt); - exist = exist && (!inside); - break; - } - default: - { - std::cout << "\n FAILURE: the boolean operation is not applicable!" << std::endl; - std::cout << __FILE__ << ':' << __LINE__ << std::endl; - exit(1); - break; - } - } - } - return exist; - } - //=================================================================================================// - Vec3d ComplexShapeTriangleMesh::findClosestPoint(const Vec3d& input_pnt) - { - //a big positive number - Real large_number(Infinity); - Real dist_min = large_number; - Vec3d pnt_closest(0); - Vec3d pnt_found(0); - - for (auto& each_shape : triangle_mesh_shapes_) - { - TriangleMeshShape* sp = each_shape.first; - pnt_found = sp->findClosestPoint(input_pnt); - Real dist = (input_pnt - pnt_found).norm(); - - if(dist <= dist_min) - { - dist_min = dist; - pnt_closest = pnt_found; - } - } - - return pnt_closest; - } - //=================================================================================================// - Real ComplexShapeTriangleMesh::findSignedDistance(const Vec3d& input_pnt) - { - Real distance_to_surface = (input_pnt - findClosestPoint(input_pnt)).norm(); - return checkContain(input_pnt) ? -distance_to_surface : distance_to_surface; - } - //=================================================================================================// - Vec3d ComplexShapeTriangleMesh::findNormalDirection(const Vec3d& input_pnt) - { - bool is_contain = checkContain(input_pnt); - Vecd displacement_to_surface = findClosestPoint(input_pnt) - input_pnt; - while (displacement_to_surface.norm() < Eps) { - Vecd jittered = input_pnt; //jittering - for (int l = 0; l != input_pnt.size(); ++l) - jittered[l] = input_pnt[l] + (((Real)rand() / (RAND_MAX)) - 0.5) * 100.0 * Eps; - if (checkContain(jittered) == is_contain) - displacement_to_surface = findClosestPoint(jittered) - jittered; - } - Vecd direction_to_surface = displacement_to_surface.normalize(); - return is_contain ? direction_to_surface : -1.0 * direction_to_surface; - } - //=================================================================================================// - void ComplexShapeTriangleMesh::addTriangleMeshShape(TriangleMeshShape* triangle_mesh_shape, ShapeBooleanOps op) - { - std::pair shape_and_op(triangle_mesh_shape, op); - triangle_mesh_shapes_.push_back(shape_and_op); - } - //=================================================================================================// - void ComplexShapeTriangleMesh::addBrick(Vec3d halfsize, int resolution, Vec3d translation, ShapeBooleanOps op) - { - TriangleMeshShape* triangle_mesh_shape = new TriangleMeshShape(halfsize, resolution, translation); - std::pair shape_and_op(triangle_mesh_shape, op); - triangle_mesh_shapes_.push_back(shape_and_op); - } - //=================================================================================================// - void ComplexShapeTriangleMesh::addSphere(Real radius, int resolution, Vec3d translation, ShapeBooleanOps op) - { - TriangleMeshShape* triangle_mesh_shape = new TriangleMeshShape(radius, resolution, translation); - std::pair shape_and_op(triangle_mesh_shape, op); - triangle_mesh_shapes_.push_back(shape_and_op); - } - //=================================================================================================// - void ComplexShapeTriangleMesh::addCylinder(SimTK::UnitVec3 axis, Real radius, Real halflength, int resolution, Vec3d translation, ShapeBooleanOps op) - { - /** Here SimTK::UnitVec3 give the direction of the cylinder, viz. SimTK::UnitVec3(0,0,1) create a cylinder in z-axis.*/ - TriangleMeshShape* triangle_mesh_shape = new TriangleMeshShape(axis, radius, halflength, resolution, translation); - std::pair shape_and_op(triangle_mesh_shape, op); - triangle_mesh_shapes_.push_back(shape_and_op); - } - //=================================================================================================// - void ComplexShapeTriangleMesh::addFormSTLFile(std::string file_path_name, Vec3d translation, Real scale_factor, ShapeBooleanOps op) - { - TriangleMeshShape* triangle_mesh_shape = new TriangleMeshShape(file_path_name, translation, scale_factor); - std::pair shape_and_op(triangle_mesh_shape, op); - triangle_mesh_shapes_.push_back(shape_and_op); - } - //=================================================================================================// - void ComplexShapeTriangleMesh::addComplexShapeTriangleMesh(ComplexShapeTriangleMesh* complex_shape_triangle_mesh, ShapeBooleanOps op) - { - switch (op) - { - case ShapeBooleanOps::add: - { - for (auto& shape_and_op : complex_shape_triangle_mesh->triangle_mesh_shapes_) - { - triangle_mesh_shapes_.push_back(shape_and_op); - } - break; - } - case ShapeBooleanOps::sub: - { - for (auto& shape_and_op : complex_shape_triangle_mesh->triangle_mesh_shapes_) - { - TriangleMeshShape* sp = shape_and_op.first; - ShapeBooleanOps operation_string - = shape_and_op.second == ShapeBooleanOps::add ? ShapeBooleanOps::sub : ShapeBooleanOps::add; - std::pair substract_shape_and_op(sp, operation_string); - - triangle_mesh_shapes_.push_back(substract_shape_and_op); - } - break; - } - default: - { - throw std::runtime_error("unknown operation shape boolean operator"); - break; - } - } - } - //=================================================================================================// - bool ComplexShapeTriangleMesh::checkNotFar(const Vec3d& input_pnt, Real threshold) - { - return checkContain(input_pnt) || checkNearSurface(input_pnt , threshold) ? true : false; - } - //=================================================================================================// - bool ComplexShapeTriangleMesh::checkNearSurface(const Vec3d& input_pnt, Real threshold) - { - return getMaxAbsoluteElement(input_pnt - findClosestPoint(input_pnt)) < threshold ? true : false; - } - //=================================================================================================// - BoundingBox ComplexShapeTriangleMesh::findBounds() - { - //initial reference values - Vec3d lower_bound = Vec3d(Infinity); - Vec3d upper_bound = Vec3d(-Infinity); - - for (size_t i = 0; i < triangle_mesh_shapes_.size(); i++) - { - BoundingBox shape_bounds = triangle_mesh_shapes_[i].first->findBounds(); - for (int j = 0; j != 3; ++j) { - lower_bound[j] = SMIN(lower_bound[j], shape_bounds.first[j]); - upper_bound[j] = SMAX(upper_bound[j], shape_bounds.second[j]); - } - } - return BoundingBox(lower_bound, upper_bound); - } - //=================================================================================================// -} \ No newline at end of file diff --git a/SPHINXsys/src/for_3D_build/geometries/complex_shape_triangle_mesh.h b/SPHINXsys/src/for_3D_build/geometries/complex_shape_triangle_mesh.h deleted file mode 100644 index 5fd31e4d9e..0000000000 --- a/SPHINXsys/src/for_3D_build/geometries/complex_shape_triangle_mesh.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -------------------------------------------------------------------------* -* SPHinXsys * -* --------------------------------------------------------------------------* -* SPHinXsys (pronunciation: s'finksis) is an acronym from Smoothed Particle * -* Hydrodynamics for industrial compleX systems. It provides C++ APIs for * -* physical accurate simulation and aims to model coupled industrial dynamic * -* systems including fluid, solid, multi-body dynamics and beyond with SPH * -* (smoothed particle hydrodynamics), a meshless computational method using * -* particle discretization. * -* * -* SPHinXsys is partially funded by German Research Foundation * -* (Deutsche Forschungsgemeinschaft) DFG HU1527/6-1, HU1527/10-1 * -* and HU1527/12-1. * -* * -* Portions copyright (c) 2017-2020 Technical University of Munich and * -* the authors' affiliations. * -* * -* Licensed under the Apache License, Version 2.0 (the "License"); you may * -* not use this file except in compliance with the License. You may obtain a * -* copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * -* * -* --------------------------------------------------------------------------*/ -/** -* @file complex_shape_triangle_mesh.h -* @brief x -* @details x -* x -* @author Yijin Mao -*/ - -#ifndef COMPLEX_SHAPE_TRIANGLE_MESH_H -#define COMPLEX_SHAPE_TRIANGLE_MESH_H - -#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING - -#include "base_geometry.h" -#include "SimTKcommon.h" -#include "SimTKmath.h" -#include "Simbody.h" -#include "simbody_middle.h" -#include "complex_shape_mesh.h" - -#include -#include -#include - -/** Macro for APPLE compilers*/ -#ifdef __APPLE__ -#include -namespace fs = boost::filesystem; -#else -#include -namespace fs = std::experimental::filesystem; -#endif - -namespace SPH -{ - class TriangleMeshShape; - - class ComplexShapeTriangleMesh : public ComplexShapeMesh - { - public: - ComplexShapeTriangleMesh() : ComplexShapeMesh("ComplexShapeTriangleMesh") {}; - ComplexShapeTriangleMesh(std::string complex_shape_name) : ComplexShapeMesh(complex_shape_name) {}; - virtual ~ComplexShapeTriangleMesh() {}; - virtual BoundingBox findBounds() override; - - void addTriangleMeshShape(TriangleMeshShape* triangle_mesh_shape, ShapeBooleanOps op); - void addComplexShapeTriangleMesh(ComplexShapeTriangleMesh* complex_shape_triangle_mesh, ShapeBooleanOps op); - virtual void addBrick(Vec3d halfsize, int resolution, Vec3d translation, ShapeBooleanOps op); - virtual void addSphere(Real radius, int resolution, Vec3d translation, ShapeBooleanOps op); - virtual void addCylinder(SimTK::UnitVec3 axis, Real radius, Real halflength, int resolution, Vec3d translation, ShapeBooleanOps op); - void addFormSTLFile(std::string file_path_name, Vec3d translation, Real scale_factor, ShapeBooleanOps op); - - virtual bool checkContain(const Vec3d& input_pnt, bool BOUNDARY_INCLUDED = true); - virtual bool checkNotFar(const Vec3d& input_pnt, Real threshold); - virtual bool checkNearSurface(const Vec3d& input_pnt, Real threshold); - /** Signed distance is negative for point within the complex shape. */ - virtual Real findSignedDistance(const Vec3d& input_pnt); - /** Normal direction point toward outside of the complex shape. */ - virtual Vec3d findNormalDirection(const Vec3d& input_pnt); - virtual Vec3d findClosestPoint(const Vec3d& input_pnt); - protected: - /** shape container */ - std::vector> triangle_mesh_shapes_; - }; -} - -#endif //COMPLEX_SHAPE_TRIANGLE_MESH_H diff --git a/SPHINXsys/src/for_3D_build/geometries/geometry.h b/SPHINXsys/src/for_3D_build/geometries/geometry.h deleted file mode 100644 index b72472437b..0000000000 --- a/SPHINXsys/src/for_3D_build/geometries/geometry.h +++ /dev/null @@ -1,142 +0,0 @@ -/* -------------------------------------------------------------------------* -* SPHinXsys * -* --------------------------------------------------------------------------* -* SPHinXsys (pronunciation: s'finksis) is an acronym from Smoothed Particle * -* Hydrodynamics for industrial compleX systems. It provides C++ APIs for * -* physical accurate simulation and aims to model coupled industrial dynamic * -* systems including fluid, solid, multi-body dynamics and beyond with SPH * -* (smoothed particle hydrodynamics), a meshless computational method using * -* particle discretization. * -* * -* SPHinXsys is partially funded by German Research Foundation * -* (Deutsche Forschungsgemeinschaft) DFG HU1527/6-1, HU1527/10-1 * -* and HU1527/12-1. * -* * -* Portions copyright (c) 2017-2020 Technical University of Munich and * -* the authors' affiliations. * -* * -* Licensed under the Apache License, Version 2.0 (the "License"); you may * -* not use this file except in compliance with the License. You may obtain a * -* copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * -* * -* --------------------------------------------------------------------------*/ -/** -* @file geometry.h -* @brief Here, we define the 3D geometric algortihms. they are based on the polymesh. -* @details The idea is to define complex geometry by passing stl, obj or other -* polymesh files. -* @author Chi ZHang and Xiangyu Hu -*/ - -#ifndef GEOMETRY_3D_H -#define GEOMETRY_3D_H - -#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING - -#include "base_geometry.h" -#include "SimTKcommon.h" -#include "SimTKmath.h" -#include "Simbody.h" -#include "simbody_middle.h" -#include "complex_shape_mesh.h" -#include "complex_shape_triangle_mesh.h" -#include "complex_shape_image_mesh.h" -#include "image_mesh_shape.h" - -#include -#include -#include - -/** Macro for APPLE compilers*/ -#ifdef __APPLE__ -#include -namespace fs = boost::filesystem; -#else -#include -namespace fs = std::experimental::filesystem; -#endif - -namespace SPH -{ - - /** - * @brief preclaimed classes. - */ - class Kernel; - - class TriangleMeshShape : public Shape - { - public: - //constructor for load stl file from out side - TriangleMeshShape(std::string file_path_name, Vec3d translation, Real scale_factor); -#ifdef __EMSCRIPTEN__ - //constructor for load stl file from buffer - TriangleMeshShape(const uint8_t* buffer, Vec3d translation, Real scale_factor); -#endif - // constructor for brick geometry - TriangleMeshShape(Vec3d halfsize, int resolution, Vec3d translation); - // constructor for sphere geometry - TriangleMeshShape(Real radius, int resolution, Vec3d translation); - //constructor for cylinder geometry - TriangleMeshShape(SimTK::UnitVec3 axis, Real radius, Real halflength, int resolution, Vec3d translation); - - SimTK::ContactGeometry::TriangleMesh *getTriangleMesh() { return triangle_mesh_; }; - bool checkContain(const Vec3d &pnt, bool BOUNDARY_INCLUDED = true); - Vec3d findClosestPoint(const Vec3d &input_pnt); - virtual BoundingBox findBounds() override; - - protected: - SimTK::ContactGeometry::TriangleMesh *triangle_mesh_; - - //generate triangle mesh from polymesh - SimTK::ContactGeometry::TriangleMesh *generateTriangleMesh(SimTK::PolygonalMesh &ploy_mesh); - }; - - class ComplexShape : public Shape - { - public: - ComplexShape() : Shape("ComplexShape") { complex_shape_mesh_ = nullptr; }; - ComplexShape(std::string complex_shape_name) : Shape(complex_shape_name) { complex_shape_mesh_ = nullptr; }; - ComplexShape(ComplexShapeMesh* complex_shape_mesh) : Shape("ComplexShape") { complex_shape_mesh_ = complex_shape_mesh; }; - virtual ~ComplexShape() {}; - virtual BoundingBox findBounds() override; - - void addTriangleMeshShape(TriangleMeshShape *triangle_mesh_shape, ShapeBooleanOps op) - { - if(complex_shape_mesh_->getName() == "ComplexShapeTriangleMesh") - { - ComplexShapeTriangleMesh *complex_shape_mesh = dynamic_cast(complex_shape_mesh_); - complex_shape_mesh->addTriangleMeshShape(triangle_mesh_shape, op); - } - } - // void addComplexShape(ComplexShape *complex_shape, ShapeBooleanOps op); - void addBrick(Vec3d halfsize, int resolution, Vec3d translation, ShapeBooleanOps op) - { - if(complex_shape_mesh_->getName() == "ComplexShapeTriangleMesh") - { - ComplexShapeTriangleMesh *complex_shape_mesh = dynamic_cast(complex_shape_mesh_); - complex_shape_mesh->addBrick(halfsize, resolution, translation, op); - } - } - //void addSphere(Real radius, int resolution, Vec3d translation, ShapeBooleanOps op); - //void addCylinder(SimTK::UnitVec3 axis, Real radius, Real halflength, int resolution, Vec3d translation, ShapeBooleanOps op); - //void addFormSTLFile(std::string file_path_name, Vec3d translation, Real scale_factor, ShapeBooleanOps op); - - virtual bool checkContain(const Vec3d &input_pnt, bool BOUNDARY_INCLUDED = true); - virtual bool checkNotFar(const Vec3d &input_pnt, Real threshold); - virtual bool checkNearSurface(const Vec3d &input_pnt, Real threshold); - /** Signed distance is negative for point within the complex shape. */ - virtual Real findSignedDistance(const Vec3d &input_pnt); - /** find closest point on the surface */ - virtual Vec3d findClosestPoint(const Vec3d &input_pnt); - /** Normal direction point toward outside of the complex shape. */ - virtual Vec3d findNormalDirection(const Vec3d &input_pnt); - - protected: - /** shape container */ - - ComplexShapeMesh* complex_shape_mesh_; - }; -} - -#endif //GEOMETRY_3D_H diff --git a/SPHINXsys/src/for_3D_build/geometries/image_mesh_shape.cpp b/SPHINXsys/src/for_3D_build/geometries/image_mesh_shape.cpp deleted file mode 100644 index 92cdfbce3f..0000000000 --- a/SPHINXsys/src/for_3D_build/geometries/image_mesh_shape.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef __EMSCRIPTEN__ - -#include "image_mesh_shape.h" - -namespace SPH -{ - //=================================================================================================// - ImageMeshShape::ImageMeshShape(std::string file_path_name) : - translation_(0.0), - rotation_(1.0), - image_(nullptr), - max_distance_(-INFINITY), - min_distance_(INFINITY) - { - if (image_ == nullptr) - image_.reset(new ImageMHD(file_path_name)); - } - //=================================================================================================// - ImageMeshShape::ImageMeshShape(Real radius, Vec3d spacings, Vec3d center) : - translation_(0.0), - rotation_(1.0), - image_(nullptr), - max_distance_(-INFINITY), - min_distance_(INFINITY) - { - double extend = 1.5; - int length = int(std::ceil(2.0*extend*radius)); - Vec3i NxNyNz(length, length, length); - if(image_ == nullptr) - image_.reset(new ImageMHD(radius, NxNyNz,spacings)); - } - //=================================================================================================// - ImageMeshShape::~ImageMeshShape() - { - } - //=================================================================================================// - bool ImageMeshShape::checkContain(const Vec3d& input_pnt, bool BOUNDARY_INCLUDED) - { - Real value = findValueAtPoint(input_pnt); - if (BOUNDARY_INCLUDED == true) - { - if (value > 0.0) return false; - else return true; - } - else - { - if (value >= 0.0) return false; - else return true; - } - } - //=================================================================================================// - Vec3d ImageMeshShape::findClosestPoint(const Vec3d& input_pnt) - { - return image_->findClosestPoint(input_pnt); - } - //=================================================================================================// - BoundingBox ImageMeshShape::findBounds() - { - return image_->findBounds(); - } - //=================================================================================================// - Real ImageMeshShape::findValueAtPoint(const Vec3d& input_pnt) - { - return image_->findValueAtPoint(input_pnt); - } - //=================================================================================================// - Vec3d ImageMeshShape::findNormalAtPoint(const Vec3d & input_pnt) - { - return image_->findNormalAtPoint(input_pnt); - } - //=================================================================================================// - -} - -#endif // __EMSCRIPTEN__ \ No newline at end of file diff --git a/SPHINXsys/src/for_3D_build/geometries/image_shape.cpp b/SPHINXsys/src/for_3D_build/geometries/image_shape.cpp new file mode 100644 index 0000000000..74a36afd2a --- /dev/null +++ b/SPHINXsys/src/for_3D_build/geometries/image_shape.cpp @@ -0,0 +1,72 @@ +#include "image_shape.h" + +namespace SPH +{ + //=================================================================================================// + bool ImageShape::checkContain(const Vec3d &input_pnt, bool BOUNDARY_INCLUDED) + { + Real value = findSignedDistance(input_pnt); + if (BOUNDARY_INCLUDED == true) + { + if (value > 0.0) + return false; + else + return true; + } + else + { + if (value >= 0.0) + return false; + else + return true; + } + } + //=================================================================================================// + Vec3d ImageShape::findClosestPoint(const Vec3d &input_pnt) + { + return image_->findClosestPoint(input_pnt); + } + //=================================================================================================// + BoundingBox ImageShape::findBounds() + { + return image_->findBounds(); + } + //=================================================================================================// + Real ImageShape::findSignedDistance(const Vec3d &input_pnt) + { + return image_->findValueAtPoint(input_pnt); + } + //=================================================================================================// + Vec3d ImageShape::findNormalDirection(const Vec3d &input_pnt) + { + return image_->findNormalAtPoint(input_pnt); + } + //=================================================================================================// + bool ImageShape::checkNotFar(const Vec3d &input_pnt, Real threshold) + { + return checkContain(input_pnt) || checkNearSurface(input_pnt, threshold) ? true : false; + } + //=================================================================================================// + bool ImageShape::checkNearSurface(const Vec3d &input_pnt, Real threshold) + { + return getMaxAbsoluteElement(input_pnt - findClosestPoint(input_pnt)) < threshold ? true : false; + } + //=================================================================================================// + ImageShapeFromFile:: + ImageShapeFromFile(const std::string &file_path_name, const std::string &shape_name) + : ImageShape(shape_name) + { + image_.reset(new ImageMHD(file_path_name)); + } + //=================================================================================================// + ImageShapeSphere:: + ImageShapeSphere(Real radius, Vec3d spacings, Vec3d center, const std::string &shape_name) + : ImageShape(shape_name) + { + double extend = 1.5; + int length = int(std::ceil(2.0 * extend * radius)); + Vec3i NxNyNz(length, length, length); + image_.reset(new ImageMHD(radius, NxNyNz, spacings)); + } + //=================================================================================================// +} \ No newline at end of file diff --git a/SPHINXsys/src/for_3D_build/geometries/image_mesh_shape.h b/SPHINXsys/src/for_3D_build/geometries/image_shape.h similarity index 62% rename from SPHINXsys/src/for_3D_build/geometries/image_mesh_shape.h rename to SPHINXsys/src/for_3D_build/geometries/image_shape.h index 2c19264acf..c459bc822a 100644 --- a/SPHINXsys/src/for_3D_build/geometries/image_mesh_shape.h +++ b/SPHINXsys/src/for_3D_build/geometries/image_shape.h @@ -21,28 +21,22 @@ * * * --------------------------------------------------------------------------*/ /** -* @file image_mesh_shape.h +* @file image_shape.h * @brief x -* @details x -* x +* @details x +* x * @author Yijin Mao */ -#ifndef IMAGE_MESH_SHAPE_H -#define IMAGE_MESH_SHAPE_H +#ifndef IMAGE_SHAPE_3D_H +#define IMAGE_SHAPE_3D_H #ifndef __EMSCRIPTEN__ #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING #include "base_geometry.h" -#include "SimTKcommon.h" -#include "SimTKmath.h" -#include "Simbody.h" -#include "simbody_middle.h" -#include "geometry.h" #include "image_mhd.h" -#include "base_data_type.h" #include #include @@ -59,21 +53,21 @@ namespace fs = std::experimental::filesystem; namespace SPH { -//- imageMesh is input 3d image - class ImageMeshShape + class ImageShape : public Shape { public: - //constructor for load mhd/raw file from out side - ImageMeshShape(std::string file_path_name); - ImageMeshShape(Real radius, Vec3d spacings, Vec3d center); - virtual ~ImageMeshShape(); + explicit ImageShape(const std::string &shape_name) + : Shape(shape_name), translation_(0.0), rotation_(1.0), + max_distance_(-INFINITY), min_distance_(INFINITY){}; - bool checkContain(const Vec3d& input_pnt, bool BOUNDARY_INCLUDED = true); - Vec3d findClosestPoint(const Vec3d& input_pnt); - BoundingBox findBounds(); + virtual bool checkContain(const Vec3d &input_pnt, bool BOUNDARY_INCLUDED = true) override; + virtual Vec3d findClosestPoint(const Vec3d &input_pnt) override; + virtual BoundingBox findBounds() override; - Real findValueAtPoint(const Vec3d& input_pnt); - Vec3d findNormalAtPoint(const Vec3d & input_pnt); + virtual bool checkNotFar(const Vec3d &input_pnt, Real threshold) override; + virtual bool checkNearSurface(const Vec3d &input_pnt, Real threshold) override; + virtual Real findSignedDistance(const Vec3d &input_pnt) override; + virtual Vec3d findNormalDirection(const Vec3d &input_pnt) override; protected: //- distance map has to be float type image @@ -83,10 +77,27 @@ namespace SPH Real max_distance_; Real min_distance_; + }; + + class ImageShapeFromFile : public ImageShape + { + public: + //constructor for load mhd/raw file from out side + explicit ImageShapeFromFile(const std::string &file_path_name, + const std::string &shape_name = "ImageShapeFromFile"); + virtual ~ImageShapeFromFile(){}; + }; + class ImageShapeSphere : public ImageShape + { + public: + //constructor for load mhd/raw file from out side + ImageShapeSphere(Real radius, Vec3d spacings, Vec3d center, + const std::string &shape_name = "ImageShapeSphere"); + virtual ~ImageShapeSphere(){}; }; } -#endif // __EMSCRIPTEN__ +#endif //__EMSCRIPTEN__ -#endif //IMAGE_MESH_SHAPE_H +#endif //IMAGE_SHAPE_3D_H diff --git a/SPHINXsys/src/for_3D_build/geometries/level_set_supplementary.cpp b/SPHINXsys/src/for_3D_build/geometries/level_set_supplementary.cpp index df0cbbbc84..da5081cde3 100644 --- a/SPHINXsys/src/for_3D_build/geometries/level_set_supplementary.cpp +++ b/SPHINXsys/src/for_3D_build/geometries/level_set_supplementary.cpp @@ -4,11 +4,11 @@ */ #include "level_set.h" - +#include "mesh_with_data_packages.hpp" #include "base_kernel.h" #include "base_particles.h" #include "base_body.h" -#include "particle_adaptation.h" +#include "adaptation.h" namespace SPH { //=================================================================================================// @@ -26,7 +26,7 @@ namespace SPH { } } //=================================================================================================// - void LevelSetDataPackage::initializeBasicData(ComplexShape& complex_shape) + void LevelSetDataPackage::initializeBasicData(Shape& shape) { for (int i = 0; i != PackageSize(); ++i) for (int j = 0; j != PackageSize(); ++j) @@ -34,7 +34,7 @@ namespace SPH { { Vec3d position = data_lower_bound_ + Vec3d((Real)i * grid_spacing_, (Real)j * grid_spacing_, (Real)k * grid_spacing_); - phi_[i][j][k] = complex_shape.findSignedDistance(position); + phi_[i][j][k] = shape.findSignedDistance(position); near_interface_id_[i][j][k] = phi_[i][j][k] < 0.0 ? -2 : 2; } } @@ -172,8 +172,8 @@ namespace SPH { int k = (int)cell_index[2]; Vecd cell_position = CellPositionFromIndex(cell_index); - Real signed_distance = complex_shape_.findSignedDistance(cell_position); - Vecd normal_direction = complex_shape_.findNormalDirection(cell_position); + Real signed_distance = shape_.findSignedDistance(cell_position); + Vecd normal_direction = shape_.findNormalDirection(cell_position); Real measure = getMaxAbsoluteElement(normal_direction * signed_distance); if (measure < grid_spacing_) { mutex_my_pool.lock(); @@ -181,15 +181,15 @@ namespace SPH { mutex_my_pool.unlock(); Vecd pkg_lower_bound = GridPositionFromCellPosition(cell_position); new_data_pkg->initializePackageGeometry(pkg_lower_bound, data_spacing_); - new_data_pkg->initializeBasicData(complex_shape_); + new_data_pkg->initializeBasicData(shape_); core_data_pkgs_.push_back(new_data_pkg); new_data_pkg->pkg_index_ = Vecu(i, j, k); new_data_pkg->is_core_pkg_ = true; data_pkg_addrs_[i][j][k] = new_data_pkg; } else { - data_pkg_addrs_[i][j][k] = complex_shape_.checkContain(cell_position) ? - singular_data_pkgs_addrs[0] : singular_data_pkgs_addrs[1]; + data_pkg_addrs_[i][j][k] = shape_.checkContain(cell_position) ? + singular_data_pkgs_addrs_[0] : singular_data_pkgs_addrs_[1]; } } //=================================================================================================// @@ -221,7 +221,7 @@ namespace SPH { Vecd cell_position = CellPositionFromIndex(cell_index); Vecd pkg_lower_bound = GridPositionFromCellPosition(cell_position); new_data_pkg->initializePackageGeometry(pkg_lower_bound, data_spacing_); - new_data_pkg->initializeBasicData(complex_shape_); + new_data_pkg->initializeBasicData(shape_); new_data_pkg->is_inner_pkg_ = true; new_data_pkg->pkg_index_ = Vecu(i, j, k); inner_data_pkgs_.push_back(new_data_pkg); diff --git a/SPHINXsys/src/for_3D_build/geometries/geometry.cpp b/SPHINXsys/src/for_3D_build/geometries/triangle_mesh_shape.cpp similarity index 63% rename from SPHINXsys/src/for_3D_build/geometries/geometry.cpp rename to SPHINXsys/src/for_3D_build/geometries/triangle_mesh_shape.cpp index 53edf2626f..00ada0871b 100644 --- a/SPHINXsys/src/for_3D_build/geometries/geometry.cpp +++ b/SPHINXsys/src/for_3D_build/geometries/triangle_mesh_shape.cpp @@ -1,62 +1,13 @@ -#include "geometry.h" +#include "triangle_mesh_shape.h" namespace SPH { - //=================================================================================================// - TriangleMeshShape::TriangleMeshShape(std::string filepathname, Vec3d translation, Real scale_factor) - : Shape("TriangleMeshShape") - { - if (!fs::exists(filepathname)) - { - std::cout << "\n Error: the input file:" << filepathname << " is not exists" << std::endl; - std::cout << __FILE__ << ':' << __LINE__ << std::endl; - throw; - } - SimTK::PolygonalMesh polymesh; - polymesh.loadStlFile(filepathname); - polymesh.scaleMesh(scale_factor); - triangle_mesh_ = generateTriangleMesh(polymesh.transformMesh(translation)); - } -#ifdef __EMSCRIPTEN__ - //=================================================================================================// - TriangleMeshShape::TriangleMeshShape(const uint8_t* buffer, Vec3d translation, Real scale_factor) - : Shape("TriangleMeshShape") - { - SimTK::PolygonalMesh polymesh; - polymesh.loadStlBuffer(buffer); - polymesh.scaleMesh(scale_factor); - triangle_mesh_ = generateTriangleMesh(polymesh.transformMesh(translation)); - } -#endif - //=================================================================================================// - TriangleMeshShape::TriangleMeshShape(Vec3d halfsize, int resolution, Vec3d translation) - : Shape("TriangleMeshShape") - { - SimTK::PolygonalMesh polymesh = SimTK::PolygonalMesh::createBrickMesh(halfsize, resolution); - triangle_mesh_ = generateTriangleMesh(polymesh.transformMesh(translation)); - } - //=================================================================================================// - TriangleMeshShape::TriangleMeshShape(Real radius, int resolution, Vec3d translation) - : Shape("TriangleMeshShape") - { - SimTK::PolygonalMesh polymesh = SimTK::PolygonalMesh::createSphereMesh(radius, resolution); - triangle_mesh_ = generateTriangleMesh(polymesh.transformMesh(translation)); - } - //=================================================================================================// - TriangleMeshShape:: - TriangleMeshShape(SimTK::UnitVec3 axis, Real radius, Real halflength, int resolution, Vec3d translation) - : Shape("TriangleMeshShape") - { - SimTK::PolygonalMesh polymesh = - SimTK::PolygonalMesh::createCylinderMesh(axis, radius, halflength, resolution); - triangle_mesh_ = generateTriangleMesh(polymesh.transformMesh(translation)); - } //=================================================================================================// SimTK::ContactGeometry::TriangleMesh *TriangleMeshShape:: generateTriangleMesh(SimTK::PolygonalMesh &ploy_mesh) { SimTK::ContactGeometry::TriangleMesh *triangle_mesh; - triangle_mesh = new SimTK::ContactGeometry::TriangleMesh(ploy_mesh); + triangle_mesh = triangle_mesh_ptr_keeper_.createPtr(ploy_mesh); if (!SimTK::ContactGeometry::TriangleMesh::isInstance(*triangle_mesh)) { std::cout << "\n Error the triangle mesh is not valid" << std::endl; @@ -148,43 +99,55 @@ namespace SPH } return BoundingBox(lower_bound, upper_bound); } - - //=================================================================================================// - bool ComplexShape::checkContain(const Vec3d &input_pnt, bool BOUNDARY_INCLUDED) - { - return complex_shape_mesh_->checkContain(input_pnt, BOUNDARY_INCLUDED); - } //=================================================================================================// - Vec3d ComplexShape::findClosestPoint(const Vec3d &input_pnt) + TriangleMeshShapeSTL:: + TriangleMeshShapeSTL(const std::string &filepathname, Vec3d translation, Real scale_factor, + const std::string &shape_name) + : TriangleMeshShape(shape_name) { - //std::cout << "ComplexShape::findSignedDistance(const Vec3d &input_pnt) called"; - return complex_shape_mesh_->findClosestPoint(input_pnt); - } - //=================================================================================================// - Real ComplexShape::findSignedDistance(const Vec3d &input_pnt) - { - return complex_shape_mesh_->findSignedDistance(input_pnt); + if (!fs::exists(filepathname)) + { + std::cout << "\n Error: the input file:" << filepathname << " is not exists" << std::endl; + std::cout << __FILE__ << ':' << __LINE__ << std::endl; + throw; + } + SimTK::PolygonalMesh polymesh; + polymesh.loadStlFile(filepathname); + polymesh.scaleMesh(scale_factor); + triangle_mesh_ = generateTriangleMesh(polymesh.transformMesh(translation)); } //=================================================================================================// - Vec3d ComplexShape::findNormalDirection(const Vec3d &input_pnt) + TriangleMeshShapeBrick:: + TriangleMeshShapeBrick(Vec3d halfsize, int resolution, Vec3d translation, + const std::string &shape_name) + : TriangleMeshShape(shape_name) { - return complex_shape_mesh_->findNormalDirection(input_pnt); + SimTK::PolygonalMesh polymesh = SimTK::PolygonalMesh::createBrickMesh(halfsize, resolution); + triangle_mesh_ = generateTriangleMesh(polymesh.transformMesh(translation)); } //=================================================================================================// + TriangleMeshShapeBrick:: + TriangleMeshShapeBrick(const TriangleMeshShapeBrick::ShapeParameters &shape_parameters, + const std::string &shape_name) + : TriangleMeshShapeBrick(shape_parameters.halfsize_, shape_parameters.resolution_, + shape_parameters.translation_, shape_name) {} //=================================================================================================// - bool ComplexShape::checkNotFar(const Vec3d& input_pnt, Real threshold) + TriangleMeshShapeShere::TriangleMeshShapeShere(Real radius, int resolution, Vec3d translation, + const std::string &shape_name) + : TriangleMeshShape(shape_name) { - return complex_shape_mesh_->checkNotFar(input_pnt, threshold); - } - //=================================================================================================// - bool ComplexShape::checkNearSurface(const Vec3d &input_pnt, Real threshold) - { - return complex_shape_mesh_->checkNearSurface(input_pnt, threshold); + SimTK::PolygonalMesh polymesh = SimTK::PolygonalMesh::createSphereMesh(radius, resolution); + triangle_mesh_ = generateTriangleMesh(polymesh.transformMesh(translation)); } //=================================================================================================// - BoundingBox ComplexShape::findBounds() + TriangleMeshShapeCylinder:: + TriangleMeshShapeCylinder(SimTK::UnitVec3 axis, Real radius, Real halflength, int resolution, + Vec3d translation, const std::string &shape_name) + : TriangleMeshShape(shape_name) { - return complex_shape_mesh_->findBounds(); + SimTK::PolygonalMesh polymesh = + SimTK::PolygonalMesh::createCylinderMesh(axis, radius, halflength, resolution); + triangle_mesh_ = generateTriangleMesh(polymesh.transformMesh(translation)); } //=================================================================================================// } \ No newline at end of file diff --git a/SPHINXsys/src/for_3D_build/geometries/triangle_mesh_shape.h b/SPHINXsys/src/for_3D_build/geometries/triangle_mesh_shape.h new file mode 100644 index 0000000000..8ac492de67 --- /dev/null +++ b/SPHINXsys/src/for_3D_build/geometries/triangle_mesh_shape.h @@ -0,0 +1,122 @@ +/* -------------------------------------------------------------------------* +* SPHinXsys * +* --------------------------------------------------------------------------* +* SPHinXsys (pronunciation: s'finksis) is an acronym from Smoothed Particle * +* Hydrodynamics for industrial compleX systems. It provides C++ APIs for * +* physical accurate simulation and aims to model coupled industrial dynamic * +* systems including fluid, solid, multi-body dynamics and beyond with SPH * +* (smoothed particle hydrodynamics), a meshless computational method using * +* particle discretization. * +* * +* SPHinXsys is partially funded by German Research Foundation * +* (Deutsche Forschungsgemeinschaft) DFG HU1527/6-1, HU1527/10-1 * +* and HU1527/12-1. * +* * +* Portions copyright (c) 2017-2020 Technical University of Munich and * +* the authors' affiliations. * +* * +* Licensed under the Apache License, Version 2.0 (the "License"); you may * +* not use this file except in compliance with the License. You may obtain a * +* copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * +* * +* --------------------------------------------------------------------------*/ +/** +* @file triangle_mesh_shape.h +* @brief Here, we define the 3D geometric algortihms. they are based on the polymesh. +* @details The idea is to define complex geometry by passing stl, obj or other +* polymesh files. +* @author Chi ZHang and Xiangyu Hu +*/ + +#ifndef TRIANGULAR_MESH_SHAPE_H +#define TRIANGULAR_MESH_SHAPE_H + +#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING + +#include "base_geometry.h" +#include "simbody_middle.h" + +#include +#include +#include + +/** Macro for APPLE compilers*/ +#ifdef __APPLE__ +#include +namespace fs = boost::filesystem; +#else +#include +namespace fs = std::experimental::filesystem; +#endif + +namespace SPH +{ + class TriangleMeshShape : public Shape + { + private: + UniquePtrKeeper triangle_mesh_ptr_keeper_; + + public: + explicit TriangleMeshShape(const std::string &shape_name) + : Shape(shape_name), triangle_mesh_(nullptr){}; + + virtual bool checkContain(const Vec3d &pnt, bool BOUNDARY_INCLUDED = true) override; + virtual Vec3d findClosestPoint(const Vec3d &input_pnt) override; + virtual BoundingBox findBounds() override; + + SimTK::ContactGeometry::TriangleMesh *getTriangleMesh() { return triangle_mesh_; }; + + protected: + SimTK::ContactGeometry::TriangleMesh *triangle_mesh_; + + //generate triangle mesh from polymesh + SimTK::ContactGeometry::TriangleMesh *generateTriangleMesh(SimTK::PolygonalMesh &ploy_mesh); + }; + + class TriangleMeshShapeSTL : public TriangleMeshShape + { + public: + //constructor for load STL file from out side + explicit TriangleMeshShapeSTL(const std::string &file_path_name, Vec3d translation, Real scale_factor, + const std::string &shape_name = "TriangleMeshShapeSTL"); + virtual ~TriangleMeshShapeSTL(){}; + }; + + class TriangleMeshShapeBrick : public TriangleMeshShape + { + public: + class ShapeParameters + { + public: + ShapeParameters() : halfsize_(0), resolution_(0), translation_(0) {}; + Vec3d halfsize_; + int resolution_; + Vec3d translation_; + }; + explicit TriangleMeshShapeBrick(Vec3d halfsize, int resolution, Vec3d translation, + const std::string &shape_name = "TriangleMeshShapeBrick"); + explicit TriangleMeshShapeBrick(const TriangleMeshShapeBrick::ShapeParameters &shape_parameters, + const std::string &shape_name = "TriangleMeshShapeBrick"); + virtual ~TriangleMeshShapeBrick(){}; + }; + + class TriangleMeshShapeShere : public TriangleMeshShape + { + public: + //constructor for sphere shape + explicit TriangleMeshShapeShere(Real radius, int resolution, Vec3d translation, + const std::string &shape_name = "TriangleMeshShapeShere"); + virtual ~TriangleMeshShapeShere(){}; + }; + + class TriangleMeshShapeCylinder : public TriangleMeshShape + { + public: + //constructor for cylinder shape + explicit TriangleMeshShapeCylinder(SimTK::UnitVec3 axis, Real radius, Real halflength, int resolution, Vec3d translation, + const std::string &shape_name = "TriangleMeshShapeCylinder"); + virtual ~TriangleMeshShapeCylinder(){}; + }; +} + +#endif //TRIANGULAR_MESH_SHAPE_H diff --git a/SPHINXsys/src/for_3D_build/particle_generator/particle_generator_lattice_supplementary.cpp b/SPHINXsys/src/for_3D_build/particle_generator/particle_generator_lattice_supplementary.cpp index bd1e841930..8bdbc41874 100644 --- a/SPHINXsys/src/for_3D_build/particle_generator/particle_generator_lattice_supplementary.cpp +++ b/SPHINXsys/src/for_3D_build/particle_generator/particle_generator_lattice_supplementary.cpp @@ -2,7 +2,7 @@ #include "particle_generator_lattice.h" -#include "geometry.h" +#include "complex_shape.h" #include "base_mesh.h" #include "base_body.h" #include "base_particles.h" @@ -11,13 +11,13 @@ namespace SPH { //=================================================================================================// void ParticleGeneratorLattice::createBaseParticles(BaseParticles* base_particles) { - std::unique_ptr mesh(new BaseMesh(domain_bounds_, lattice_spacing_, 0)); + BaseMesh mesh(domain_bounds_, lattice_spacing_, 0); Real particle_volume = lattice_spacing_ * lattice_spacing_ * lattice_spacing_; - Vecu number_of_lattices = mesh->NumberOfCellsFromNumberOfGridPoints(mesh->NumberOfGridPoints()); + Vecu number_of_lattices = mesh.NumberOfCellsFromNumberOfGridPoints(mesh.NumberOfGridPoints()); for (size_t i = 0; i < number_of_lattices[0]; ++i) for (size_t j = 0; j < number_of_lattices[1]; ++j) for (size_t k = 0; k < number_of_lattices[2]; ++k) { - Vecd particle_position = mesh->CellPositionFromIndex(Vecu(i, j, k)); + Vecd particle_position = mesh.CellPositionFromIndex(Vecu(i, j, k)); if (body_shape_->checkNotFar(particle_position, lattice_spacing_)) { if (body_shape_->checkContain(particle_position)) diff --git a/SPHINXsys/src/for_3D_build/particle_generator/particle_generator_network.cpp b/SPHINXsys/src/for_3D_build/particle_generator/particle_generator_network.cpp index 3f55eb341a..8b062237ea 100644 --- a/SPHINXsys/src/for_3D_build/particle_generator/particle_generator_network.cpp +++ b/SPHINXsys/src/for_3D_build/particle_generator/particle_generator_network.cpp @@ -9,24 +9,23 @@ #include "base_body.h" #include "base_particles.h" #include "in_output.h" - //=================================================================================================// -namespace SPH +//=================================================================================================// +namespace SPH { //=================================================================================================// ParticleGeneratorNetwork:: ParticleGeneratorNetwork(Vecd starting_pnt, Vecd second_pnt, int iterator, Real grad_factor) : ParticleGenerator(), starting_pnt_(starting_pnt), second_pnt_(second_pnt), - n_it_(iterator), fascicles_(true), segments_in_branch_(10), segment_length_(0), - grad_factor_(grad_factor), body_shape_(nullptr), tree_(nullptr){} + n_it_(iterator), fascicles_(true), segments_in_branch_(10), segment_length_(0), + grad_factor_(grad_factor), body_shape_(nullptr), cell_linked_list_(nullptr), tree_(nullptr) {} //=================================================================================================// - void ParticleGeneratorNetwork::initialize(SPHBody* sph_body) + void ParticleGeneratorNetwork::initialize(SPHBody *sph_body) { sph_body_ = sph_body; - cell_linked_list_ = dynamic_cast(sph_body)->cell_linked_list_; - segment_length_ = sph_body_->particle_adaptation_->ReferenceSpacing(); - body_shape_ = sph_body_->body_shape_; - tree_ = new GenerativeTree(sph_body_); - sph_body_->generative_structure_ = tree_; + cell_linked_list_ = DynamicCast(this, sph_body)->cell_linked_list_; + segment_length_ = sph_body_->sph_adaptation_->ReferenceSpacing(); + body_shape_ = &sph_body_->body_shape_; + tree_ = sph_body_->createGenerativeStructure(sph_body_); Vecd displacement = second_pnt_ - starting_pnt_; Vecd end_direction = displacement / (displacement.norm() + TinyReal); //add particle to the first branch of the tree @@ -38,7 +37,8 @@ namespace SPH { Vecd upgrad(0), downgrad(0); Vecd shift(delta); - for (int i = 0; i != Dimensions; i++) { + for (int i = 0; i != Dimensions; i++) + { Vecd upwind = pt; Vecd downwind = pt; upwind[i] -= shift[i]; @@ -63,7 +63,7 @@ namespace SPH } //=================================================================================================// bool ParticleGeneratorNetwork:: - isCollision(Vecd& new_point, ListData& nearest_neighbor, size_t parent_id) + isCollision(const Vecd &new_point, const ListData &nearest_neighbor, size_t parent_id) { bool collision = false; bool is_family = false; @@ -71,37 +71,40 @@ namespace SPH collision = extraCheck(new_point); size_t edge_location = tree_->BranchLocation(nearest_neighbor.first); - if (edge_location == parent_id) is_family = true; - for (const size_t& brother_branch : tree_->branches_[parent_id]->out_edge_) + if (edge_location == parent_id) + is_family = true; + for (const size_t &brother_branch : tree_->branches_[parent_id]->out_edge_) { - if (edge_location == brother_branch) is_family = true; + if (edge_location == brother_branch) + { + is_family = true; + } } if (!is_family) { Real min_distance = (new_point - nearest_neighbor.second).norm(); - if (min_distance < 5.0 * segment_length_) collision = true; + if (min_distance < 5.0 * segment_length_) + collision = true; } return collision; } //=================================================================================================// bool ParticleGeneratorNetwork:: - createABranchIfValid(SPHBody* sph_body, size_t parent_id, Real angle, - Real repulsivity, size_t number_segments) + createABranchIfValid(size_t parent_id, Real angle, Real repulsivity, size_t number_segments) { bool is_valid = false; - GenerativeTree::Branch* parent_branch = tree_->branches_[parent_id]; - IndexVector& parent_elements = parent_branch->inner_particles_; + GenerativeTree::Branch *parent_branch = tree_->branches_[parent_id]; + IndexVector &parent_elements = parent_branch->inner_particles_; StdLargeVec &tree_points = tree_->pos_n_; - + Vecd init_point = tree_points[parent_elements.back()]; Vecd init_direction = parent_branch->end_direction_; - Vecd surface_norm = body_shape_->findNormalDirection(init_point); surface_norm /= surface_norm.norm() + TinyReal; - Vecd in_plane = - SimTK::cross(init_direction, surface_norm); + Vecd in_plane = -SimTK::cross(init_direction, surface_norm); Real delta = grad_factor_ * segment_length_; Vecd grad = getGradientFromNearestPoints(init_point, delta); @@ -111,11 +114,10 @@ namespace SPH Vecd end_point = init_point; Vecd new_point = createATentativeNewBranchPoint(end_point, end_direction); - ListData nearest_neighbor = cell_linked_list_->findNearestListDataEntry(new_point); - if (!isCollision(new_point, nearest_neighbor, parent_id)) + if (!isCollision(new_point, cell_linked_list_->findNearestListDataEntry(new_point), parent_id)) { is_valid = true; - GenerativeTree::Branch* new_branch = new GenerativeTree::Branch(parent_id, tree_); + GenerativeTree::Branch *new_branch = tree_->createANewBranch(parent_id); tree_->growAParticleOnBranch(new_branch, new_point, end_direction); for (size_t i = 1; i < number_segments; i++) @@ -130,25 +132,23 @@ namespace SPH end_point = new_point; new_point = createATentativeNewBranchPoint(end_point, end_direction); - ListData nearest_neighbor = cell_linked_list_->findNearestListDataEntry(new_point); - if (isCollision(new_point, nearest_neighbor, parent_id)) + if (isCollision(new_point, cell_linked_list_->findNearestListDataEntry(new_point), parent_id)) { new_branch->is_terminated_ = true; std::cout << "Branch Collision Detected, Break! " << std::endl; break; } /** This constraint imposed to avoid too small time step size. */ - if((new_point - end_point).norm() < 0.5 * segment_length_) + if ((new_point - end_point).norm() < 0.5 * segment_length_) { new_branch->is_terminated_ = true; std::cout << "New branch point is too close, Break! " << std::endl; - break; + break; } tree_->growAParticleOnBranch(new_branch, new_point, end_direction); - } - for (const size_t& particle_idx : new_branch->inner_particles_) + for (const size_t &particle_idx : new_branch->inner_particles_) { cell_linked_list_->InsertACellLinkedListDataEntry(particle_idx, tree_points[particle_idx]); } @@ -157,15 +157,12 @@ namespace SPH return is_valid; } //=================================================================================================// - void ParticleGeneratorNetwork::createBaseParticles(BaseParticles* base_particles) + void ParticleGeneratorNetwork::createBaseParticles(BaseParticles *base_particles) { - In_Output* in_output = sph_body_->getSPHSystem().in_output_; - BodyStatesRecordingToVtu write_states(*in_output, { sph_body_ }); - - std::cout << "Now creating Particles on network... " << "\n" << std::endl; + In_Output *in_output = sph_body_->getSPHSystem().in_output_; + BodyStatesRecordingToVtp write_states(*in_output, {sph_body_}); - //the second branch - bool is_valid = createABranchIfValid(sph_body_, 0, 0.0, 0.0, segments_in_branch_); + std::cout << "Now creating Particles on network... " << std::endl; size_t ite = 0; sph_body_->setNewlyUpdated(); @@ -173,8 +170,13 @@ namespace SPH IndexVector branches_to_grow; IndexVector new_branches_to_grow; - if (is_valid) branches_to_grow.push_back(tree_->last_branch_id_); - + + //the second branch + if (createABranchIfValid(0, 0.0, 0.0, segments_in_branch_)) + { + branches_to_grow.push_back(tree_->last_branch_id_); + } + if (fascicles_) { /** Set vertices in family branch. */ @@ -182,50 +184,49 @@ namespace SPH for (size_t i = 0; i != 2; i++) { /** Creating a new branch. */ - Real angle_to_use = fascicle_angles_[i]; + Real angle_to_use = fascicle_angles_[i]; size_t fascicles_segments = int(fascicle_ratio_ * segments_in_branch_); - bool is_valid = createABranchIfValid(sph_body_, 1, angle_to_use, 0.0, fascicles_segments); - if (is_valid) branches_to_grow.push_back(tree_->last_branch_id_); + if (createABranchIfValid(1, angle_to_use, 0.0, fascicles_segments)) + { + branches_to_grow.push_back(tree_->last_branch_id_); + } } ite++; sph_body_->setNewlyUpdated(); write_states.writeToFile(ite); - } - for(size_t i = 0; i != n_it_; i++) - { + for (size_t i = 0; i != n_it_; i++) + { new_branches_to_grow.clear(); random_shuffle(branches_to_grow.begin(), branches_to_grow.end()); - for(size_t j = 0; j != branches_to_grow.size(); j++) - { - size_t grow_id = branches_to_grow[j]; + for (size_t j = 0; j != branches_to_grow.size(); j++) + { + size_t grow_id = branches_to_grow[j]; Real rand_num = ((Real)rand() / (RAND_MAX)) - 0.5; Real angle_to_use = angle_ + rand_num * 0.05; - for(size_t k = 0; k != 2; k++) - { - /** Creating a new branch with fixed number of segments. */ - size_t random_number_segments = segments_in_branch_; - bool is_valid = createABranchIfValid(sph_body_, grow_id, angle_to_use, repulsivity_, - random_number_segments); - - if(is_valid && !tree_->LastBranch()->is_terminated_) - { - new_branches_to_grow.push_back(tree_->last_branch_id_); - } - - angle_to_use *= -1.0; - } - } - branches_to_grow = new_branches_to_grow; + for (size_t k = 0; k != 2; k++) + { + /** Creating a new branch with fixed number of segments. */ + size_t random_number_segments = segments_in_branch_; + if (createABranchIfValid(grow_id, angle_to_use, repulsivity_, random_number_segments) && + !tree_->LastBranch()->is_terminated_) + { + new_branches_to_grow.push_back(tree_->last_branch_id_); + } + + angle_to_use *= -1.0; + } + } + branches_to_grow = new_branches_to_grow; ite++; sph_body_->setNewlyUpdated(); write_states.writeToFile(ite); } - - std::cout << base_particles->total_real_particles_ << " Particles has been successfully created!" << "\n" << std::endl; + + std::cout << base_particles->total_real_particles_ << " Particles has been successfully created!" << std::endl; } //=================================================================================================// } diff --git a/SPHINXsys/src/for_3D_build/particle_generator/particle_generator_network.h b/SPHINXsys/src/for_3D_build/particle_generator/particle_generator_network.h index fa446e517d..fb0fa734c5 100644 --- a/SPHINXsys/src/for_3D_build/particle_generator/particle_generator_network.h +++ b/SPHINXsys/src/for_3D_build/particle_generator/particle_generator_network.h @@ -30,12 +30,11 @@ #ifndef PARTICLE_GENERATOR_NETWORK_H #define PARTICLE_GENERATOR_NETWORK_H - #include "sph_data_containers.h" #include "base_particle_generator.h" #include "generative_structures.h" -namespace SPH +namespace SPH { class BaseLevelSet; class BaseCellLinkedList; @@ -49,31 +48,32 @@ namespace SPH { public: ParticleGeneratorNetwork(Vecd starting_pnt, Vecd second_pnt, int iterator, Real grad_factor); - virtual ~ParticleGeneratorNetwork() {}; + virtual ~ParticleGeneratorNetwork(){}; /** *@brief Parameters initialization. *@param[in] sph_body*(SPHBody) SPHBody to whom it generate particles. */ - virtual void initialize(SPHBody* sph_body) override; + virtual void initialize(SPHBody *sph_body) override; /** *@brief Created base particles based on edges in branch. *@param[in] base_particles(BaseParticles) Pointer to baseparticle link to a SPHBody. */ - virtual void createBaseParticles(BaseParticles* base_particles) override; + virtual void createBaseParticles(BaseParticles *base_particles) override; + protected: - Vecd starting_pnt_; /**< Starting point for net work. */ - Vecd second_pnt_; /**< Second point, approximate the growing direction. */ - size_t n_it_; /**< Number of iterations (generations of branch. */ - bool fascicles_; /**< Create fascicles? */ - size_t segments_in_branch_; /**< approximated number of segments in a branch. */ - Real segment_length_; /**< segment length of the branch. */ - Real angle_ = 0.3; /**< angle with respect to the direction of the previous edge and the new edge. */ - Real repulsivity_ = 0.175; /**< repulsivity parameter. */ - Real grad_factor_; /**< Factor for computing gradient from nearest node. */ - std::vector fascicle_angles_ = {-1.25, 0.75}; /**< angles with respect to the initial edge of the fascicles.*/ - Real fascicle_ratio_ = 15.0; /**< ratio of length of the fascicles. Include one per fascicle to include.*/ - ComplexShape* body_shape_; - BaseCellLinkedList* cell_linked_list_; + Vecd starting_pnt_; /**< Starting point for net work. */ + Vecd second_pnt_; /**< Second point, approximate the growing direction. */ + size_t n_it_; /**< Number of iterations (generations of branch. */ + bool fascicles_; /**< Create fascicles? */ + size_t segments_in_branch_; /**< approximated number of segments in a branch. */ + Real segment_length_; /**< segment length of the branch. */ + Real angle_ = 0.3; /**< angle with respect to the direction of the previous edge and the new edge. */ + Real repulsivity_ = 0.175; /**< repulsivity parameter. */ + Real grad_factor_; /**< Factor for computing gradient from nearest node. */ + std::vector fascicle_angles_ = {-1.25, 0.75}; /**< angles with respect to the initial edge of the fascicles.*/ + Real fascicle_ratio_ = 15.0; /**< ratio of length of the fascicles. Include one per fascicle to include.*/ + ComplexShape *body_shape_; + BaseCellLinkedList *cell_linked_list_; GenerativeTree *tree_; /** *@brief Get the gradient from nearest points, for imposing repulsive force. @@ -89,8 +89,7 @@ namespace SPH *@param[in] repulsivity(Real) The repulsivity for creating new points. *@param[in] number_segments(size_t) Number of segments in this branch. */ - bool createABranchIfValid(SPHBody* sph_body, size_t parent_id, Real angle, - Real repulsivity, size_t number_segments); + bool createABranchIfValid(size_t parent_id, Real angle, Real repulsivity, size_t number_segments); /** *@brief Functions that creates a new node in the mesh surface and it to the queue is it lies in the surface. *@param[in] init_node vector that contains the coordinates of the last node added in the branch. @@ -105,12 +104,12 @@ namespace SPH *@param[in] nearest_neighbor(ListData) The nearest point of the existing points. *@param[in] parent_id(size_t) Id of parent branch */ - bool isCollision(Vecd& new_point, ListData& nearest_neighbor, size_t parent_id); + bool isCollision(const Vecd &new_point, const ListData &nearest_neighbor, size_t parent_id); /** *@brief Check if the new point is valid according to extra constraint. *@param[in] new_point(Vecd) The enquiry point. */ - virtual bool extraCheck(Vecd& new_point){return false;}; + virtual bool extraCheck(const Vecd &new_point) { return false; }; }; } #endif //PARTICLE_GENERATOR_NETWORK_H \ No newline at end of file diff --git a/SPHINXsys/src/shared/regression_testing/CMakeLists.txt b/SPHINXsys/src/shared/adaptations/CMakeLists.txt similarity index 100% rename from SPHINXsys/src/shared/regression_testing/CMakeLists.txt rename to SPHINXsys/src/shared/adaptations/CMakeLists.txt diff --git a/SPHINXsys/src/shared/particles/particle_adaptation.cpp b/SPHINXsys/src/shared/adaptations/adaptation.cpp similarity index 74% rename from SPHINXsys/src/shared/particles/particle_adaptation.cpp rename to SPHINXsys/src/shared/adaptations/adaptation.cpp index 43df505958..3f51fd771e 100644 --- a/SPHINXsys/src/shared/particles/particle_adaptation.cpp +++ b/SPHINXsys/src/shared/adaptations/adaptation.cpp @@ -1,22 +1,20 @@ /** - * @file particle_adaptation.cpp - * @brief Definition of functions declared in particle_adaptation.h + * @file sph_adaptation.cpp + * @brief Definition of functions declared in adaptation.h * @author Xiangyu Hu and Chi Zhang */ -#include "particle_adaptation.h" +#include "adaptation.h" #include "sph_system.h" #include "all_kernels.h" #include "base_body.h" #include "base_particles.h" -#include "cell_linked_list.h" -#include "level_set.h" namespace SPH { //=================================================================================================// - ParticleAdaptation::ParticleAdaptation(Real h_spacing_ratio, Real system_resolution_ratio, Real small_shift_factor) + SPHAdaptation::SPHAdaptation(Real h_spacing_ratio, Real system_resolution_ratio, Real small_shift_factor) : h_spacing_ratio_(h_spacing_ratio), system_resolution_ratio_(system_resolution_ratio), local_refinement_level_(0), @@ -25,13 +23,13 @@ namespace SPH spacing_min_(0), spacing_ratio_min_(1.0), spacing_ratio_max_(1.0), h_ratio_min_(1.0), h_ratio_max_(1.0), number_density_min_(1.0), number_density_max_(1.0), - kernel_(new KernelWendlandC2()), + kernel_(kernel_ptr_keeper_.createPtr()), sph_body_(nullptr), system_domain_bounds_(), base_particles_(nullptr), small_shift_factor_(small_shift_factor) {}; //=================================================================================================// - void ParticleAdaptation::initialize(SPHBody *sph_body) + void SPHAdaptation::initialize(SPHBody *sph_body) { sph_body_ = sph_body; system_domain_bounds_ = sph_body_->getSPHSystem().system_domain_bounds_; @@ -47,19 +45,13 @@ namespace SPH number_density_max_ = computeReferenceNumberDensity(Vecd(0), h_ratio_min_); } //=================================================================================================// - void ParticleAdaptation::replaceKernel(Kernel *another_kernel) - { - delete kernel_; - kernel_ = another_kernel; - } - //=================================================================================================// - Real ParticleAdaptation:: + Real SPHAdaptation:: RefinedSpacing(Real coarse_particle_spacing, int refinement_level) { return coarse_particle_spacing / powerN(2.0, refinement_level); } //=================================================================================================// - Real ParticleAdaptation::computeReferenceNumberDensity(Vec2d zero, Real h_ratio) + Real SPHAdaptation::computeReferenceNumberDensity(Vec2d zero, Real h_ratio) { Real sigma(0); Real cutoff_radius = kernel_->CutOffRadius(h_ratio); @@ -76,7 +68,7 @@ namespace SPH return sigma; } //=================================================================================================// - Real ParticleAdaptation::computeReferenceNumberDensity(Vec3d zero, Real h_ratio) + Real SPHAdaptation::computeReferenceNumberDensity(Vec3d zero, Real h_ratio) { Real sigma(0); Real cutoff_radius = kernel_->CutOffRadius(h_ratio); @@ -95,37 +87,37 @@ namespace SPH return sigma; } //=================================================================================================// - Real ParticleAdaptation::ReferenceNumberDensity() + Real SPHAdaptation::ReferenceNumberDensity() { return computeReferenceNumberDensity(Vecd(0), 1.0); } //=================================================================================================// - Real ParticleAdaptation::probeNumberDensity(Vecd zero, Real h_ratio) + Real SPHAdaptation::probeNumberDensity(Vecd zero, Real h_ratio) { Real alpha = (h_ratio_max_ - h_ratio) / (h_ratio_max_ - h_ratio_min_ + TinyReal); return alpha * number_density_max_ + (1.0 - alpha) * number_density_min_; } //=================================================================================================// - void ParticleAdaptation::assignBaseParticles(BaseParticles *base_particles) + void SPHAdaptation::assignBaseParticles(BaseParticles *base_particles) { base_particles_ = base_particles; } //=================================================================================================// - BaseCellLinkedList *ParticleAdaptation::createCellLinkedList() + UniquePtr SPHAdaptation::createCellLinkedList() { - return new CellLinkedList(system_domain_bounds_, kernel_->CutOffRadius(), *sph_body_, *this); + return makeUnique(system_domain_bounds_, kernel_->CutOffRadius(), *sph_body_, *this); } //=================================================================================================// - BaseLevelSet *ParticleAdaptation::createLevelSet(ComplexShape &complex_shape) + UniquePtr SPHAdaptation::createLevelSet(Shape &shape) { - return new LevelSet(complex_shape.findBounds(), ReferenceSpacing(), complex_shape, *this, small_shift_factor_); + return makeUnique(shape.findBounds(), ReferenceSpacing(), shape, *this); } //=================================================================================================// ParticleWithLocalRefinement:: ParticleWithLocalRefinement(Real h_spacing_ratio, Real system_resolution_ratio, int local_refinement_level) - : ParticleAdaptation(h_spacing_ratio, system_resolution_ratio) + : SPHAdaptation(h_spacing_ratio, system_resolution_ratio) { local_refinement_level_ = local_refinement_level; local_coarse_level_ = local_refinement_level_ / 2; @@ -143,22 +135,22 @@ namespace SPH //=================================================================================================// void ParticleWithLocalRefinement::assignBaseParticles(BaseParticles *base_particles) { - ParticleAdaptation::assignBaseParticles(base_particles); + SPHAdaptation::assignBaseParticles(base_particles); base_particles->registerAVariable(h_ratio_, "SmoothingLengthRatio", 1.0); } //=================================================================================================// - BaseCellLinkedList *ParticleWithLocalRefinement::createCellLinkedList() + UniquePtr ParticleWithLocalRefinement::createCellLinkedList() { - return new MultilevelCellLinkedList(system_domain_bounds_, kernel_->CutOffRadius(), - getCellLinkedListTotalLevel(), - MaximumSpacingRatio(), *sph_body_, *this); + return makeUnique(system_domain_bounds_, kernel_->CutOffRadius(), + getCellLinkedListTotalLevel(), + MaximumSpacingRatio(), *sph_body_, *this); } //=================================================================================================// - BaseLevelSet *ParticleWithLocalRefinement::createLevelSet(ComplexShape &complex_shape) + UniquePtr ParticleWithLocalRefinement::createLevelSet(Shape &shape) { - return new MultilevelLevelSet(complex_shape.findBounds(), - ReferenceSpacing(), getLevelSetTotalLevel(), - MaximumSpacingRatio(), complex_shape, *this); + return makeUnique(shape.findBounds(), + ReferenceSpacing(), getLevelSetTotalLevel(), + MaximumSpacingRatio(), shape, *this); } //=================================================================================================// ParticleSpacingByBodyShape:: @@ -167,9 +159,9 @@ namespace SPH : ParticleWithLocalRefinement(smoothing_length_ratio, system_resolution_ratio, local_refinement_level){}; //=================================================================================================// - Real ParticleSpacingByBodyShape::getLocalSpacing(ComplexShape &complex_shape, Vecd &position) + Real ParticleSpacingByBodyShape::getLocalSpacing(Shape &shape, Vecd &position) { - Real phi = fabs(complex_shape.findSignedDistance(position)); + Real phi = fabs(shape.findSignedDistance(position)); Real ratio_ref = phi / (2.0 * spacing_ref_ * spacing_ratio_max_); Real target_ratio = spacing_ratio_max_; if (ratio_ref < kernel_->KernelSize()) diff --git a/SPHINXsys/src/shared/particles/particle_adaptation.h b/SPHINXsys/src/shared/adaptations/adaptation.h similarity index 64% rename from SPHINXsys/src/shared/particles/particle_adaptation.h rename to SPHINXsys/src/shared/adaptations/adaptation.h index 5c4c4fd5b6..ea90ccddb1 100644 --- a/SPHINXsys/src/shared/particles/particle_adaptation.h +++ b/SPHINXsys/src/shared/adaptations/adaptation.h @@ -21,9 +21,9 @@ * * * --------------------------------------------------------------------------*/ /** - * @file particle_adaptation.h - * @brief Particle adaptation is for adaptivity of SPH particles. - * The particle adaptation is defined before SPH body. + * @file adaptation.h + * @brief Adaptation is constructed before SPH body, but initialized in SPHBody constructor. + * It defines the parameters for single or multi-resolution computations. * @author Xiangyu Hu and Chi Zhang */ @@ -32,35 +32,37 @@ #include "base_data_package.h" #include "sph_data_containers.h" +#include "cell_linked_list.h" +#include "level_set.h" namespace SPH { class SPHBody; - class ComplexShape; + class Shape; class Kernel; - class BaseCellLinkedList; - class BaseLevelSet; class BaseParticles; /** - * @class ParticleAdaptation - * @brief Base class for particle adaptation - * The base class defined essential global parameteres. - * It is also used for single resolution SPH method, - * where constructor parameter system_resolution_ratio defines . + * @class SPHAdaptation + * @brief Base class for adaptation. + * The base class defines essential global parameteres. It is also used for single-resolution SPH method. + * In the constructor parameter, system_resolution_ratio defines the relation between present resolution to the system reference resolution. * The derived class will be used if further adaptation is introduced. */ - class ParticleAdaptation + class SPHAdaptation { + private: + UniquePtrKeeper kernel_ptr_keeper_; + protected: - Real h_spacing_ratio_; /**< ratio of reference kernel smoothing length to particle spacing */ + Real h_spacing_ratio_; /**< ratio of reference kernel smoothing length to particle spacing */ Real system_resolution_ratio_; /**< ratio of body resolution to system resolution, set to 1.0 by default */ - int local_refinement_level_; /**< refinement level respect to reference particle spacing */ - int local_coarse_level_; //TODO: try to delete this because it leads to confusion on particle resolutions - Real spacing_ref_; /**< reference particle spacing used to determine local particle spacing */ - Real h_ref_; /**< reference particle spacing used to determine local particle smoothing length */ - Real spacing_min_; /**< minimum particle spacing determined by local refinement level */ + int local_refinement_level_; /**< refinement level respect to reference particle spacing */ + int local_coarse_level_; //TODO: try to delete this because it leads to confusion on particle resolutions + Real spacing_ref_; /**< reference particle spacing used to determine local particle spacing */ + Real h_ref_; /**< reference particle spacing used to determine local particle smoothing length */ + Real spacing_min_; /**< minimum particle spacing determined by local refinement level */ Real spacing_ratio_min_; Real spacing_ratio_max_; Real h_ratio_min_; @@ -73,11 +75,11 @@ namespace SPH BoundingBox system_domain_bounds_; BaseParticles *base_particles_; - Real small_shift_factor_; + Real small_shift_factor_; /**< small shift for level generation. TODO: this should be clarified for its usage. */ public: - ParticleAdaptation(Real h_spacing_ratio = 1.3, Real system_resolution_ratio = 1.0, Real small_shift_factor = 0.75); - virtual ~ParticleAdaptation(){}; + SPHAdaptation(Real h_spacing_ratio = 1.3, Real system_resolution_ratio = 1.0, Real small_shift_factor = 0.75); + virtual ~SPHAdaptation(){}; /** Note: called after construction of this and derived classes. */ virtual void initialize(SPHBody *sph_body); @@ -85,8 +87,14 @@ namespace SPH Real ReferenceSpacing() { return spacing_ref_; }; Real ReferenceSmoothingLength() { return h_ref_; }; Kernel *getKernel() { return kernel_; }; - /**Note: replace a kernel should be done before kernel initialization */ - void replaceKernel(Kernel *another_kernel); + /**Note: replace a kernel should be done before kernel initialization, + * which is called in SPHBody constructor. + */ + template + void replaceKernel(ConstructorArgs &&...args) + { + kernel_ = kernel_ptr_keeper_.createPtr(std::forward(args)...); + }; Real MinimumSpacing() { return spacing_min_; }; Real MinimumSpacingRatio() { return spacing_ratio_min_; }; Real MaximumSpacingRatio() { return spacing_ratio_max_; }; @@ -97,8 +105,9 @@ namespace SPH virtual Real SmoothingLengthRatio(size_t particle_index_i) { return 1.0; }; virtual void assignBaseParticles(BaseParticles *base_particles); - virtual BaseCellLinkedList *createCellLinkedList(); - virtual BaseLevelSet *createLevelSet(ComplexShape &complex_shape); + virtual UniquePtr createCellLinkedList(); + virtual UniquePtr createLevelSet(Shape &shape); + protected: Real RefinedSpacing(Real coarse_particle_spacing, int refinement_level); }; @@ -107,26 +116,26 @@ namespace SPH * @class ParticleWithLocalRefinement * @brief Base class for particle with refinement. */ - class ParticleWithLocalRefinement : public ParticleAdaptation + class ParticleWithLocalRefinement : public SPHAdaptation { public: StdLargeVec h_ratio_; /**< the ratio between reference smoothing length to variable smoothing length */ ParticleWithLocalRefinement(Real h_spacing_ratio_, - Real system_resolution_ratio, + Real system_resolution_ratio, int local_refinement_level); virtual ~ParticleWithLocalRefinement(){}; size_t getCellLinkedListTotalLevel(); size_t getLevelSetTotalLevel(); - virtual Real SmoothingLengthRatio(size_t particle_index_i) override - { - return h_ratio_[particle_index_i]; + virtual Real SmoothingLengthRatio(size_t particle_index_i) override + { + return h_ratio_[particle_index_i]; }; virtual void assignBaseParticles(BaseParticles *base_particles) override; - virtual BaseCellLinkedList *createCellLinkedList() override; - virtual BaseLevelSet *createLevelSet(ComplexShape &complex_shape) override; + virtual UniquePtr createCellLinkedList() override; + virtual UniquePtr createLevelSet(Shape &shape) override; }; /** * @class ParticleSpacingByBodyShape @@ -136,11 +145,11 @@ namespace SPH { public: ParticleSpacingByBodyShape(Real smoothing_length_ratio, - Real system_resolution_ratio, + Real system_resolution_ratio, int local_refinement_level); virtual ~ParticleSpacingByBodyShape(){}; - Real getLocalSpacing(ComplexShape &complex_shape, Vecd &position); + Real getLocalSpacing(Shape &shape, Vecd &position); }; } #endif //PARTICLE_ADAPTATION_H \ No newline at end of file diff --git a/SPHINXsys/src/shared/bodies/all_bodies.h b/SPHINXsys/src/shared/bodies/all_bodies.h index 0947695d6a..85b5b4c2b2 100644 --- a/SPHINXsys/src/shared/bodies/all_bodies.h +++ b/SPHINXsys/src/shared/bodies/all_bodies.h @@ -11,4 +11,6 @@ bodies used in SPHinXsys. **/ #include "fluid_body.h" #include "solid_body.h" +#include "observer_body.h" + #endif //ALL_BODIES_H diff --git a/SPHINXsys/src/shared/bodies/base_body.cpp b/SPHINXsys/src/shared/bodies/base_body.cpp index a621fbfa26..77e002c9c0 100644 --- a/SPHINXsys/src/shared/bodies/base_body.cpp +++ b/SPHINXsys/src/shared/bodies/base_body.cpp @@ -8,20 +8,19 @@ #include "sph_system.h" #include "base_particles.h" #include "body_relation.h" -#include "cell_linked_list.h" namespace SPH { //=================================================================================================// - SPHBody::SPHBody(SPHSystem &sph_system, std::string body_name, - ParticleAdaptation *particle_adaptation, ParticleGenerator *particle_generator) + SPHBody::SPHBody(SPHSystem &sph_system, const std::string &body_name, + SharedPtr sph_adaptation_ptr) : sph_system_(sph_system), body_name_(body_name), newly_updated_(true), body_domain_bounds_(0, 0), is_domain_bounds_determined_(false), - particle_adaptation_(particle_adaptation), particle_generator_(particle_generator), - body_shape_(nullptr), generative_structure_(nullptr) + sph_adaptation_(sph_adaptation_ptr_keeper_.assignPtr(sph_adaptation_ptr)), + generative_structure_(nullptr) { sph_system_.addABody(this); - particle_adaptation_->initialize(this); + sph_adaptation_->initialize(this); } //=================================================================================================// BoundingBox SPHBody::getSPHSystemBounds() @@ -39,12 +38,6 @@ namespace SPH return sph_system_; } //=================================================================================================// - void SPHBody::useParticleGeneratorReload() - { - particle_generator_->~ParticleGenerator(); - particle_generator_ = new ParticleGeneratorReload(sph_system_.in_output_, body_name_); - } - //=================================================================================================// void SPHBody::assignBaseParticles(BaseParticles *base_particles) { base_particles_ = base_particles; @@ -58,7 +51,7 @@ namespace SPH } } //=================================================================================================// - void SPHBody::setBodyDomainBounds(BoundingBox body_domain_bounds) + void SPHBody::setBodyDomainBounds(BoundingBox body_domain_bounds) { body_domain_bounds_ = body_domain_bounds; is_domain_bounds_determined_ = true; @@ -68,7 +61,7 @@ namespace SPH { if (!is_domain_bounds_determined_) { - body_domain_bounds_ = body_shape_->findBounds(); + body_domain_bounds_ = body_shape_.findBounds(); is_domain_bounds_determined_ = true; } return body_domain_bounds_; @@ -80,7 +73,13 @@ namespace SPH newly_updated_ = false; } //=================================================================================================// - void SPHBody::writeSurfaceParticlesToVtuFile(std::ofstream &output_file, ShapeSurface& surface_particles) + void SPHBody::writeParticlesToVtpFile(std::ofstream &output_file) + { + base_particles_->writeParticlesToVtpFile(output_file); + newly_updated_ = false; + } + //=================================================================================================// + void SPHBody::writeSurfaceParticlesToVtuFile(std::ofstream &output_file, BodySurface& surface_particles) { base_particles_->writeSurfaceParticlesToVtuFile(output_file, surface_particles); newly_updated_ = false; @@ -113,13 +112,13 @@ namespace SPH base_particles_->readFromXmlForReloadParticle(filefullpath); } //=================================================================================================// - RealBody::RealBody(SPHSystem &sph_system, std::string body_name, - ParticleAdaptation *particle_adaptation, ParticleGenerator *particle_generator) - : SPHBody(sph_system, body_name, particle_adaptation, particle_generator), + RealBody::RealBody(SPHSystem &sph_system, const std::string &body_name, + SharedPtr sph_adaptation_ptr) + : SPHBody(sph_system, body_name, sph_adaptation_ptr), particle_sorting_(this) { sph_system.addARealBody(this); - cell_linked_list_ = particle_adaptation_->createCellLinkedList(); + cell_linked_list_ = cell_linked_list_keeper_.movePtr(sph_adaptation_->createCellLinkedList()); size_t number_of_split_cell_lists = powerN(3, Vecd(0).size()); split_cell_lists_.resize(number_of_split_cell_lists); } @@ -143,138 +142,124 @@ namespace SPH { cell_linked_list_->UpdateCellLists(); } + //=================================================================================================// FictitiousBody:: - FictitiousBody(SPHSystem &system, std::string body_name, - ParticleAdaptation *particle_adaptation, ParticleGenerator *particle_generator) - : SPHBody(system, body_name, particle_adaptation, particle_generator) + FictitiousBody(SPHSystem &system, const std::string &body_name, + SharedPtr sph_adaptation_ptr) + : SPHBody(system, body_name, sph_adaptation_ptr) { system.addAFictitiousBody(this); } //=================================================================================================// - BodyPartByShape::BodyPartByShape(SPHBody *body, std::string body_part_name) - : BodyPart(body, body_part_name), body_part_shape_(nullptr) {} + void BodyPartByParticle::tagParticles(TaggingParticleMethod &tagging_particle_method) + { + for (size_t i = 0; i < base_particles_->total_real_particles_; ++i) + { + tagging_particle_method(i); + } + }; //=================================================================================================// - BoundingBox BodyPartByShape::BodyPartBounds() + void BodyPartByCell::tagCells(TaggingCellMethod &tagging_cell_method) { - return body_part_shape_->findBounds(); + cell_linked_list_->tagBodyPartByCell(body_part_cells_, tagging_cell_method); } //=================================================================================================// - void BodyPartByParticle::tagAParticle(size_t particle_index) + BodyRegionByParticle:: + BodyRegionByParticle(SPHBody &sph_body, const std::string &body_part_name, Shape &shape) + : BodyPartByParticle(sph_body, body_part_name), body_part_shape_(shape) { - body_part_particles_.push_back(particle_index); + TaggingParticleMethod tagging_particle_method = std::bind(&BodyRegionByParticle::tagByContain, this, _1); + tagParticles(tagging_particle_method); } //=================================================================================================// - void BodyPartByParticle::tagBodyPart() + void BodyRegionByParticle::tagByContain(size_t particle_index) { - BaseParticles *base_particles = body_->base_particles_; - for (size_t i = 0; i < base_particles->total_real_particles_; ++i) + if (body_part_shape_.checkContain(base_particles_->pos_n_[particle_index])) { - if (body_part_shape_->checkContain(base_particles->pos_n_[i])) - tagAParticle(i); + body_part_particles_.push_back(particle_index); } } //=================================================================================================// - ShapeSurface::ShapeSurface(SPHBody *body) - : BodyPartByParticle(body, "Surface"), - particle_spacing_min_(body->particle_adaptation_->MinimumSpacing()) + BodySurface::BodySurface(SPHBody &sph_body) + : BodyPartByParticle(sph_body, "BodySurface"), + particle_spacing_min_(sph_body.sph_adaptation_->MinimumSpacing()) { - tagBodyPart(); + TaggingParticleMethod tagging_particle_method = std::bind(&BodySurface::tagNearSurface, this, _1); + tagParticles(tagging_particle_method); + std::cout << "Number of surface particles : " << body_part_particles_.size() << std::endl; } //=================================================================================================// - void ShapeSurface::tagBodyPart() + void BodySurface::tagNearSurface(size_t particle_index) { - BaseParticles *base_particles = body_->base_particles_; - for (size_t i = 0; i < base_particles->total_real_particles_; ++i) - { - Real phi = body_->body_shape_->findSignedDistance(base_particles->pos_n_[i]); - if (fabs(phi) < particle_spacing_min_) - tagAParticle(i); - } - //std::cout << "Number of surface particles : " << body_part_particles_.size() << std::endl; + Real phi = sph_body_->body_shape_.findSignedDistance(base_particles_->pos_n_[particle_index]); + if (fabs(phi) < particle_spacing_min_) + body_part_particles_.push_back(particle_index); } //=================================================================================================// - ShapeSurfaceLayer::ShapeSurfaceLayer(SPHBody *body, Real layer_thickness) - : BodyPartByParticle(body, "InnerLayers"), - thickness_threshold_(body->particle_adaptation_->ReferenceSpacing() * layer_thickness) + BodySurfaceLayer::BodySurfaceLayer(SPHBody &sph_body, Real layer_thickness) + : BodyPartByParticle(sph_body, "InnerLayers"), + thickness_threshold_(sph_body.sph_adaptation_->ReferenceSpacing() * layer_thickness) { - tagBodyPart(); + TaggingParticleMethod tagging_particle_method = std::bind(&BodySurfaceLayer::tagSurfaceLayer, this, _1); + tagParticles(tagging_particle_method); + std::cout << "Number of inner layers particles : " << body_part_particles_.size() << std::endl; } //=================================================================================================// - void ShapeSurfaceLayer::tagBodyPart() + void BodySurfaceLayer::tagSurfaceLayer(size_t particle_index) { - BaseParticles *base_particles = body_->base_particles_; - for (size_t i = 0; i < base_particles->total_real_particles_; ++i) + Real distance = fabs(sph_body_->body_shape_.findSignedDistance(base_particles_->pos_n_[particle_index])); + if (distance < thickness_threshold_) { - Vecd position_i = base_particles->pos_n_[i]; - Real distance = fabs(body_->body_shape_->findSignedDistance(position_i)); - if (distance < thickness_threshold_) - tagAParticle(i); + body_part_particles_.push_back(particle_index); } - std::cout << "Number of inner layers particles : " << body_part_particles_.size() << std::endl; } //=================================================================================================// - BodyPartByCell::BodyPartByCell(RealBody *real_body, std::string body_part_name) - : BodyPartByShape(real_body, body_part_name), real_body_(real_body), - checkIncluded_(std::bind(&BodyPartByCell::checkIncluded, this, _1, _2)) {} - //=================================================================================================// - bool BodyPartByCell::checkIncluded(Vecd cell_position, Real threshold) + BodyRegionByCell::BodyRegionByCell(RealBody &real_body, const std::string &body_part_name, Shape &shape) + : BodyPartByCell(real_body, body_part_name), body_part_shape_(shape) { - return body_part_shape_->checkNotFar(cell_position, threshold); - } + TaggingCellMethod tagging_cell_method = std::bind(&BodyRegionByCell::checkNotFar, this, _1, _2); + tagCells(tagging_cell_method); + }; //=================================================================================================// - void BodyPartByCell::tagBodyPart() + bool BodyRegionByCell::checkNotFar(Vecd cell_position, Real threshold) { - real_body_->cell_linked_list_->tagBodyPartByCell(body_part_cells_, checkIncluded_); + return body_part_shape_.checkNotFar(cell_position, threshold); } //=================================================================================================// NearShapeSurface:: - NearShapeSurface(RealBody *real_body, ComplexShape *complex_shape, std::string body_part_name) - : BodyPartByCell(real_body, body_part_name) - { - level_set_complex_shape_ = new LevelSetComplexShape(real_body, *complex_shape, true); - body_part_shape_ = level_set_complex_shape_; - tagBodyPart(); - } - //=================================================================================================// - NearShapeSurface::NearShapeSurface(RealBody *real_body) - : BodyPartByCell(real_body, "NearShapeSurface") - { - body_part_shape_ = real_body->body_shape_; - level_set_complex_shape_ = dynamic_cast(body_part_shape_); - if (level_set_complex_shape_ == nullptr) - { - std::cout << "\n FAILURE: LevelSetComplexShape is undefined!" << std::endl; - std::cout << __FILE__ << ':' << __LINE__ << std::endl; - exit(1); - } - tagBodyPart(); - } - //=================================================================================================// - LevelSetComplexShape *NearShapeSurface::getLevelSetComplexShape() + NearShapeSurface(RealBody &real_body, const std::string &body_part_name, Shape &shape) + : BodyPartByCell(real_body, body_part_name), + level_set_shape_( + level_set_shape_keeper_.createRef(&real_body, shape, true)) { - return level_set_complex_shape_; + TaggingCellMethod tagging_cell_method = std::bind(&NearShapeSurface::checkNearSurface, this, _1, _2); + tagCells(tagging_cell_method); } //=================================================================================================// - bool NearShapeSurface::checkIncluded(Vecd cell_position, Real threshold) + NearShapeSurface::NearShapeSurface(RealBody &real_body) + : BodyPartByCell(real_body, "NearShapeSurface"), + level_set_shape_( + DynamicCast(this, *real_body.body_shape_.getShapeByName(real_body.getBodyName()))) { - return body_part_shape_->checkNearSurface(cell_position, threshold); + TaggingCellMethod tagging_cell_method = std::bind(&NearShapeSurface::checkNearSurface, this, _1, _2); + tagCells(tagging_cell_method); } //=================================================================================================// - TerminateBranches::TerminateBranches(SPHBody *body) - : BodyPartByParticle(body, "Leaves"), - tree_(dynamic_cast(body->generative_structure_)) + bool NearShapeSurface::checkNearSurface(Vecd cell_position, Real threshold) { - tagBodyPart(); + return level_set_shape_.checkNearSurface(cell_position, threshold); } //=================================================================================================// - void TerminateBranches::tagBodyPart() + TreeTerminates::TreeTerminates(SPHBody &sph_body) + : BodyPartByParticle(sph_body, "Leaves"), + tree_(*DynamicCast(this, sph_body.generative_structure_)) { - for (const auto *branch : tree_->branches_) + for (const auto *branch : tree_.branches_) { if (branch->is_terminated_) { - size_t particle_id = branch->inner_particles_.back(); - tagAParticle(particle_id); + size_t particle_index = branch->inner_particles_.back(); + body_part_particles_.push_back(particle_index); } } } diff --git a/SPHINXsys/src/shared/bodies/base_body.h b/SPHINXsys/src/shared/bodies/base_body.h index a316d2f203..3ca97633ec 100644 --- a/SPHINXsys/src/shared/bodies/base_body.h +++ b/SPHINXsys/src/shared/bodies/base_body.h @@ -38,8 +38,8 @@ #include "base_data_package.h" #include "sph_data_containers.h" -#include "particle_adaptation.h" -#include "all_particle_generators.h" +#include "adaptation.h" +#include "cell_linked_list.h" #include "particle_sorting.h" #include "all_geometries.h" #include "generative_structures.h" @@ -50,9 +50,9 @@ namespace SPH { class SPHSystem; class BaseParticles; - class BaseCellLinkedList; class SPHBodyRelation; - class ShapeSurface; + class ComplexShape; + class BodySurface; /** * @class SPHBody @@ -63,22 +63,24 @@ namespace SPH */ class SPHBody { + private: + SharedPtrKeeper sph_adaptation_ptr_keeper_; + UniquePtrKeeper generative_structure_ptr_keeper_; + protected: SPHSystem &sph_system_; std::string body_name_; - bool newly_updated_; /**< whether this body is in a newly updated state */ + bool newly_updated_; /**< whether this body is in a newly updated state */ /**< Computational domain bounds for boundary conditions. * Note that domain bounds may be different from those of the initial body geometry. */ - BoundingBox body_domain_bounds_; + BoundingBox body_domain_bounds_; bool is_domain_bounds_determined_; public: - ParticleAdaptation *particle_adaptation_; /**< Particle adapation policy. */ - ParticleGenerator *particle_generator_; /**< Particle generator manner */ - BaseParticles *base_particles_; /**< Base particles of this body. */ - PositionsAndVolumes body_input_points_volumes_; /**< For direct generate particles. Note this should be moved to direct generator. */ - ComplexShape *body_shape_; /**< describe the geometry of the body*/ - GenerativeStructure *generative_structure_; /**< structure which can be used to generate particles or/and configurations directly*/ + ComplexShape body_shape_; /**< describe the volumetric geometry of the body */ + SPHAdaptation *sph_adaptation_; /**< Particle adapation policy. */ + BaseParticles *base_particles_; /**< Base particles of this body. */ + GenerativeStructure *generative_structure_; /**< structure which can be used to generate particles or/and configurations directly*/ /** * @brief particle by cells lists is for parallel splitting algorithm. * All particles in each cell are collected together. @@ -89,31 +91,36 @@ namespace SPH StdVec body_relations_; /**< all contact relations centered from this body **/ - explicit SPHBody(SPHSystem &sph_system, std::string body_name, - ParticleAdaptation *particle_adaptation = new ParticleAdaptation(), - ParticleGenerator *particle_generator = new ParticleGeneratorLattice()); + explicit SPHBody(SPHSystem &sph_system, const std::string &body_name, + SharedPtr sph_adaptation_ptr); virtual ~SPHBody(){}; std::string getBodyName(); SPHSystem &getSPHSystem(); - Real getSPHBodyResolutionRef() { return particle_adaptation_->ReferenceSpacing(); }; + Real getSPHBodyResolutionRef() { return sph_adaptation_->ReferenceSpacing(); }; void setNewlyUpdated() { newly_updated_ = true; }; void setNotNewlyUpdated() { newly_updated_ = false; }; bool checkNewlyUpdated() { return newly_updated_; }; - void useParticleGeneratorReload(); - void setBodyDomainBounds(BoundingBox body_domain_bounds); BoundingBox getBodyDomainBounds(); BoundingBox getSPHSystemBounds(); + /** create the generative structure from outside */ + template + GenerativeStructureType *createGenerativeStructure(ConstructorArgs &&...args) + { + generative_structure_ = generative_structure_ptr_keeper_.createPtr(std::forward(args)...); + return DynamicCast(this, generative_structure_); + }; /** This will be called in BaseParticle constructor * and is important because particles are not defined in SPHBody constructor. */ virtual void assignBaseParticles(BaseParticles *base_particles); void allocateConfigurationMemoriesForBufferParticles(); - virtual void writeParticlesToVtuFile(std::ostream &output_file); - virtual void writeSurfaceParticlesToVtuFile(std::ofstream &output_file, ShapeSurface& surface_particles); + virtual void writeParticlesToVtuFile(std::ostream &output_file); + virtual void writeParticlesToVtpFile(std::ofstream &output_file); virtual void writeParticlesToPltFile(std::ofstream &output_file); + virtual void writeSurfaceParticlesToVtuFile(std::ofstream &output_file, BodySurface& surface_particles); virtual void writeParticlesToXmlForRestart(std::string &filefullpath); virtual void readParticlesFromXmlForRestart(std::string &filefullpath); virtual void writeToXmlForReloadParticle(std::string &filefullpath); @@ -128,15 +135,15 @@ namespace SPH */ class RealBody : public SPHBody { + private: + UniquePtrKeeper cell_linked_list_keeper_; + public: ParticleSorting particle_sorting_; BaseCellLinkedList *cell_linked_list_; /**< Cell linked mesh of this body. */ - RealBody(SPHSystem &sph_system, std::string body_name, ParticleAdaptation *particle_adaptation, - ParticleGenerator *particle_generator = new ParticleGeneratorLattice()); - RealBody(SPHSystem &sph_system, std::string body_name, Real sph_body_resolution_ref, - ParticleAdaptation *particle_adaptation, - ParticleGenerator *particle_generator = new ParticleGeneratorLattice()); + RealBody(SPHSystem &sph_system, const std::string &body_name, + SharedPtr sph_adaptation_ptr); virtual ~RealBody(){}; /** This will be called in BaseParticle constructor @@ -154,178 +161,182 @@ namespace SPH class FictitiousBody : public SPHBody { public: - FictitiousBody(SPHSystem &system, std::string body_name, - ParticleAdaptation *particle_adaptation = new ParticleAdaptation(), - ParticleGenerator *particle_generator = new ParticleGeneratorDirect()); + FictitiousBody(SPHSystem &system, const std::string &body_name, + SharedPtr sph_adaptation_ptr); virtual ~FictitiousBody(){}; }; /** * @class BodyPart - * @brief An abstract auxillary class for SPHBody to indicate a part of the body. + * @brief An auxillary class for SPHBody to indicate a part of the body. */ + using namespace std::placeholders; class BodyPart { public: - BodyPart(SPHBody *body, std::string body_part_name) - : body_(body), body_part_name_(body_part_name){}; + BodyPart(SPHBody &sph_body, const std::string &body_part_name) + : sph_body_(&sph_body), body_part_name_(body_part_name){}; virtual ~BodyPart(){}; - SPHBody *getBody() { return body_; }; + SPHBody *getSPHBody() { return sph_body_; }; std::string BodyPartName() { return body_part_name_; }; protected: - SPHBody *body_; + SPHBody *sph_body_; std::string body_part_name_; - - virtual void tagBodyPart() = 0; }; - /** - * @class BodyPartByShape - * @brief An auxillary class for SPHBody to indicate - * a part of the body defined by a presribed complex shape. - */ - class BodyPartByShape : public BodyPart - { - public: - BodyPartByShape(SPHBody *body, std::string body_part_name); - virtual ~BodyPartByShape(){}; - - ComplexShape *getBodyPartShape() { return body_part_shape_; }; - BoundingBox BodyPartBounds(); - - protected: - ComplexShape *body_part_shape_; - }; /** * @class BodyPartByParticle - * @brief An auxillary class for SPHBody to - * indicate a part of the body moving together with particles. + * @brief A body part with a collection of particles. */ - class BodyPartByParticle : public BodyPartByShape + class BodyPartByParticle : public BodyPart { public: IndexVector body_part_particles_; /**< Collection particle in this body part. */ - BodyPartByParticle(SPHBody *body, std::string body_part_name) - : BodyPartByShape(body, body_part_name), - body_part_bounds_(Vecd(0), Vecd(0)), body_part_bounds_set_(false) - {}; - + BodyPartByParticle(SPHBody &sph_body, const std::string &body_part_name) + : BodyPart(sph_body, body_part_name), base_particles_(sph_body.base_particles_), + body_part_bounds_(Vecd(0), Vecd(0)), body_part_bounds_set_(false){}; virtual ~BodyPartByParticle(){}; - void setBodyPartBounds(BoundingBox bbox){ + void setBodyPartBounds(BoundingBox bbox) + { body_part_bounds_ = bbox; body_part_bounds_set_ = true; }; - BoundingBox getBodyPartBounds(){ - if (!body_part_bounds_set_) std::cout << "WARNING: the body part bounds are not set for BodyPartByParticle." << std::endl; + BoundingBox getBodyPartBounds() + { + if (!body_part_bounds_set_) + std::cout << "WARNING: the body part bounds are not set for BodyPartByParticle." << std::endl; return body_part_bounds_; } protected: - void tagAParticle(size_t particle_index); - virtual void tagBodyPart() override; - + BaseParticles *base_particles_; BoundingBox body_part_bounds_; bool body_part_bounds_set_; + + typedef std::function TaggingParticleMethod; + void tagParticles(TaggingParticleMethod &tagging_particle_method); }; /** - * @class ShapeSurface - * @brief A auxillary class for Body to - * indicate the surface of a shape + * @class BodyPartByCell + * @brief A body part with a collection of cell lists. */ - class ShapeSurface : public BodyPartByParticle + class BodyPartByCell : public BodyPart { public: - ShapeSurface(SPHBody *body); - virtual ~ShapeSurface(){}; + CellLists body_part_cells_; /**< Collection of cells to indicate the body part. */ + + BodyPartByCell(RealBody &real_body, const std::string &body_part_name) + : BodyPart(real_body, body_part_name), cell_linked_list_(real_body.cell_linked_list_){}; + virtual ~BodyPartByCell(){}; protected: - Real particle_spacing_min_; - virtual void tagBodyPart() override; + BaseCellLinkedList *cell_linked_list_; + typedef std::function TaggingCellMethod; + void tagCells(TaggingCellMethod &tagging_cell_method); }; /** - * @class ShapeSurfaceLayer - * @brief A auxillary class for Body to - * indicate the particles within the inner layers of a shape + * @class BodyRegionByParticle + * @brief A body part with the collection of particles within by a presribed shape. */ - class ShapeSurfaceLayer : public BodyPartByParticle + class BodyRegionByParticle : public BodyPartByParticle { public: - ShapeSurfaceLayer(SPHBody *body, Real layer_thickness = 3.0); - virtual ~ShapeSurfaceLayer(){}; + Shape &body_part_shape_; - protected: - Real thickness_threshold_; + BodyRegionByParticle(SPHBody &sph_body, const std::string &body_part_name, Shape &shape); + virtual ~BodyRegionByParticle(){}; - virtual void tagBodyPart() override; + private: + void tagByContain(size_t particle_index); }; /** - * @class BodyPartByCell - * @brief An auxillary class for SPHBody to - * indicate a part of the body fixed in space defined by mesh cells. + * @class BodySurface + * @brief A body part with the collection of particles at surface of a body */ - using namespace std::placeholders; - class BodyPartByCell : public BodyPartByShape + class BodySurface : public BodyPartByParticle { - protected: - RealBody *real_body_; - typedef std::function CheckIncludedFunctor; - CheckIncludedFunctor checkIncluded_; + public: + explicit BodySurface(SPHBody &sph_body); + virtual ~BodySurface(){}; - /** all cells near or contained by the body part shape are included */ - virtual bool checkIncluded(Vecd cell_position, Real threshold); - virtual void tagBodyPart() override; + private: + Real particle_spacing_min_; + void tagNearSurface(size_t particle_index); + }; + /** + * @class BodySurfaceLayer + * @brief A body part with the collection of particles within the surface layers of a body. + */ + class BodySurfaceLayer : public BodyPartByParticle + { public: - CellLists body_part_cells_; /**< Collection of cells to indicate the body part. */ + explicit BodySurfaceLayer(SPHBody &sph_body, Real layer_thickness = 3.0); + virtual ~BodySurfaceLayer(){}; - BodyPartByCell(RealBody *real_body, std::string body_part_name); - virtual ~BodyPartByCell(){}; + private: + Real thickness_threshold_; + void tagSurfaceLayer(size_t particle_index); + }; + + /** + * @class BodyRegionByCell + * @brief A body part with the cell lists within a prescribed shape. + */ + class BodyRegionByCell : public BodyPartByCell + { + public: + Shape &body_part_shape_; + + BodyRegionByCell(RealBody &real_body, const std::string &body_part_name, Shape &shape); + virtual ~BodyRegionByCell(){}; + + private: + bool checkNotFar(Vecd cell_position, Real threshold); }; /** * @class NearShapeSurface - * @brief An auxillary class for SPHBody to - * indicate the region close to the surface of shape. + * @brief A body part with the cell lists near the surface of a prescribed shape. */ class NearShapeSurface : public BodyPartByCell { + private: + UniquePtrKeeper level_set_shape_keeper_; + public: + LevelSetShape &level_set_shape_; + /** for the case that the body part shape is not that of the body */ - NearShapeSurface(RealBody *real_body, ComplexShape *complex_shape, std::string body_part_name); + NearShapeSurface(RealBody &real_body, const std::string &body_part_name, Shape &shape); /** for the case that the body part is the surface of the body shape */ - NearShapeSurface(RealBody *real_body); + explicit NearShapeSurface(RealBody &real_body); virtual ~NearShapeSurface(){}; - LevelSetComplexShape *getLevelSetComplexShape(); - - protected: - LevelSetComplexShape *level_set_complex_shape_; + private: /** only cells near the surface of the body part shape are included */ - virtual bool checkIncluded(Vecd cell_position, Real threshold) override; + bool checkNearSurface(Vecd cell_position, Real threshold); }; /** - * @class TerminateBranches - * @brief A auxillary class for a Tree-like Body to - * indicate the particles from the terminates of the tree. + * @class TreeTerminates + * @brief A body part with the collection of particles as the terminates of the tree. */ - class TerminateBranches : public BodyPartByParticle + class TreeTerminates : public BodyPartByParticle { public: - TerminateBranches(SPHBody *body); - virtual ~TerminateBranches(){}; + GenerativeTree &tree_; - protected: - GenerativeTree *tree_; - virtual void tagBodyPart() override; + explicit TreeTerminates(SPHBody &sph_body); + virtual ~TreeTerminates(){}; }; } #endif //BASE_BODY_H \ No newline at end of file diff --git a/SPHINXsys/src/shared/bodies/body_relation.cpp b/SPHINXsys/src/shared/bodies/body_relation.cpp index cab90d06c3..4fb1a4e0a8 100644 --- a/SPHINXsys/src/shared/bodies/body_relation.cpp +++ b/SPHINXsys/src/shared/bodies/body_relation.cpp @@ -13,11 +13,11 @@ namespace SPH { //=================================================================================================// - SPHBodyRelation::SPHBodyRelation(SPHBody *sph_body) - : sph_body_(sph_body), base_particles_(sph_body->base_particles_) {} + SPHBodyRelation::SPHBodyRelation(SPHBody &sph_body) + : sph_body_(&sph_body), base_particles_(sph_body.base_particles_) {} //=================================================================================================// - BaseBodyRelationInner::BaseBodyRelationInner(RealBody *real_body) - : SPHBodyRelation(real_body), real_body_(real_body) + BaseBodyRelationInner::BaseBodyRelationInner(RealBody &real_body) + : SPHBodyRelation(real_body), real_body_(&real_body) { subscribeToBody(); updateConfigurationMemories(); @@ -43,9 +43,9 @@ namespace SPH ap); } //=================================================================================================// - BodyRelationInner::BodyRelationInner(RealBody *real_body) - : BaseBodyRelationInner(real_body), get_inner_neighbor_(real_body), - cell_linked_list_(dynamic_cast(real_body->cell_linked_list_)) {} + BodyRelationInner::BodyRelationInner(RealBody &real_body) + : BaseBodyRelationInner(real_body), get_inner_neighbor_(&real_body), + cell_linked_list_(DynamicCast(this, real_body.cell_linked_list_)) {} //=================================================================================================// void BodyRelationInner::updateConfiguration() { @@ -58,18 +58,19 @@ namespace SPH } //=================================================================================================// BodyRelationInnerVariableSmoothingLength:: - BodyRelationInnerVariableSmoothingLength(RealBody *real_body) + BodyRelationInnerVariableSmoothingLength(RealBody &real_body) : BaseBodyRelationInner(real_body), total_levels_(0), - get_inner_neighbor_variable_smoothing_length_(real_body) + get_inner_neighbor_variable_smoothing_length_(&real_body) { MultilevelCellLinkedList *multi_level_cell_linked_list = - dynamic_cast(real_body->cell_linked_list_); + DynamicCast(this, real_body.cell_linked_list_); cell_linked_list_levels_ = multi_level_cell_linked_list->getMeshLevels(); total_levels_ = cell_linked_list_levels_.size(); for (size_t l = 0; l != total_levels_; ++l) { get_multi_level_search_depth_.push_back( - new SearchDepthVariableSmoothingLength(real_body, cell_linked_list_levels_[l])); + search_variable_smoothinglength_ptr_vector_keeper_ + .createPtr(real_body, cell_linked_list_levels_[l])); } } //=================================================================================================// @@ -87,13 +88,13 @@ namespace SPH } //=================================================================================================// SolidBodyRelationSelfContact:: - SolidBodyRelationSelfContact(RealBody *real_body) + SolidBodyRelationSelfContact(RealBody &real_body) : BaseBodyRelationInner(real_body), - body_surface_layer_(ShapeSurfaceLayer(real_body)), + body_surface_layer_(real_body), body_part_particles_(body_surface_layer_.body_part_particles_), get_body_part_particle_index_(body_part_particles_), - get_self_contact_neighbor_(real_body), - cell_linked_list_(dynamic_cast(real_body->cell_linked_list_)) {} + get_self_contact_neighbor_(&real_body), + cell_linked_list_(DynamicCast(this, real_body.cell_linked_list_)) {} //=================================================================================================// void SolidBodyRelationSelfContact::resetNeighborhoodCurrentSize() { @@ -121,19 +122,19 @@ namespace SPH get_self_contact_neighbor_); } //=================================================================================================// - BaseBodyRelationContact::BaseBodyRelationContact(SPHBody *sph_body, RealBodyVector contact_sph_bodies) + BaseBodyRelationContact::BaseBodyRelationContact(SPHBody &sph_body, RealBodyVector contact_sph_bodies) : SPHBodyRelation(sph_body), contact_bodies_(contact_sph_bodies) { subscribeToBody(); updateConfigurationMemories(); } //=================================================================================================// - BaseBodyRelationContact::BaseBodyRelationContact(SPHBody *sph_body, BodyPartVector contact_body_parts) + BaseBodyRelationContact::BaseBodyRelationContact(SPHBody &sph_body, BodyPartVector contact_body_parts) : SPHBodyRelation(sph_body) { for (size_t k = 0; k != contact_body_parts.size(); ++k) { - contact_bodies_.push_back(dynamic_cast(contact_body_parts[k]->getBody())); + contact_bodies_.push_back(DynamicCast(this, contact_body_parts[k]->getSPHBody())); } subscribeToBody(); updateConfigurationMemories(); @@ -166,13 +167,13 @@ namespace SPH } } //=================================================================================================// - BodyRelationContact::BodyRelationContact(SPHBody *sph_body, RealBodyVector contact_sph_bodies) + BodyRelationContact::BodyRelationContact(SPHBody &sph_body, RealBodyVector contact_sph_bodies) : BaseBodyRelationContact(sph_body, contact_sph_bodies) { initialization(); } //=================================================================================================// - BodyRelationContact::BodyRelationContact(SPHBody *sph_body, BodyPartVector contact_body_parts) + BodyRelationContact::BodyRelationContact(SPHBody &sph_body, BodyPartVector contact_body_parts) : BaseBodyRelationContact(sph_body, contact_body_parts) { initialization(); @@ -183,10 +184,12 @@ namespace SPH for (size_t k = 0; k != contact_bodies_.size(); ++k) { CellLinkedList *target_cell_linked_list = - dynamic_cast(contact_bodies_[k]->cell_linked_list_); + DynamicCast(this, contact_bodies_[k]->cell_linked_list_); target_cell_linked_lists_.push_back(target_cell_linked_list); - get_search_depths_.push_back(new SearchDepthMultiResolution(sph_body_, target_cell_linked_list)); - get_contact_neighbors_.push_back(new NeighborRelationContact(sph_body_, contact_bodies_[k])); + get_search_depths_.push_back( + search_depth_multi_resolution_ptr_vector_keeper_.createPtr(*sph_body_, target_cell_linked_list)); + get_contact_neighbors_.push_back( + neighbor_relation_contact_ptr_vector_keeper_.createPtr(sph_body_, contact_bodies_[k])); } } //=================================================================================================// @@ -204,21 +207,21 @@ namespace SPH } } //=================================================================================================// - SolidBodyRelationContact::SolidBodyRelationContact(SPHBody *sph_body, RealBodyVector contact_bodies) + SolidBodyRelationContact::SolidBodyRelationContact(SPHBody &sph_body, RealBodyVector contact_bodies) : BaseBodyRelationContact(sph_body, contact_bodies), - body_surface_layer_(ShapeSurfaceLayer(sph_body)), - body_part_particles_(body_surface_layer_.body_part_particles_), + body_surface_layer_(shape_surface_ptr_keeper_.createPtr(sph_body)), + body_part_particles_(body_surface_layer_->body_part_particles_), get_body_part_particle_index_(body_part_particles_) { initialization(); } //=================================================================================================// SolidBodyRelationContact:: - SolidBodyRelationContact(SolidBodyRelationSelfContact *solid_body_relation_self_contact, + SolidBodyRelationContact(SolidBodyRelationSelfContact &solid_body_relation_self_contact, RealBodyVector contact_bodies) - : BaseBodyRelationContact(solid_body_relation_self_contact->real_body_, contact_bodies), - body_surface_layer_(solid_body_relation_self_contact->body_surface_layer_), - body_part_particles_(body_surface_layer_.body_part_particles_), + : BaseBodyRelationContact(*solid_body_relation_self_contact.real_body_, contact_bodies), + body_surface_layer_(&solid_body_relation_self_contact.body_surface_layer_), + body_part_particles_(body_surface_layer_->body_part_particles_), get_body_part_particle_index_(body_part_particles_) { initialization(); @@ -247,10 +250,12 @@ namespace SPH for (size_t k = 0; k != contact_bodies_.size(); ++k) { CellLinkedList *target_cell_linked_list = - dynamic_cast(contact_bodies_[k]->cell_linked_list_); + DynamicCast(this, contact_bodies_[k]->cell_linked_list_); target_cell_linked_lists_.push_back(target_cell_linked_list); - get_search_depths_.push_back(new SearchDepthMultiResolution(sph_body_, target_cell_linked_list)); - get_contact_neighbors_.push_back(new NeighborRelationSolidContact(sph_body_, contact_bodies_[k])); + get_search_depths_.push_back( + search_depth_multi_resolution_ptr_vector_keeper_.createPtr(*sph_body_, target_cell_linked_list)); + get_contact_neighbors_.push_back( + neighbor_relation_contact_ptr_vector_keeper_.createPtr(sph_body_, contact_bodies_[k])); } } //=================================================================================================// @@ -273,10 +278,10 @@ namespace SPH generative_structure_->buildParticleConfiguration(*base_particles_, inner_configuration_); } //=================================================================================================// - BodyPartRelationContact::BodyPartRelationContact(BodyPart *body_part, RealBodyVector contact_bodies) - : BodyRelationContact(body_part->getBody(), contact_bodies), body_part_(body_part), - body_part_particles_(dynamic_cast(body_part)->body_part_particles_), - get_body_part_particle_index_(dynamic_cast(body_part)->body_part_particles_) + BodyPartRelationContact::BodyPartRelationContact(BodyPart &body_part, RealBodyVector contact_bodies) + : BodyRelationContact(*body_part.getSPHBody(), contact_bodies), body_part_(&body_part), + body_part_particles_(DynamicCast(this, body_part).body_part_particles_), + get_body_part_particle_index_(DynamicCast(this, body_part).body_part_particles_) { } //=================================================================================================// @@ -293,12 +298,14 @@ namespace SPH } } //=================================================================================================// - BodyRelationContactToBodyPart::BodyRelationContactToBodyPart(RealBody *real_body, BodyPartVector contact_body_parts) + BodyRelationContactToBodyPart::BodyRelationContactToBodyPart(RealBody &real_body, BodyPartVector contact_body_parts) : BodyRelationContact(real_body, contact_body_parts), contact_body_parts_(contact_body_parts) { for (size_t k = 0; k != contact_bodies_.size(); ++k) { - get_part_contact_neighbors_.push_back(new NeighborRelationContactBodyPart(sph_body_, contact_body_parts[k])); + get_part_contact_neighbors_.push_back( + neighbor_relation_contact_body_part_ptr_vector_keeper_ + .createPtr(sph_body_, contact_body_parts[k])); } } //=================================================================================================// @@ -316,39 +323,64 @@ namespace SPH } //=================================================================================================// ComplexBodyRelation:: - ComplexBodyRelation(BaseBodyRelationInner *inner_relation, BaseBodyRelationContact *contact_relation) - : SPHBodyRelation(inner_relation->sph_body_), - inner_relation_(inner_relation), contact_relation_(contact_relation), - contact_bodies_(contact_relation->contact_bodies_), - inner_configuration_(inner_relation->inner_configuration_), - contact_configuration_(contact_relation->contact_configuration_) + ComplexBodyRelation(BaseBodyRelationInner &inner_relation, BaseBodyRelationContact &contact_relation) + : SPHBodyRelation(*inner_relation.sph_body_), + inner_relation_(inner_relation), + contact_relation_(contact_relation), + contact_bodies_(contact_relation_.contact_bodies_), + inner_configuration_(inner_relation_.inner_configuration_), + contact_configuration_(contact_relation_.contact_configuration_) { updateConfigurationMemories(); } //=================================================================================================// - ComplexBodyRelation::ComplexBodyRelation(RealBody *real_body, RealBodyVector contact_bodies) - : ComplexBodyRelation(new BodyRelationInner(real_body), - new BodyRelationContact(real_body, contact_bodies)) {} + ComplexBodyRelation::ComplexBodyRelation(RealBody &real_body, RealBodyVector contact_bodies) + : SPHBodyRelation(real_body), + inner_relation_(base_body_relation_inner_ptr_keeper_.createRef(real_body)), + contact_relation_(base_body_relation_contact_ptr_keeper_ + .createRef(real_body, contact_bodies)), + contact_bodies_(contact_relation_.contact_bodies_), + inner_configuration_(inner_relation_.inner_configuration_), + contact_configuration_(contact_relation_.contact_configuration_) + { + updateConfigurationMemories(); + } //=================================================================================================// ComplexBodyRelation:: - ComplexBodyRelation(BaseBodyRelationInner *inner_relation, RealBodyVector contact_bodies) - : ComplexBodyRelation(inner_relation, - new BodyRelationContact(inner_relation->sph_body_, contact_bodies)) {} + ComplexBodyRelation(BaseBodyRelationInner &inner_relation, RealBodyVector contact_bodies) + : SPHBodyRelation(*inner_relation.sph_body_), + inner_relation_(inner_relation), + contact_relation_(base_body_relation_contact_ptr_keeper_.createRef( + DynamicCast(this, *sph_body_), contact_bodies)), + contact_bodies_(contact_relation_.contact_bodies_), + inner_configuration_(inner_relation_.inner_configuration_), + contact_configuration_(contact_relation_.contact_configuration_) + { + updateConfigurationMemories(); + } //=================================================================================================// - ComplexBodyRelation::ComplexBodyRelation(RealBody *real_body, BodyPartVector contact_body_parts) - : ComplexBodyRelation(new BodyRelationInner(real_body), - new BodyRelationContactToBodyPart(real_body, contact_body_parts)) {} + ComplexBodyRelation::ComplexBodyRelation(RealBody &real_body, BodyPartVector contact_body_parts) + : SPHBodyRelation(real_body), + inner_relation_(base_body_relation_inner_ptr_keeper_.createRef(real_body)), + contact_relation_(base_body_relation_contact_ptr_keeper_ + .createRef(real_body, contact_body_parts)), + contact_bodies_(contact_relation_.contact_bodies_), + inner_configuration_(inner_relation_.inner_configuration_), + contact_configuration_(contact_relation_.contact_configuration_) + { + updateConfigurationMemories(); + } //=================================================================================================// void ComplexBodyRelation::updateConfigurationMemories() { - inner_relation_->updateConfigurationMemories(); - contact_relation_->updateConfigurationMemories(); + inner_relation_.updateConfigurationMemories(); + contact_relation_.updateConfigurationMemories(); } //=================================================================================================// void ComplexBodyRelation::updateConfiguration() { - inner_relation_->updateConfiguration(); - contact_relation_->updateConfiguration(); + inner_relation_.updateConfiguration(); + contact_relation_.updateConfiguration(); } //=================================================================================================// } diff --git a/SPHINXsys/src/shared/bodies/body_relation.h b/SPHINXsys/src/shared/bodies/body_relation.h index 3fb9dadc96..181015bbd2 100644 --- a/SPHINXsys/src/shared/bodies/body_relation.h +++ b/SPHINXsys/src/shared/bodies/body_relation.h @@ -49,7 +49,8 @@ namespace SPH struct BodyPartParticlesIndex { IndexVector &body_part_particles_; - BodyPartParticlesIndex(IndexVector &body_part_particles) : body_part_particles_(body_part_particles){}; + explicit BodyPartParticlesIndex(IndexVector &body_part_particles) + : body_part_particles_(body_part_particles){}; size_t operator()(size_t particle_entry) const { return body_part_particles_[particle_entry]; }; }; @@ -65,10 +66,11 @@ namespace SPH struct SearchDepthMultiResolution { int search_depth_; - SearchDepthMultiResolution(SPHBody *body, CellLinkedList *target_cell_linked_list) : search_depth_(1) + SearchDepthMultiResolution(SPHBody &sph_body, CellLinkedList *target_cell_linked_list) + : search_depth_(1) { Real inv_grid_spacing_ = 1.0 / target_cell_linked_list->GridSpacing(); - Kernel *kernel_ = body->particle_adaptation_->getKernel(); + Kernel *kernel_ = sph_body.sph_adaptation_->getKernel(); search_depth_ = 1 + (int)floor(kernel_->CutOffRadius() * inv_grid_spacing_); }; int operator()(size_t particle_index) const { return search_depth_; }; @@ -82,10 +84,10 @@ namespace SPH Real inv_grid_spacing_; Kernel *kernel_; StdLargeVec &h_ratio_; - SearchDepthVariableSmoothingLength(SPHBody *body, CellLinkedList *target_cell_linked_list) + SearchDepthVariableSmoothingLength(SPHBody &sph_body, CellLinkedList *target_cell_linked_list) : inv_grid_spacing_(1.0 / target_cell_linked_list->GridSpacing()), - kernel_(body->particle_adaptation_->getKernel()), - h_ratio_(*body->base_particles_->getVariableByName("SmoothingLengthRatio")){}; + kernel_(sph_body.sph_adaptation_->getKernel()), + h_ratio_(*sph_body.base_particles_->getVariableByName("SmoothingLengthRatio")){}; int operator()(size_t particle_index) const { return 1 + (int)floor(kernel_->CutOffRadius(h_ratio_[particle_index]) * inv_grid_spacing_); @@ -102,7 +104,7 @@ namespace SPH SPHBody *sph_body_; BaseParticles *base_particles_; - SPHBodyRelation(SPHBody *sph_body); + explicit SPHBodyRelation(SPHBody &sph_body); virtual ~SPHBodyRelation(){}; void subscribeToBody() { sph_body_->body_relations_.push_back(this); }; @@ -123,7 +125,7 @@ namespace SPH RealBody *real_body_; ParticleConfiguration inner_configuration_; /**< inner configuration for the neighbor relations. */ - BaseBodyRelationInner(RealBody *real_body); + explicit BaseBodyRelationInner(RealBody &real_body); virtual ~BaseBodyRelationInner(){}; virtual void updateConfigurationMemories() override; @@ -142,7 +144,7 @@ namespace SPH CellLinkedList *cell_linked_list_; public: - BodyRelationInner(RealBody *real_body); + explicit BodyRelationInner(RealBody &real_body); virtual ~BodyRelationInner(){}; virtual void updateConfiguration() override; @@ -154,6 +156,9 @@ namespace SPH */ class BodyRelationInnerVariableSmoothingLength : public BaseBodyRelationInner { + private: + UniquePtrVectorKeeper search_variable_smoothinglength_ptr_vector_keeper_; + protected: size_t total_levels_; SPHBodyParticlesIndex get_particle_index_; @@ -162,7 +167,7 @@ namespace SPH StdVec cell_linked_list_levels_; public: - BodyRelationInnerVariableSmoothingLength(RealBody *real_body); + explicit BodyRelationInnerVariableSmoothingLength(RealBody &real_body); virtual ~BodyRelationInnerVariableSmoothingLength(){}; virtual void updateConfiguration() override; @@ -175,9 +180,9 @@ namespace SPH class SolidBodyRelationSelfContact : public BaseBodyRelationInner { public: - ShapeSurfaceLayer body_surface_layer_; + BodySurfaceLayer body_surface_layer_; - SolidBodyRelationSelfContact(RealBody *real_body); + explicit SolidBodyRelationSelfContact(RealBody &real_body); virtual ~SolidBodyRelationSelfContact(){}; virtual void updateConfiguration() override; @@ -198,6 +203,10 @@ namespace SPH */ class BaseBodyRelationContact : public SPHBodyRelation { + protected: + UniquePtrVectorKeeper search_depth_multi_resolution_ptr_vector_keeper_; + UniquePtrVectorKeeper neighbor_relation_contact_ptr_vector_keeper_; + protected: StdVec target_cell_linked_lists_; StdVec get_search_depths_; @@ -209,8 +218,8 @@ namespace SPH RealBodyVector contact_bodies_; ContatcParticleConfiguration contact_configuration_; /**< Configurations for particle interaction between bodies. */ - BaseBodyRelationContact(SPHBody *body, RealBodyVector contact_bodies); - BaseBodyRelationContact(SPHBody *body, BodyPartVector contact_body_parts); + BaseBodyRelationContact(SPHBody &sph_body, RealBodyVector contact_bodies); + BaseBodyRelationContact(SPHBody &sph_body, BodyPartVector contact_body_parts); virtual ~BaseBodyRelationContact(){}; virtual void updateConfigurationMemories() override; @@ -228,8 +237,8 @@ namespace SPH void initialization(); public: - BodyRelationContact(SPHBody *body, RealBodyVector contact_bodies); - BodyRelationContact(SPHBody *body, BodyPartVector contact_body_parts); + BodyRelationContact(SPHBody &sph_body, RealBodyVector contact_bodies); + BodyRelationContact(SPHBody &sph_body, BodyPartVector contact_body_parts); virtual ~BodyRelationContact(){}; virtual void updateConfiguration() override; }; @@ -240,15 +249,20 @@ namespace SPH */ class SolidBodyRelationContact : public BaseBodyRelationContact { + private: + UniquePtrKeeper shape_surface_ptr_keeper_; + public: - ShapeSurfaceLayer body_surface_layer_; + BodySurfaceLayer *body_surface_layer_; - SolidBodyRelationContact(SPHBody *body, RealBodyVector contact_bodies); - SolidBodyRelationContact(SolidBodyRelationSelfContact *solid_body_relation_self_contact, + SolidBodyRelationContact(SPHBody &sph_body, RealBodyVector contact_bodies); + SolidBodyRelationContact(SolidBodyRelationSelfContact &solid_body_relation_self_contact, RealBodyVector contact_bodies); + virtual ~SolidBodyRelationContact(){}; virtual void updateConfiguration() override; + protected: IndexVector &body_part_particles_; BodyPartParticlesIndex get_body_part_particle_index_; @@ -256,7 +270,7 @@ namespace SPH void initialization(); virtual void resetNeighborhoodCurrentSize() override; }; - + /** * @class GenerativeBodyRelationInner * @brief The relation within a reduced SPH body, viz. network @@ -267,9 +281,9 @@ namespace SPH GenerativeStructure *generative_structure_; public: - GenerativeBodyRelationInner(RealBody *real_body) + explicit GenerativeBodyRelationInner(RealBody &real_body) : BodyRelationInner(real_body), - generative_structure_(real_body->generative_structure_){}; + generative_structure_(real_body.generative_structure_){}; virtual ~GenerativeBodyRelationInner(){}; virtual void updateConfiguration() override; @@ -281,13 +295,12 @@ namespace SPH */ class BodyPartRelationContact : public BodyRelationContact { - public: BodyPart *body_part_; IndexVector &body_part_particles_; BodyPartParticlesIndex get_body_part_particle_index_; - BodyPartRelationContact(BodyPart *body_part, RealBodyVector contact_bodies); + BodyPartRelationContact(BodyPart &body_part, RealBodyVector contact_bodies); virtual ~BodyPartRelationContact(){}; virtual void updateConfiguration() override; @@ -299,12 +312,14 @@ namespace SPH */ class BodyRelationContactToBodyPart : public BodyRelationContact { + protected: + UniquePtrVectorKeeper neighbor_relation_contact_body_part_ptr_vector_keeper_; public: BodyPartVector contact_body_parts_; StdVec get_part_contact_neighbors_; - BodyRelationContactToBodyPart(RealBody *real_body, BodyPartVector contact_body_parts); + BodyRelationContactToBodyPart(RealBody &real_body, BodyPartVector contact_body_parts); virtual ~BodyRelationContactToBodyPart(){}; virtual void updateConfiguration() override; @@ -318,22 +333,22 @@ namespace SPH */ class ComplexBodyRelation : public SPHBodyRelation { + private: + UniquePtrKeeper base_body_relation_inner_ptr_keeper_; + UniquePtrKeeper base_body_relation_contact_ptr_keeper_; + public: - BaseBodyRelationInner *inner_relation_; - BaseBodyRelationContact *contact_relation_; + BaseBodyRelationInner &inner_relation_; + BaseBodyRelationContact &contact_relation_; RealBodyVector contact_bodies_; ParticleConfiguration &inner_configuration_; ContatcParticleConfiguration &contact_configuration_; - ComplexBodyRelation(BaseBodyRelationInner *inner_relation, BaseBodyRelationContact *contact_relation); - ComplexBodyRelation(RealBody *real_body, RealBodyVector contact_bodies); - ComplexBodyRelation(BaseBodyRelationInner *inner_relation, RealBodyVector contact_bodies); - ComplexBodyRelation(RealBody *real_body, BodyPartVector contact_body_parts); - virtual ~ComplexBodyRelation() - { - delete inner_relation_; - delete contact_relation_; - }; + ComplexBodyRelation(BaseBodyRelationInner &inner_relation, BaseBodyRelationContact &contact_relation); + ComplexBodyRelation(RealBody &real_body, RealBodyVector contact_bodies); + ComplexBodyRelation(BaseBodyRelationInner &inner_relation, RealBodyVector contact_bodies); + ComplexBodyRelation(RealBody &real_body, BodyPartVector contact_body_parts); + virtual ~ComplexBodyRelation(){}; virtual void updateConfigurationMemories() override; virtual void updateConfiguration() override; diff --git a/SPHINXsys/src/shared/bodies/fluid_body.cpp b/SPHINXsys/src/shared/bodies/fluid_body.cpp index ab2fd5caa7..f168a86f20 100644 --- a/SPHINXsys/src/shared/bodies/fluid_body.cpp +++ b/SPHINXsys/src/shared/bodies/fluid_body.cpp @@ -8,9 +8,9 @@ namespace SPH { //=================================================================================================// - FluidBody::FluidBody(SPHSystem &system, std::string body_name, - ParticleAdaptation* particle_adaptation, ParticleGenerator* particle_generator) - : RealBody(system, body_name, particle_adaptation, particle_generator), + FluidBody::FluidBody(SPHSystem &system, const std::string &body_name, + SharedPtr sph_adaptation_ptr) + : RealBody(system, body_name, sph_adaptation_ptr), iteration_count_(0) {} //=================================================================================================// void FluidBody::updateCellLinkedList() @@ -21,8 +21,8 @@ namespace SPH { cell_linked_list_->UpdateCellLists(); } //=================================================================================================// - EulerianFluidBody::EulerianFluidBody(SPHSystem &system, std::string body_name, - ParticleAdaptation* particle_adaptation, ParticleGenerator* particle_generator) - : RealBody(system, body_name, particle_adaptation, particle_generator) {} + EulerianFluidBody::EulerianFluidBody(SPHSystem &system, const std::string &body_name, + SharedPtr sph_adaptation_ptr) + : RealBody(system, body_name, sph_adaptation_ptr) {} //=================================================================================================// } diff --git a/SPHINXsys/src/shared/bodies/fluid_body.h b/SPHINXsys/src/shared/bodies/fluid_body.h index bb4a59aa57..0c3939c14f 100644 --- a/SPHINXsys/src/shared/bodies/fluid_body.h +++ b/SPHINXsys/src/shared/bodies/fluid_body.h @@ -43,9 +43,8 @@ namespace SPH { class FluidBody : public RealBody { public: - explicit FluidBody(SPHSystem &system, std::string body_name, - ParticleAdaptation* particle_adaptation = new ParticleAdaptation(), - ParticleGenerator* particle_generator = new ParticleGeneratorLattice()); + explicit FluidBody(SPHSystem &system, const std::string &body_name, + SharedPtr sph_adaptation_ptr = makeShared()); virtual ~FluidBody() {}; /** Update cell linked list with particle sorting. */ @@ -62,9 +61,8 @@ namespace SPH { class EulerianFluidBody : public RealBody { public: - explicit EulerianFluidBody(SPHSystem &system, std::string body_name, - ParticleAdaptation* particle_adaptation = new ParticleAdaptation(), - ParticleGenerator* particle_generator = new ParticleGeneratorLattice()); + explicit EulerianFluidBody(SPHSystem &system, const std::string &body_name, + SharedPtr sph_adaptation_ptr = makeShared()); virtual ~EulerianFluidBody() {}; virtual EulerianFluidBody* ThisObjectPtr() override { return this; }; diff --git a/SPHINXsys/src/shared/bodies/observer_body.h b/SPHINXsys/src/shared/bodies/observer_body.h new file mode 100644 index 0000000000..56cb2ce4f3 --- /dev/null +++ b/SPHINXsys/src/shared/bodies/observer_body.h @@ -0,0 +1,52 @@ +/* -------------------------------------------------------------------------* +* SPHinXsys * +* --------------------------------------------------------------------------* +* SPHinXsys (pronunciation: s'finksis) is an acronym from Smoothed Particle * +* Hydrodynamics for industrial compleX systems. It provides C++ APIs for * +* physical accurate simulation and aims to model coupled industrial dynamic * +* systems including fluid, solid, multi-body dynamics and beyond with SPH * +* (smoothed particle hydrodynamics), a meshless computational method using * +* particle discretization. * +* * +* SPHinXsys is partially funded by German Research Foundation * +* (Deutsche Forschungsgemeinschaft) DFG HU1527/6-1, HU1527/10-1 * +* and HU1527/12-1. * +* * +* Portions copyright (c) 2017-2020 Technical University of Munich and * +* the authors' affiliations. * +* * +* Licensed under the Apache License, Version 2.0 (the "License"); you may * +* not use this file except in compliance with the License. You may obtain a * +* copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * +* * +* --------------------------------------------------------------------------*/ +/** + * @file base_body.h + * @brief This is the base classes of SPH bodies. The real body is for + * that with cell linked list and the fictitious one does not. + * Before the definition of the SPH bodies, the shapes with complex + * geometries, i.e. those are produced by advanced binary operation, + * such as intersection, should be produced first. + * Then, all shapes used in body definition should be either contain + * or not contain each other. + * Partial overlap between them are not premitted. + * @author Luhui Han, Chi ZHang and Xiangyu Hu + */ + +#ifndef OBSERVER_BODY_H +#define OBSERVER_BODY_H + +#include "base_body.h" + +namespace SPH +{ + class ObserverBody : public FictitiousBody + { + public: + ObserverBody(SPHSystem &system, const std::string &body_name, + SharedPtr sph_adaptation_ptr = makeShared()) + : FictitiousBody(system, body_name, sph_adaptation_ptr) {}; + virtual ~ObserverBody(){}; + }; +} +#endif //OBSERVER_BODY_H \ No newline at end of file diff --git a/SPHINXsys/src/shared/bodies/solid_body.cpp b/SPHINXsys/src/shared/bodies/solid_body.cpp index 3fd0a4818a..2f57f230e4 100644 --- a/SPHINXsys/src/shared/bodies/solid_body.cpp +++ b/SPHINXsys/src/shared/bodies/solid_body.cpp @@ -11,29 +11,30 @@ #include "base_material.h" #include "solid_particles.h" -namespace SPH { +namespace SPH +{ //=================================================================================================// - SolidBody::SolidBody(SPHSystem &system, std::string body_name, - ParticleAdaptation* particle_adaptation, ParticleGenerator* particle_generator) - : RealBody(system, body_name, particle_adaptation, particle_generator) + SolidBody::SolidBody(SPHSystem &system, const std::string &body_name, + SharedPtr sph_adaptation_ptr) + : RealBody(system, body_name, sph_adaptation_ptr) { sph_system_.addASolidBody(this); } //=================================================================================================// - ThinStructure::ThinStructure(SPHSystem& system, std::string body_name, - ParticleAdaptation* particle_adaptation, ParticleGenerator* particle_generator) - : SolidBody(system, body_name, particle_adaptation, particle_generator) + ThinStructure::ThinStructure(SPHSystem &system, const std::string &body_name, + SharedPtr sph_adaptation_ptr) + : SolidBody(system, body_name, sph_adaptation_ptr) { - particle_adaptation->getKernel()->reduceOnce(); + sph_adaptation_ptr->getKernel()->reduceOnce(); } //=================================================================================================// - SolidBodyPartForSimbody - ::SolidBodyPartForSimbody(SPHBody* solid_body, std::string solid_body_part_name) - : BodyPartByParticle(solid_body, solid_body_part_name) + SolidBodyPartForSimbody:: + SolidBodyPartForSimbody(SPHBody &body, const std::string &body_part_name, Shape &shape) + : BodyRegionByParticle(body, body_part_name, shape), + solid_particles_(DynamicCast(this, body.base_particles_)), + solid_body_density_(DynamicCast(this, base_particles_->base_material_)->ReferenceDensity()) { - solid_particles_ = dynamic_cast(body_->base_particles_); - Solid* solid = dynamic_cast(body_->base_particles_->base_material_); - solid_body_density_ = solid->ReferenceDensity(); + setMassProperties(); } //=================================================================================================// } diff --git a/SPHINXsys/src/shared/bodies/solid_body.h b/SPHINXsys/src/shared/bodies/solid_body.h index d6e1241d47..f0202dfd70 100644 --- a/SPHINXsys/src/shared/bodies/solid_body.h +++ b/SPHINXsys/src/shared/bodies/solid_body.h @@ -26,14 +26,13 @@ * @author Luhui Han, Chi ZHang and Xiangyu Hu */ - #ifndef SOLID_BODY_H #define SOLID_BODY_H - #include "base_body.h" -namespace SPH { +namespace SPH +{ /** * @brief Preclaimed class. */ @@ -46,11 +45,10 @@ namespace SPH { class SolidBody : public RealBody { public: - SolidBody(SPHSystem &system, std::string body_name, - ParticleAdaptation* particle_adaptation = new ParticleAdaptation(1.15), - ParticleGenerator* particle_generator = new ParticleGeneratorLattice()); - virtual ~SolidBody() {}; - virtual SolidBody* ThisObjectPtr() override {return this;}; + SolidBody(SPHSystem &system, const std::string &body_name, + SharedPtr sph_adaptation_ptr = makeShared(1.15)); + virtual ~SolidBody(){}; + virtual SolidBody *ThisObjectPtr() override { return this; }; }; /** @@ -60,11 +58,10 @@ namespace SPH { class ThinStructure : public SolidBody { public: - ThinStructure(SPHSystem& system, std::string body_name, - ParticleAdaptation* particle_adaptation = new ParticleAdaptation(1.15), - ParticleGenerator* particle_generator = new ParticleGeneratorLattice()); - virtual ~ThinStructure() {}; - virtual ThinStructure* ThisObjectPtr() override {return this;}; + ThinStructure(SPHSystem &system, const std::string &body_name, + SharedPtr sph_adaptation_ptr = makeShared(1.15)); + virtual ~ThinStructure(){}; + virtual ThinStructure *ThisObjectPtr() override { return this; }; }; /** @@ -73,19 +70,23 @@ namespace SPH { * The mass, origin, and unit inertial matrix are computed. * Note: In Simbody, all spatial vectors are three dimensional. */ - class SolidBodyPartForSimbody : public BodyPartByParticle + class SolidBodyPartForSimbody : public BodyRegionByParticle { + protected: + UniquePtrKeeper mass_properties_ptr_keeper_; + public: Vec3d initial_mass_center_; - SimTK::MassProperties* body_part_mass_properties_; - - SolidBodyPartForSimbody(SPHBody* body, std::string solid_body_part_name); - virtual~SolidBodyPartForSimbody() {}; + SimTK::MassProperties *body_part_mass_properties_; + + SolidBodyPartForSimbody(SPHBody &body, const std::string &body_part_name, Shape &shape); + virtual ~SolidBodyPartForSimbody(){}; + protected: Real solid_body_density_; - SolidParticles* solid_particles_; - - virtual void tagBodyPart() override; - }; + SolidParticles *solid_particles_; + private: + void setMassProperties(); + }; } #endif //SOLID_BODY_H diff --git a/SPHINXsys/src/shared/common/array_allocation.h b/SPHINXsys/src/shared/common/array_allocation.h index 6ace3c622d..06e102919e 100644 --- a/SPHINXsys/src/shared/common/array_allocation.h +++ b/SPHINXsys/src/shared/common/array_allocation.h @@ -23,7 +23,7 @@ #ifndef ARRAY_ALLOCATION_H #define ARRAY_ALLOCATION_H -#include "small_vectors.h" +#include "vector_functions.h" namespace SPH { //------------------------------------------------------------------------------------------------- diff --git a/SPHINXsys/src/shared/common/base_data_package.h b/SPHINXsys/src/shared/common/base_data_package.h index a9b2c9dbdd..7ee0e9e6d7 100644 --- a/SPHINXsys/src/shared/common/base_data_package.h +++ b/SPHINXsys/src/shared/common/base_data_package.h @@ -25,9 +25,10 @@ #include "scalar_functions.h" #include "data_type.h" -#include "small_vectors.h" +#include "vector_functions.h" #include "array_allocation.h" #include "large_data_containers.h" +#include "ownership.h" #define TBB_PARALLEL true diff --git a/SPHINXsys/src/shared/common/image_mhd.h b/SPHINXsys/src/shared/common/image_mhd.h index d9ae0cb7c8..686299274c 100644 --- a/SPHINXsys/src/shared/common/image_mhd.h +++ b/SPHINXsys/src/shared/common/image_mhd.h @@ -32,7 +32,7 @@ #ifndef __EMSCRIPTEN__ -#include "small_vectors.h" +#include "vector_functions.h" #include "sph_data_containers.h" #include diff --git a/SPHINXsys/src/shared/common/large_data_containers.h b/SPHINXsys/src/shared/common/large_data_containers.h index 4a2a3fe9e2..de281c1f38 100644 --- a/SPHINXsys/src/shared/common/large_data_containers.h +++ b/SPHINXsys/src/shared/common/large_data_containers.h @@ -51,8 +51,11 @@ namespace SPH { template using StdVec = std::vector; - template - using DataVec = std::vector>; + template + using DoubleVec = std::vector>; + + template + using TripleVec = std::vector>>; } #endif //LARGE_DATA_CONTAINER_H diff --git a/SPHINXsys/src/shared/common/ownership.h b/SPHINXsys/src/shared/common/ownership.h new file mode 100644 index 0000000000..73e24209ee --- /dev/null +++ b/SPHINXsys/src/shared/common/ownership.h @@ -0,0 +1,180 @@ +/* -------------------------------------------------------------------------* +* SPHinXsys * +* --------------------------------------------------------------------------* +* SPHinXsys (pronunciation: s'finksis) is an acronym from Smoothed Particle * +* Hydrodynamics for industrial compleX systems. It provides C++ APIs for * +* physical accurate simulation and aims to model coupled industrial dynamic * +* systems including fluid, solid, multi-body dynamics and beyond with SPH * +* (smoothed particle hydrodynamics), a meshless computational method using * +* particle discretization. * +* * +* SPHinXsys is partially funded by German Research Foundation * +* (Deutsche Forschungsgemeinschaft) DFG HU1527/6-1, HU1527/10-1 * +* and HU1527/12-1. * +* * +* Portions copyright (c) 2017-2020 Technical University of Munich and * +* the authors' affiliations. * +* * +* Licensed under the Apache License, Version 2.0 (the "License"); you may * +* not use this file except in compliance with the License. You may obtain a * +* copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * +* * +* --------------------------------------------------------------------------*/ +/** + * @file ownership.h + * @brief Here, the classes related to the ownship of objects are defined + * by implementing Resource Acquisition Is Initialization (RAII). + * The basic idea in SPHinXsys to use defined ownership. + * Unique pointers are used as much as possible and shared pointer only used + * when a default smart pointer is generated as argument in the constructors. + * In this case, for objects with statically defined lifetime, references will be used. + * For those with dynamical lifetime, we will use smart-pointer keepers to handel. + * Basically, newing a raw pointer is forbiden through out the code except for + * raw matrixes, such as the cell linked list mesh, that will be deleted in destructor, + * especially, when new features are introduced. + * Generally, the classes here are private member and + * the smart pointer is used only when the memory is allocated. + * After that, we take reference or raw pointer out and use them as observer. + * @author Xiangyu Hu + */ +#ifndef OWNERSHIP_H +#define OWNERSHIP_H + +#include "base_data_type.h" + +#include + +namespace SPH +{ + template + CastingType *DynamicCast(OwnerType *owner, CastedType *casted) + { + CastingType *tmp = dynamic_cast(casted); + if (tmp == nullptr) + { + std::cout << "\n Error: pointer DynamicCasting " << typeid(*casted).name() << " leads to nullptr! \n"; + std::cout << "\n This error locates in " << typeid(*owner).name() << '\n'; + exit(1); + } + return tmp; + } + + template + CastingType &DynamicCast(OwnerType *owner, CastedType &casted) + { + CastingType *tmp = dynamic_cast(&casted); + if (tmp == nullptr) + { + std::cout << "\n Error: reference DynamicCasting " << typeid(casted).name() << " leads to nullptr! \n"; + std::cout << "\n This error locates in " << typeid(*owner).name() << '\n'; + exit(1); + } + return *tmp; + } + + template + using UniquePtr = std::unique_ptr; + + template + UniquePtr makeUnique(ConstructorArgs &&...args) + { + return std::unique_ptr(new T(std::forward(args)...)); + } + + /** + * @class UniquePtrKeeper + * @brief A wrapper to provide an ownership for a new derived object + * which previous often generated by newing a raw pointer. + */ + template + class UniquePtrKeeper + { + public: + /** output the observer as pointer */ + template + BaseType *createPtr(ConstructorArgs &&...args) + { + ptr_member_.reset(new DerivedType(std::forward(args)...)); + return ptr_member_.get(); + }; + + /** output the observer as reference */ + template + BaseType &createRef(ConstructorArgs &&...args) + { + ptr_member_.reset(new DerivedType(std::forward(args)...)); + return *ptr_member_.get(); + }; + + /** output the observer as pointer */ + BaseType *movePtr(UniquePtr moved_unique_ptr) + { + ptr_member_ = std::move(moved_unique_ptr); + return ptr_member_.get(); + }; + + private: + UniquePtr ptr_member_; + }; + + /** + * @class UniquePtrVectorKeeper + * @brief A wrapper to provide an ownership for + * a vector of base class pointers which point to derived objects. + * It should be a private member. + */ + template + class UniquePtrVectorKeeper + { + public: + /** used to create a new derived object in the vector + * and output the base class pointer as observer */ + template + BaseType *createPtr(ConstructorArgs &&...args) + { + ptr_vector_.push_back(makeUnique(std::forward(args)...)); + return ptr_vector_.back().get(); + }; + + private: + std::vector> ptr_vector_; + }; + + + template + using SharedPtr = std::shared_ptr; + + template + SharedPtr makeShared(ConstructorArgs &&...args) + { + return std::make_shared(std::forward(args)...); + } + + /** + * @class SharedPtrKeeper + * @brief A wrapper to provide an shared ownership for a new derived object + * which previous often generated by newing a raw pointer. + */ + template + class SharedPtrKeeper + { + public: + /** output the observer as pointer */ + template + BaseType *resetPtr(ConstructorArgs &&...args) + { + ptr_member_= makeShared(std::forward(args)...); + return ptr_member_.get(); + }; + /** output the observer as pointer */ + BaseType *assignPtr(SharedPtr shared_ptr) + { + ptr_member_ = shared_ptr; + return ptr_member_.get(); + }; + + private: + SharedPtr ptr_member_; + }; +} +#endif //OWNERSHIP_H diff --git a/SPHINXsys/src/shared/common/scalar_functions.cpp b/SPHINXsys/src/shared/common/scalar_functions.cpp index 768b3893f2..70e916e686 100644 --- a/SPHINXsys/src/shared/common/scalar_functions.cpp +++ b/SPHINXsys/src/shared/common/scalar_functions.cpp @@ -11,5 +11,70 @@ namespace SPH { int ThirdAxis(int axis_direction) { return SecondAxis(SecondAxis(axis_direction)); } + //=================================================================================================// + double getLeftStateInWeno(double v_1, double v_2, double v_3, double v_4) + { + double v1 = v_1; + double v2 = v_2; + double v3 = v_3; + double v4 = v_4; + + double f1 = 0.5*v2 + 0.5*v3; + double f2 = (-0.5)*v1 + 1.5*v2; + double f3 = v2 / 3.0 + 5.0*v3 / 6.0 - v4 / 6.0; + + double epsilon = 1.0e-6; + double s1 = pow(v2 - v3, 2) + epsilon; + double s2 = pow(v2 - v1, 2) + epsilon; + double s3 = pow(3.0*v2 - 4.0*v3 + v4, 2) / 4.0 + 13.0*pow(v2 - 2.0*v3 + v4, 2) / 12.0 + epsilon; + double s12 = 13.0*pow(v1 - 2.0 * v2 + v3, 2) / 12.0 + pow(v1 - v3, 2) / 4.0 + epsilon; + double tau_4 = (v1*(547.0*v1 - 2522.0*v2 + 1922.0*v3 - 494.0*v4) + + v2 * (3443.0*v2 - 5966.0*v3 + 1602.0*v4) + + v3 * (2843.0*v3 - 1642.0*v4) + + 267.0*v4*v4) / 240.0; + + double alpha_1 = (1.0 + (tau_4 / s1)*(tau_4 / s12)) / 3.0; + double alpha_2 = (1.0 + (tau_4 / s2)*(tau_4 / s12)) / 6.0; + double alpha_3 = (1.0 + tau_4 / s3) / 2.0; + double w_1 = alpha_1 / (alpha_1 + alpha_2 + alpha_3); + double w_2 = alpha_2 / (alpha_1 + alpha_2 + alpha_3); + double w_3 = alpha_3 / (alpha_1 + alpha_2 + alpha_3); + double left_state = w_1 * f1 + w_2 * f2 + w_3 * f3; + + return left_state; + } + //=================================================================================================// + double getRightStateInWeno(double v_1, double v_2, double v_3, double v_4) + { + double v1 = v_4; + double v2 = v_3; + double v3 = v_2; + double v4 = v_1; + + double f1 = 0.5*v2 + 0.5*v3; + double f2 = (-0.5)*v1 + 1.5*v2; + double f3 = v2 / 3.0 + 5.0*v3 / 6.0 - v4 / 6.0; + + double epsilon = 1.0e-6; + double s1 = pow(v2 - v3, 2) + epsilon; + double s2 = pow(v2 - v1, 2) + epsilon; + double s3 = pow(3.0*v2 - 4.0*v3 + v4, 2) / 4.0 + 13.0*pow(v2 - 2.0*v3 + v4, 2) / 12.0 + epsilon; + double s12 = 13.0*pow(v1 - 2.0 * v2 + v3, 2) / 12.0 + pow(v1 - v3, 2) / 4.0 + epsilon; + double tau_4 = (v1*(547.0*v1 - 2522.0*v2 + 1922.0*v3 - 494.0*v4) + + v2 * (3443.0*v2 - 5966.0*v3 + 1602.0*v4) + + v3 * (2843.0*v3 - 1642.0*v4) + + 267.0*v4*v4) / 240.0; + + double alpha_1 = (1.0 + (tau_4 / s1)*(tau_4 / s12)) / 3.0; + double alpha_2 = (1.0 + (tau_4 / s2)*(tau_4 / s12)) / 6.0; + double alpha_3 = (1.0 + tau_4 / s3) / 2.0; + double w_1 = alpha_1 / (alpha_1 + alpha_2 + alpha_3); + double w_2 = alpha_2 / (alpha_1 + alpha_2 + alpha_3); + double w_3 = alpha_3 / (alpha_1 + alpha_2 + alpha_3); + double right_state = w_1 * f1 + w_2 * f2 + w_3 * f3; + + return right_state; + } + //=================================================================================================// } diff --git a/SPHINXsys/src/shared/common/scalar_functions.h b/SPHINXsys/src/shared/common/scalar_functions.h index c23003504b..fcb91efb15 100644 --- a/SPHINXsys/src/shared/common/scalar_functions.h +++ b/SPHINXsys/src/shared/common/scalar_functions.h @@ -180,5 +180,8 @@ namespace SPH { * The axis_direction must be 0, 1 for 2d and 0, 1, 2 for 3d */ int ThirdAxis(int axis_direction); + + double getLeftStateInWeno(double v1, double v2, double v3, double v4); + double getRightStateInWeno(double v1, double v2, double v3, double v4); } #endif //SCALAR_FUNCTIONS_H diff --git a/SPHINXsys/src/shared/common/sph_data_containers.h b/SPHINXsys/src/shared/common/sph_data_containers.h index 4ea3e0f971..3a8a6cc8f5 100644 --- a/SPHINXsys/src/shared/common/sph_data_containers.h +++ b/SPHINXsys/src/shared/common/sph_data_containers.h @@ -10,7 +10,8 @@ #include "base_data_package.h" #include "base_data_type.h" -namespace SPH { +namespace SPH +{ /** * @brief Preclaimed classes. */ @@ -26,24 +27,25 @@ namespace SPH { /** Bounding box for system, body, body part and shape, first: lower bound, second: upper bound. */ typedef std::pair BoundingBox; /** Check if a point is inside the bounding box */ - bool checkIfPointInBoundingBox(Vec3d point, BoundingBox& bbox); - bool checkIfPointInBoundingBox(Vec2d point, BoundingBox& bbox); + bool checkIfPointInBoundingBox(Vec3d point, BoundingBox &bbox); + bool checkIfPointInBoundingBox(Vec2d point, BoundingBox &bbox); /** Generalized particle data type */ - typedef std::tuple*>, StdVec*>, StdVec*>, - StdVec*>> ParticleData; + typedef std::tuple *>, StdVec *>, StdVec *>, + StdVec *>> + ParticleData; /** Generalized particle variable to index map */ typedef std::array, 4> ParticleDataMap; /** Generalized particle variable list */ typedef std::array>, 4> ParticleVariableList; /** Vector of Material. Note that vector of references are not allowed in c++.*/ - using MaterialVector = StdVec; + using MaterialVector = StdVec; /** Vector of bodies */ - using SPHBodyVector = StdVec; - using SolidBodyVector = StdVec; - using RealBodyVector = StdVec; - using BodyPartVector = StdVec; - using FictitiousBodyVector = StdVec; + using SPHBodyVector = StdVec; + using SolidBodyVector = StdVec; + using RealBodyVector = StdVec; + using BodyPartVector = StdVec; + using FictitiousBodyVector = StdVec; /** Index container with elements of size_t. */ using IndexVector = StdVec; @@ -55,63 +57,80 @@ namespace SPH { /** Vector of list data pair */ using ListDataVector = StdLargeVec; /** Cell lists*/ - using CellLists = StdLargeVec; + using CellLists = StdLargeVec; /** Concurrent vector .*/ - template + template using ConcurrentVector = LargeVec; /** concurrent cell lists*/ - using ConcurrentCellLists = LargeVec; + using ConcurrentCellLists = LargeVec; /** Split cell list for split algorithms. */ using SplitCellLists = StdVec; /** Pair of point and volume. */ - using PositionsAndVolumes = StdVec>; + using PositionsVolumes = StdVec>; - /** loop particle data with operations */ - template typename OperationType, - typename... ParticleArgs> - void loopParticleData(ParticleData& particle_data, ParticleArgs... particle_args) + /** an operation on particle data of all types */ + template