-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #161 from SophT-Team/160_elasticapp_interface
160 elasticapp interface
- Loading branch information
Showing
4 changed files
with
128 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from .cosserat_rod_cpp_forcing_grids import ( | ||
CosseratRodCPPElementCentricForcingGrid, | ||
) | ||
from .cosserat_rod_cpp_flow_interaction import CosseratRodCPPFlowInteraction |
60 changes: 60 additions & 0 deletions
60
sopht/simulator/immersed_body/cosserat_rod_cpp/cosserat_rod_cpp_flow_interaction.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import numpy as np | ||
from sopht.simulator.immersed_body import ( | ||
ImmersedBodyForcingGrid, | ||
ImmersedBodyFlowInteraction, | ||
) | ||
from typing import Type, Optional | ||
|
||
|
||
class CosseratRodCPPFlowInteraction(ImmersedBodyFlowInteraction): | ||
"""Class for Elastica++ Cosserat rod flow interaction.""" | ||
|
||
def __init__( | ||
self, | ||
cosserat_rod_simulator, | ||
eul_grid_forcing_field: np.ndarray, | ||
eul_grid_velocity_field: np.ndarray, | ||
virtual_boundary_stiffness_coeff: float, | ||
virtual_boundary_damping_coeff: float, | ||
dx: float, | ||
grid_dim: int, | ||
forcing_grid_cls: Type[ImmersedBodyForcingGrid], | ||
real_t: type = np.float64, | ||
eul_grid_coord_shift: Optional[float] = None, | ||
interp_kernel_width: Optional[float] = None, | ||
enable_eul_grid_forcing_reset: bool = False, | ||
num_threads: int | bool = False, | ||
start_time: float = 0.0, | ||
**forcing_grid_kwargs, | ||
) -> None: | ||
"""Class initialiser.""" | ||
rod, _ = cosserat_rod_simulator.communicate() | ||
n_elems = int(rod.n_elems[0]) | ||
body_flow_forces = np.zeros( | ||
(3, n_elems + 1), | ||
) | ||
body_flow_torques = np.zeros( | ||
(3, n_elems), | ||
) | ||
|
||
forcing_grid_kwargs["cosserat_rod_simulator"] = cosserat_rod_simulator | ||
|
||
# initialising super class | ||
super().__init__( | ||
eul_grid_forcing_field, | ||
eul_grid_velocity_field, | ||
body_flow_forces, | ||
body_flow_torques, | ||
forcing_grid_cls, | ||
virtual_boundary_stiffness_coeff, | ||
virtual_boundary_damping_coeff, | ||
dx, | ||
grid_dim, | ||
real_t, | ||
eul_grid_coord_shift, | ||
interp_kernel_width, | ||
enable_eul_grid_forcing_reset, | ||
num_threads, | ||
start_time, | ||
**forcing_grid_kwargs, | ||
) |
63 changes: 63 additions & 0 deletions
63
sopht/simulator/immersed_body/cosserat_rod_cpp/cosserat_rod_cpp_forcing_grids.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
from elastica.interaction import node_to_element_velocity | ||
import numpy as np | ||
from sopht.simulator.immersed_body import ImmersedBodyForcingGrid | ||
|
||
|
||
class CosseratRodCPPElementCentricForcingGrid(ImmersedBodyForcingGrid): | ||
"""Class for forcing grid at Cosserat rod element centers""" | ||
|
||
def __init__(self, grid_dim: int, cosserat_rod_simulator) -> None: | ||
self.cs = cosserat_rod_simulator | ||
rod, _ = self.cs.communicate() | ||
num_lag_nodes = int(rod.n_elems[0]) | ||
super().__init__(grid_dim, num_lag_nodes) | ||
|
||
# to ensure position/velocity are consistent during initialisation | ||
self.compute_lag_grid_position_field() | ||
self.compute_lag_grid_velocity_field() | ||
|
||
def compute_lag_grid_position_field(self) -> None: | ||
"""Computes location of forcing grid for the Cosserat rod""" | ||
rod, _ = self.cs.communicate() | ||
rod_position_field = np.asarray(rod.get_position()) | ||
self.position_field[...] = ( | ||
rod_position_field[: self.grid_dim, 1:] | ||
+ rod_position_field[: self.grid_dim, :-1] | ||
) / 2.0 | ||
|
||
def compute_lag_grid_velocity_field(self) -> None: | ||
"""Computes velocity of forcing grid points for the Cosserat rod""" | ||
rod, _ = self.cs.communicate() | ||
rod_velocity_field = np.asarray(rod.get_velocity()) | ||
rod_masses = np.asarray(rod.mass) | ||
|
||
self.velocity_field[...] = node_to_element_velocity( | ||
rod_masses, rod_velocity_field | ||
)[: self.grid_dim] | ||
|
||
def transfer_forcing_from_grid_to_body( | ||
self, | ||
body_flow_forces: np.ndarray, | ||
body_flow_torques: np.ndarray, | ||
lag_grid_forcing_field: np.ndarray, | ||
) -> None: | ||
"""Transfer forcing from lagrangian forcing grid to the cosserat rod""" | ||
# negative sign due to Newtons third law | ||
_, body_forces_cpp = self.cs.communicate() | ||
body_forces_cpp = np.asarray(body_forces_cpp) | ||
body_flow_forces[...] = 0.0 | ||
body_flow_forces[: self.grid_dim, 1:] -= 0.5 * lag_grid_forcing_field | ||
body_flow_forces[: self.grid_dim, :-1] -= 0.5 * lag_grid_forcing_field | ||
|
||
body_forces_cpp *= 0.0 | ||
body_forces_cpp[: self.grid_dim, 1:] -= 0.5 * lag_grid_forcing_field | ||
body_forces_cpp[: self.grid_dim, :-1] -= 0.5 * lag_grid_forcing_field | ||
|
||
# torque from grid forcing (don't modify since set = 0 at initialisation) | ||
# because no torques acting on element centers | ||
|
||
def get_maximum_lagrangian_grid_spacing(self) -> float: | ||
"""Get the maximum Lagrangian grid spacing""" | ||
# estimated distance between consecutive elements | ||
rod, _ = self.cs.communicate() | ||
return np.amax(np.asarray(rod.lengths)) |