Skip to content

Commit 6171705

Browse files
authored
Merge branch 'update-v1' into elasticapp-integration
2 parents e21b5e4 + ad02dfc commit 6171705

File tree

8 files changed

+57
-188
lines changed

8 files changed

+57
-188
lines changed

.pre-commit-config.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ repos:
1010
- id: trailing-whitespace
1111
- id: check-json
1212
- id: check-yaml
13+
- id: check-toml
1314
- id: end-of-file-fixer
1415
exclude: LICENSE
16+
- id: check-added-large-files
17+
- id: mixed-line-ending
1518

1619
- repo: local
1720
hooks:

elastica/modules/base_system.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
)
1919

2020
import numpy as np
21-
import warnings
2221
from itertools import chain
2322

2423
from collections import defaultdict
@@ -129,13 +128,6 @@ def _check_type(self, sys_to_be_added: Any) -> bool:
129128
f"The system {sys_to_be_added.__class__} requires the following modules:\n"
130129
f"{sys_to_be_added.REQUISITE_MODULES}\n"
131130
)
132-
if id(sys_to_be_added) in [id(system) for system in self.__systems]:
133-
# Warning for duplicate system instance
134-
warnings.warn(
135-
f"System {sys_to_be_added.__class__} is already in the system collection.\n"
136-
"Adding multiple instance is technically allowed, but it is not recommended.",
137-
UserWarning,
138-
)
139131
return True
140132

141133
def __len__(self) -> int:

elastica/rod/cosserat_rod.py

Lines changed: 0 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
_average,
2424
)
2525
from .factory_function import allocate
26-
from .knot_theory import KnotTheory
2726

2827
position_difference_kernel = _difference
2928
position_average = _average
@@ -627,75 +626,6 @@ def zeroed_out_external_forces_and_torques(self, time: np.float64) -> None:
627626
self.external_forces, self.external_torques
628627
)
629628

630-
def compute_translational_energy(self) -> NDArray[np.float64]:
631-
"""
632-
Compute total translational energy of the rod at the instance.
633-
"""
634-
return (
635-
0.5
636-
* (
637-
self.mass
638-
* np.einsum(
639-
"ij, ij-> j", self.velocity_collection, self.velocity_collection
640-
)
641-
).sum()
642-
)
643-
644-
def compute_rotational_energy(self) -> NDArray[np.float64]:
645-
"""
646-
Compute total rotational energy of the rod at the instance.
647-
"""
648-
J_omega_upon_e = (
649-
_batch_matvec(self.mass_second_moment_of_inertia, self.omega_collection)
650-
/ self.dilatation
651-
)
652-
return 0.5 * np.einsum("ik,ik->k", self.omega_collection, J_omega_upon_e).sum()
653-
654-
def compute_velocity_center_of_mass(self) -> NDArray[np.float64]:
655-
"""
656-
Compute velocity center of mass of the rod at the instance.
657-
"""
658-
mass_times_velocity = np.einsum("j,ij->ij", self.mass, self.velocity_collection)
659-
sum_mass_times_velocity = np.einsum("ij->i", mass_times_velocity)
660-
661-
return sum_mass_times_velocity / self.mass.sum()
662-
663-
def compute_position_center_of_mass(self) -> NDArray[np.float64]:
664-
"""
665-
Compute position center of mass of the rod at the instance.
666-
"""
667-
mass_times_position = np.einsum("j,ij->ij", self.mass, self.position_collection)
668-
sum_mass_times_position = np.einsum("ij->i", mass_times_position)
669-
670-
return sum_mass_times_position / self.mass.sum()
671-
672-
def compute_bending_energy(self) -> NDArray[np.float64]:
673-
"""
674-
Compute total bending energy of the rod at the instance.
675-
"""
676-
kappa_diff = self.kappa - self.rest_kappa
677-
bending_internal_torques = _batch_matvec(self.bend_matrix, kappa_diff)
678-
679-
return (
680-
0.5
681-
* (
682-
_batch_dot(kappa_diff, bending_internal_torques)
683-
* self.rest_voronoi_lengths
684-
).sum()
685-
)
686-
687-
def compute_shear_energy(self) -> NDArray[np.float64]:
688-
"""
689-
Compute total shear energy of the rod at the instance.
690-
"""
691-
sigma_diff = self.sigma - self.rest_sigma
692-
shear_internal_forces = _batch_matvec(self.shear_matrix, sigma_diff)
693-
694-
return (
695-
0.5
696-
* (_batch_dot(sigma_diff, shear_internal_forces) * self.rest_lengths).sum()
697-
)
698-
699629

