Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
b56cba6
build: move brigand and cxxopts to external/ and add cmake files
sy-cui Jan 17, 2026
f789e4f
refactor: replace external codes with vcpkg configs
sy-cui Mar 10, 2026
bf09957
Fix H5Metadata format lookup
skim0119 Mar 27, 2026
8d6b6c4
Preserve Cosserat initializer state during setup
skim0119 Mar 27, 2026
d9de809
fix segfault, due to old Mock impl
skim0119 Mar 27, 2026
756fe44
feat: variable time step interface for python interface
sy-cui May 23, 2025
47b6f02
feat: fish swimming case study
sy-cui May 23, 2025
372545f
chore: formatting python files
sy-cui May 23, 2025
164207b
fix: fixed vtkh5py setup
sy-cui May 23, 2025
d26f8ae
feat: data logger for small pieces of rod info
sy-cui May 23, 2025
ce02531
chore: add rod data logging to simulation scripts
sy-cui May 23, 2025
d41ad93
chore: query function for the mpi flow interaction class inspecting w…
sy-cui May 25, 2025
ce7feab
chore: parameter change for non-mpi
sy-cui May 25, 2025
f24b8c2
feat: mpi implemenetation now distributes the case studies onto the p…
sy-cui May 25, 2025
b011158
fix: added cstdint headers where appropriate
sy-cui May 27, 2025
f43d56c
fix: added the missing scope for initialize_component
sy-cui May 27, 2025
c57f919
chore: remove temporary debug codes
sy-cui May 27, 2025
61a0226
fix: fixed flow interaction computation logic
sy-cui May 29, 2025
4e90f7e
chore: minor formatting
sy-cui May 31, 2025
5a3f343
refactor: enable auto-ghosting only for the first flow interaction
sy-cui May 31, 2025
38e7778
fix: enable track order for vtkhdf group creation so that partitione …
sy-cui May 31, 2025
26f3fe7
fix: index -> Index for partitioned_dataset
sy-cui May 31, 2025
e4f4492
chore: fish head data file
sy-cui Jun 1, 2025
5000ea8
feat: fish_swimming.py now uses partitioned datasest for rod io and l…
sy-cui Jun 1, 2025
803d984
refactor: fish_swimming_mpi now load fish head data, and function sig…
sy-cui Jun 1, 2025
ff635f5
feat: forcing grid and flow interaction classes for multiple fish
sy-cui Jun 2, 2025
06a7ff6
feat: multifish mpi flow interaction
sy-cui Jun 2, 2025
dbaafb6
feat: multi fish case
sy-cui Jun 2, 2025
f1a1caf
refactor multi_fish_swimming_mpi now uses partitioned dataset
sy-cui Jun 4, 2025
51f0d14
refactor: specify compression backend & level with h5py
sy-cui Jun 30, 2025
7670840
fix: remove compression since hdf5-mpi doesn't support compression, a…
sy-cui Jun 30, 2025
c792c18
refactor: add an additional set of fish head data and move all data t…
sy-cui Jul 1, 2025
e501b27
refactor: move vtkh5py/ to utils/io/
sy-cui Jul 1, 2025
920e44d
refactor: set up __init__.py and move fish_data_logging.py to io
sy-cui Jul 1, 2025
06f307a
feat: mpi_polydata_writer, moved to io/ along with mpi_image_data_writer
sy-cui Jul 1, 2025
998264f
chore: remove unused import in fish_grid.py
sy-cui Jul 1, 2025
502af24
refactor: rename data/ to fish_init_data/
sy-cui Jul 1, 2025
2081341
refactor: adjust imports in fish_swimming.py according to new packaging
sy-cui Jul 1, 2025
a2b5f7f
chore: remove unused import in mpi_polydata_writer.py
sy-cui Jul 1, 2025
bdce277
doc: add build types to .gitignore
sy-cui Jul 1, 2025
3483d7a
chore: formatting for utils/
sy-cui Jul 1, 2025
faa2a60
fix: fixed packaging to avoid circular import
sy-cui Jul 1, 2025
2b16ac3
fix: fixed io import in fish_swimming.py
sy-cui Jul 1, 2025
f0e7821
refactor: remove fish_init_data/ to assets/
sy-cui Jul 2, 2025
421826e
doc: add all directory with glob pattern *data* to .gitignore
sy-cui Jul 2, 2025
5b7334d
refactor: move both MPI writers to one file
sy-cui Jul 2, 2025
22ab934
feat: read feature for mpi_hdf5_io, writers are now renamed to io
sy-cui Jul 2, 2025
ee29567
chore: reformat one file
sy-cui Jul 2, 2025
868b65c
fix: fixed asset path in fish_swimming.py
sy-cui Jul 2, 2025
eae1f9c
chore: is_empty() utility function for MultiFishFlowInteractionMPI
sy-cui Jul 2, 2025
a9844cd
feat: cpp file for fish grid
sy-cui Jul 3, 2025
e67da0c
doc: add *.so to .gitignore
sy-cui Jul 3, 2025
125a267
build: adjust build to include cpp extension
sy-cui Jul 3, 2025
7eda9b1
feat: immersed boundary forcing grid class using the cpp helper
sy-cui Jul 3, 2025
efa1ef8
fix: add new forcing class to package
sy-cui Jul 3, 2025
30d3d96
fix: minor bug fixes for new fish grid
sy-cui Jul 3, 2025
b4eb041
feat: utility function for path finding and data globbing
sy-cui Jul 4, 2025
c89b869
feat: mpi io for fish now takes lagrangian grid data
sy-cui Jul 4, 2025
5d389e4
feat: pybinding for function set_current_time
sy-cui Jul 4, 2025
a215747
refactor: add virtual fish to mpi fish io
sy-cui Jul 4, 2025
290f7d1
fix: lag field io datatype now fixed to float64
sy-cui Jul 5, 2025
2b88a7d
fix: MPIFishIO now allow non-conforming lagrangian grid fields
sy-cui Jul 6, 2025
273fc7a
feat: mpi fish swimming case with fishes distributed
sy-cui Jul 6, 2025
958f3fe
fix: add back force copying
sy-cui Jul 6, 2025
4857549
refactor: abstract fish distribution across ranks and add concentrate…
sy-cui Jul 6, 2025
bcc0c71
refactor: remove multi_fish_swimming_mpi.py as its functionality is c…
sy-cui Jul 6, 2025
4d4b55f
chore: remove unused imports
sy-cui Jul 6, 2025
eee92e8
refactor: strcmp is now case insensitive
sy-cui Jul 6, 2025
09d377c
fix: change click option signature to avoid collision
sy-cui Jul 6, 2025
4d82689
chore: rename fish origin data file names
sy-cui Mar 30, 2026
e62934b
fix: changed cpp17 namespace to std to reflect the compiler changes
sy-cui Mar 30, 2026
4273528
doc: add docstrings to fish_swimming_mpi.py functions
sy-cui Mar 30, 2026
524d02a
fix: sync changes from main
sy-cui Apr 3, 2026
56d7034
feat: 'step_width' interface function that allows time-stepping simul…
sy-cui Apr 3, 2026
a7d5fa3
refactor: switch fish_utils local compiler version to c++20 for consi…
sy-cui Apr 3, 2026
4488c3b
build: modify utils/__init__.py to exclude MPI related packages if no…
sy-cui Apr 3, 2026
8c49d6e
refactor: minor changes to fish IBM utilities and added docs
sy-cui Apr 3, 2026
cad39e1
refactor: replace vtkh5py with localized io functions
sy-cui Apr 3, 2026
ac9aa3c
build: add sopht to pyproject.toml
sy-cui Apr 3, 2026
736df66
doc: README.md for fish swimming case
sy-cui Apr 3, 2026
b954efc
fix: remove references to utils.io module
sy-cui Apr 3, 2026
2ab3509
refactor: fish_swimming.py now serves as an example case with one fish
sy-cui Apr 3, 2026
30c5e6e
feat: github workflow for smoke running fish swimming
sy-cui Apr 3, 2026
96bb745
build: add version tag for sopht
sy-cui Apr 3, 2026
6e58143
fix: add missing brackets
sy-cui Apr 4, 2026
a012012
refactor reduce fish swimming default run time
sy-cui Apr 28, 2026
7f8ea35
fix: remove redundant dependency direction for sopht
sy-cui May 5, 2026
50b8f87
fix: add elastica python build to ci
sy-cui May 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .github/workflows/examples-smoke-run.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
-D ELASTICA_BUILD_BENCHMARKS=OFF \
-D ELASTICA_BUILD_DOCUMENTATION=OFF \
-D ELASTICA_BUILD_EXAMPLES=ON \
-D ELASTICA_BUILD_PYTHON_BINDINGS=OFF
-D ELASTICA_BUILD_PYTHON_BINDINGS=ON