700630
# Below is the numba-implementation of Cosserat Rod equations. They don't need to be visible by users.
701631

elastica/timestepper/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def extend_stepper_interface(
2222
SteppersOperatorsType,
2323
]:
2424
try:
25-
stepper_methods: SteppersOperatorsType = stepper.steps_and_prefactors
25+
stepper_methods: SteppersOperatorsType = stepper.steps_and_prefactors # type: ignore
2626
do_step_method: Callable = stepper.do_step # type: ignore[attr-defined]
2727
except AttributeError as e:
2828
raise NotImplementedError(f"{stepper} stepper is not supported.") from e

elastica/timestepper/protocol.py

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
from typing import Protocol
44

55
from elastica.typing import (
6-
SteppersOperatorsType,
7-
StepType,
6+
SystemType,
87
SystemCollectionType,
98
)
109
from elastica.systems.protocol import SymplecticSystemProtocol
@@ -15,15 +14,6 @@
1514
class StepperProtocol(Protocol):
1615
"""Protocol for all time-steppers"""
1716

18-
steps_and_prefactors: SteppersOperatorsType
19-
20-
def __init__(self) -> None: ...
21-
22-
@property
23-
def n_stages(self) -> int: ...
24-
25-
def step_methods(self) -> SteppersOperatorsType: ...
26-
2717
def step(
2818
self,
2919
SystemCollection: SystemCollectionType,
@@ -32,13 +22,5 @@ def step(
3222
) -> np.float64: ...
3323

3424
def step_single_instance(
35-
self, System: SymplecticSystemProtocol, time: np.float64, dt: np.float64
25+
self, System: SystemType, time: np.float64, dt: np.float64
3626
) -> np.float64: ...
37-
38-
39-
class SymplecticStepperProtocol(StepperProtocol, Protocol):
40-
"""symplectic stepper protocol."""
41-
42-
def get_steps(self) -> list[StepType]: ...
43-
44-
def get_prefactors(self) -> list[StepType]: ...

elastica/timestepper/symplectic_steppers.py

Lines changed: 48 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
__doc__ = """Symplectic time steppers and concepts for integrating the kinematic and dynamic equations of rod-like objects. """
22

3-
from typing import TYPE_CHECKING, Any
3+
from typing import TYPE_CHECKING, Any, Callable
44

55
from itertools import zip_longest
66

77
from elastica.typing import (
88
SystemCollectionType,
9+
SystemType,
910
StepType,
1011
SteppersOperatorsType,
1112
)
1213

1314
import numpy as np
1415

1516
from elastica.systems.protocol import SymplecticSystemProtocol
16-
from .protocol import SymplecticStepperProtocol
17+
from .protocol import StepperProtocol
1718

1819
"""
1920
Developer Note
@@ -25,10 +26,13 @@
2526

2627

2728
class SymplecticStepperMixin:
28-
def __init__(self: SymplecticStepperProtocol):
29+
get_steps: Callable[[], list[StepType]]
30+
get_prefactors: Callable[[], list[StepType]]
31+
32+
def __init__(self) -> None:
2933
self.steps_and_prefactors: SteppersOperatorsType = self.step_methods()
3034

31-
def step_methods(self: SymplecticStepperProtocol) -> SteppersOperatorsType:
35+
def step_methods(self) -> SteppersOperatorsType:
3236
# Let the total number of steps for the Symplectic method
3337
# be (2*n + 1) (for time-symmetry).
3438
_steps: list[StepType] = self.get_steps()
@@ -56,32 +60,14 @@ def no_operation(*args: Any) -> None:
5660
)
5761

5862
@property
59-
def n_stages(self: SymplecticStepperProtocol) -> int:
63+
def n_stages(self) -> int:
6064
return len(self.steps_and_prefactors)
6165

6266
def step(
63-
self: SymplecticStepperProtocol,
67+
self,
6468
SystemCollection: SystemCollectionType,
6569
time: np.float64 | float,
6670
dt: np.float64 | float,
67-
) -> np.float64:
68-
return SymplecticStepperMixin.do_step(
69-
self,
70-
self.steps_and_prefactors,
71-
SystemCollection,
72-
np.float64(time),
73-
np.float64(dt),
74-
)
75-
76-
# TODO: Merge with .step method in the future.
77-
# DEPRECATED: Use .step instead.
78-
@staticmethod
79-
def do_step(
80-
TimeStepper: SymplecticStepperProtocol,
81-
steps_and_prefactors: SteppersOperatorsType,
82-
SystemCollection: SystemCollectionType,
83-
time: np.float64,
84-
dt: np.float64,
8571
) -> np.float64:
8672
"""
8773
Function for doing symplectic stepper over the user defined rods (system).
@@ -92,53 +78,73 @@ def do_step(
9278
The time after the integration step.
9379
9480
"""
95-
for kin_prefactor, kin_step, dyn_step in steps_and_prefactors[:-1]:
81+
simulation_time = np.float64(time)
82+
simulation_dt = np.float64(dt)
9683

84+
for kin_prefactor, kin_step, dyn_step in self.steps_and_prefactors[:-1]:
9785
for system in SystemCollection.final_systems():
98-
kin_step(system, time, dt)
86+
kin_step(system, simulation_time, simulation_dt)
9987

100-
time += kin_prefactor(dt)
88+
simulation_time += kin_prefactor(simulation_dt)
10189

10290
# Constrain only values
103-
SystemCollection.constrain_values(time)
91+
SystemCollection.constrain_values(simulation_time)
10492

10593
# We need internal forces and torques because they are used by interaction module.
10694
for system in SystemCollection.final_systems():
107-
system.compute_internal_forces_and_torques(time)
95+
system.compute_internal_forces_and_torques(simulation_time)
10896

10997
# Add external forces, controls etc.
110-
SystemCollection.synchronize(time)
98+
SystemCollection.synchronize(simulation_time)
11199

112100
for system in SystemCollection.final_systems():
113-
dyn_step(system, time, dt)
101+
dyn_step(system, simulation_time, simulation_dt)
114102

115103
# Constrain only rates
116-
SystemCollection.constrain_rates(time)
104+
SystemCollection.constrain_rates(simulation_time)
117105

118106
# Peel the last kinematic step and prefactor alone
119-
last_kin_prefactor = steps_and_prefactors[-1][0]
120-
last_kin_step = steps_and_prefactors[-1][1]
107+
last_kin_prefactor = self.steps_and_prefactors[-1][0]
108+
last_kin_step = self.steps_and_prefactors[-1][1]
121109

122110
for system in SystemCollection.final_systems():
123-
last_kin_step(system, time, dt)
124-
time += last_kin_prefactor(dt)
125-
SystemCollection.constrain_values(time)
111+
last_kin_step(system, simulation_time, simulation_dt)
112+
simulation_time += last_kin_prefactor(simulation_dt)
113+
SystemCollection.constrain_values(simulation_time)
126114

127115
# Call back function, will call the user defined call back functions and store data
128-
SystemCollection.apply_callbacks(time, round(time / dt))
116+
SystemCollection.apply_callbacks(
117+
simulation_time, round(simulation_time / simulation_dt)
118+
)
129119

130120
# Zero out the external forces and torques
131121
for system in SystemCollection.final_systems():
132-
system.zeroed_out_external_forces_and_torques(time)
122+
system.zeroed_out_external_forces_and_torques(simulation_time)
123+
124+
return simulation_time
125+
126+
@staticmethod
127+
def do_step(
128+
TimeStepper: StepperProtocol,
129+
steps_and_prefactors: SteppersOperatorsType,
130+
SystemCollection: SystemCollectionType,
131+
time: np.float64,
132+
dt: np.float64,
133+
) -> np.float64: # pragma: no cover
134+
from warning import warn
133135

134-
return time
136+
warn("This method is deprecated. Use the instance method .step instead.")
137+
return Timestepper.step(SystemCollection, time, dt) # type: ignore
135138

136139
def step_single_instance(
137-
self: SymplecticStepperProtocol,
138-
System: SymplecticSystemProtocol,
140+
self,
141+
System: SystemType,
139142
time: np.float64,
140143
dt: np.float64,
141144
) -> np.float64:
145+
"""
146+
(The function is used for single system instance, mainly for testing purposes.)
147+
"""
142148

143149
for kin_prefactor, kin_step, dyn_step in self.steps_and_prefactors[:-1]:
144150
kin_step(System, time, dt)

elastica/typing.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@
2424
SystemProtocol,
2525
SymplecticSystemProtocol,
2626
)
27-
from .timestepper.protocol import (
28-
StepperProtocol,
29-
SymplecticStepperProtocol,
30-
)
27+
from .timestepper.protocol import StepperProtocol
3128
from .memory_block.protocol import BlockSystemProtocol
3229

3330
else:
@@ -40,7 +37,6 @@
4037
StaticSystemProtocol = "StaticSystemProtocol"
4138
SymplecticSystemProtocol = "SymplecticSystemProtocol"
4239
StepperProtocol = "StepperProtocol"
43-
SymplecticStepperProtocol = "SymplecticStepperProtocol"
4440
BlockSystemProtocol = "BlockSystemProtocol"
4541

4642

0 commit comments

Comments
 (0)