- name: Build example executables
run: |
Expand All @@ -54,6 +54,7 @@ jobs:
example_free_nest \
example_oscillatory_magnetic_field \
example_timoshenko \
PyFishCaseStudy \
--parallel

- name: Run Axial Stretching
Expand Down Expand Up @@ -86,3 +87,14 @@ jobs:
working-directory: build
run: |
./bin/example_timoshenko --n_steps 10

- name: Install Fish Swimming Python dependencies
shell: bash
run: |
python -m pip install build/bin/python/
python -m pip install examples/fish_swimming/

- name: Run Fish Swimming
shell: bash
run: |
python examples/fish_swimming/fish_swimming.py
9 changes: 9 additions & 0 deletions elastica/Utilities/AppSupport/CaseStudyInterface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ namespace elastica {
}
//**************************************************************************

//**************************************************************************
/*!\brief Change the time step to a given value and do one step.
*/
void step_with(::elastica::real_t dt) {
set_dt(dt);
self().step();
}
//**************************************************************************

//@}
//**************************************************************************

Expand Down
2 changes: 2 additions & 0 deletions elastica/Utilities/AppSupport/Python/CaseStudyPybind.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ namespace py_bindings {
.def("run_for_n_iterations", &CaseStudy::run_for_n_iterations,
py::arg("n_iterations"), py::pos_only(),
"Runs the simulator for n additional iterations")
.def("step_with", &CaseStudy::step_with, py::arg("dt"),
"Change the time step to a given value and do one step.")
.def("current_time", &CaseStudy::current_time,
"Gets the current time of the simulation")
.def("current_dt", &CaseStudy::current_dt,
Expand Down
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ add_subdirectory(rod_plane_collision)
add_subdirectory(nest)

add_subdirectory(magnetism)
add_subdirectory(fish_swimming)

# examples
include(ElasticaAddExamples)
Expand Down
8 changes: 8 additions & 0 deletions examples/fish_swimming/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*.vtkhdf
*.pvsm
*.egg-info/
build/
dist/
*.egg
*data*/
*.so
42 changes: 42 additions & 0 deletions examples/fish_swimming/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
add_subdirectory(FishModel)

set(LIBRARY FishCaseStudy)

add_library(${LIBRARY} STATIC ${LIBRARY}.cpp)
target_sources(${LIBRARY} INTERFACE
${LIBRARY}.hpp
)

target_link_libraries(${LIBRARY}
PRIVATE
Block
SystemsCommon
CosseratRods
SystemsCustomization
RigidBody
States
Utilities
Simulator
Systems
Materials
ElasticaFlags
FishModel
)

# So that I can code up as <elastica/CaseStudy> rather than "CaseStudy"
target_include_directories(${LIBRARY} PRIVATE ${CMAKE_SOURCE_DIR})

include(ElasticaCaseStudyHelpers)

add_elastica_case_study(example_elastic_fish
FROM ${LIBRARY}
AS elastica::standalone_executable
)

add_elastica_case_study(Py${LIBRARY}
FROM ${LIBRARY}
AS elastica::python_object
)
#
elastica_python_link_libraries(Py${LIBRARY} PRIVATE Blaze)
elastica_python_add_dependencies(Py${LIBRARY} PyArrays PyCosseratRods PyFishModel)
133 changes: 133 additions & 0 deletions examples/fish_swimming/FishCaseStudy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#include "FishCaseStudy.hpp"

#include <elastica/Simulator/Materials.hpp>
#include <elastica/Utilities/Get.hpp>
#include <elastica/Utilities/Math/Vec3.hpp>

void FishCaseStudy::setup(InputTypes<This> const& input_parameters) {
::elastica::MaterialID rod_material = elastica::create_material(
::elastica::get<density>(input_parameters), 0.24,
::elastica::get<youngs_modulus>(input_parameters),
::elastica::get<youngs_modulus>(input_parameters) /
::elastica::real_t(3.0),
200, 1e-10, 1e-10, 0.1, 0.1);

const ::elastica::Vec3 origin{0.0, 0.0, 0.0};
const ::elastica::real_t base_length{
::elastica::get<length>(input_parameters)};
const std::size_t n_elems = ::elastica::get<n_elements>(input_parameters);
const std::size_t n_fish = ::elastica::get<num_fish>(input_parameters);
std::size_t n_nodes = n_elems + 1UL;

/* Initialize the fishes (actual + virtual) */
using StraightInit =
::elastica::cosserat_rod::StraightCosseratRodWithoutDampingInitializer;
for (std::size_t i = 0; i < n_fish; ++i) {
StraightInit straight_initializer{
StraightInit::NElement{n_elems},
StraightInit::Material{rod_material},
StraightInit::Radius{base_length * 0.01}, // overwritten internally
StraightInit::Length{base_length},
StraightInit::Origin{
::blaze::column(::elastica::get<origins>(input_parameters), i)},
StraightInit::Direction{::elastica::Vec3{1.0, 0.0, 0.0}},
StraightInit::Normal{::elastica::Vec3{0.0, 0.0, 1.0}},
};

elastic_fish.emplace_back(simulator->template emplace_back<RodType>(
straight_initializer.template initialize<RodType>()));
virtual_fish.emplace_back(simulator->template emplace_back<RodType>(
straight_initializer.template initialize<RodType>()));
}

/* Prescribe the virtual fishes' motion */
for (auto& vf : virtual_fish) {
simulator->constrain(vf).at(0UL).with(
::fish::constraint::make_carling_fish_constraint(
vf,
::elastica::get<period>(input_parameters), // period
2 * M_PI / base_length, // wave number
0.0, // phase shift
::elastica::get<period>(input_parameters) // ramp up time
));
}

/* Connect the virtual and actual fish */
using Tag = ::elastica::tags::ShearStretchRigidityMatrix;
real_t const conn_k = ::elastica::get<Tag>(elastic_fish[0].get())(2, 0);
real_t const y_idx = 1;
namespace econ = ::elastica::connections;
auto connection_generator = econ::make_connection(
econ::make_force([=](auto /*time*/, auto& suitor,
std::size_t /*rod_one_index*/, auto& leader,
auto /*rod_two_index*/) {
using ETag = ::elastica::tags::ExternalLoads;
::blaze::row(::elastica::get<ETag>(suitor), y_idx) +=
conn_k * (::blaze::row(::elastica::position(leader), y_idx) -
::blaze::row(::elastica::position(suitor), y_idx));
}),
econ::make_torque([=](auto /*time*/, auto& suitor,
std::size_t /*rod_one_index*/, auto& leader,
auto /*rod_two_index*/) {
using TraitOp =
::elastica::cosserat_rod::DefaultCosseratRodTraits::Operations;
using ITag = ::elastica::tags::InternalTorques;
using ETag = ::elastica::tags::ExternalTorques;

// tau_1 + Q_1 * Q_2^T * m_2 = 0
auto&& tmp1 =
::elastica::get<::elastica::tags::_DummyElementVector>(leader);
auto&& tmp2 =
::elastica::get<::elastica::tags::_DummyElementVector>(suitor);
TraitOp::batch_mattranspvec(tmp1, ::elastica::director(leader),
::elastica::get<ITag>(leader));
TraitOp::batch_matvec(tmp2, ::elastica::director(suitor), tmp1);
::elastica::get<ETag>(suitor) -= tmp2;
}));

using ::elastica::interface::at;
for (std::size_t i = 0; i < n_fish; ++i) {
simulator->connect(elastic_fish[i], at(0UL))
.to(virtual_fish[i], at(0UL))
.with(connection_generator());
}

/* Apply flow forces onto the elastic fish */
namespace efo = ::elastica::forcing;
flow_forces = ::blaze::zero<real_t>(3UL, n_fish * n_nodes);
flow_torques = ::blaze::zero<real_t>(3UL, n_fish * n_elems);
for (std::size_t i = 0; i < n_fish; ++i) {
auto flow_force =
blaze::submatrix(flow_forces, 0UL, i * n_nodes, 3UL, n_nodes);
auto flow_torque =
blaze::submatrix(flow_torques, 0UL, i * n_elems, 3UL, n_elems);
simulator->force(elastic_fish[i])
.at(0UL)
.with(efo::make_forcing(
efo::make_force([=](auto /*time*/, auto& rod_system,
std::size_t /*index*/) {
::elastica::get<::elastica::tags::ExternalLoads>(rod_system) +=
flow_force;
}),
efo::make_torque([=](auto /*time*/, auto& rod_system,
std::size_t /*index*/) {
::elastica::get<::elastica::tags::ExternalTorques>(rod_system) +=
flow_torque;
}))());
}

/* Finalize the simulator*/
simulator->finalize();

/* Set the dt value */
real_t dt =
::elastica::get<dt_scale>(input_parameters) * base_length / n_elems;
set_dt(dt);
}

void FishCaseStudy::step() {
simulator->step(time_stepper, get_current_time(), get_dt(),
get_current_iteration());
}

void FishCaseStudy::run() {}
Loading
Loading