Source code for elastica.modules.damping
__doc__ = """
Damping
-------
(added in version 0.3.0)
Provides the damper interface to apply damping
on the rods. (see `dissipation.py`).
"""
from elastica.dissipation import DamperBase
[docs]class Damping:
"""
The Damping class is a module for applying damping
on rod-like objects, the simulator class must be derived from
Damping class.
Attributes
----------
_dampers: list
List of damper classes defined for rod-like objects.
"""
def __init__(self):
self._dampers = []
super(Damping, self).__init__()
self._feature_group_constrain_rates.append(self._dampen_rates)
self._feature_group_finalize.append(self._finalize_dampers)
[docs] def dampen(self, system):
"""
This method applies damping on relevant user-defined
system or rod-like object. You must input the system or rod-like
object that you want to apply damping on.
Parameters
----------
system: object
System is a rod-like object.
Returns
-------
"""
sys_idx = self._get_sys_idx_if_valid(system)
# Create _Damper object, cache it and return to user
_damper = _Damper(sys_idx)
self._dampers.append(_damper)
return _damper
def _finalize_dampers(self):
# From stored _Damping objects, instantiate the dissipation/damping
# inplace : https://stackoverflow.com/a/1208792
self._dampers[:] = [
(damper.id(), damper(self._systems[damper.id()]))
for damper in self._dampers
]
# Sort from lowest id to highest id for potentially better memory access
# _dampers contains list of tuples. First element of tuple is rod number and
# following elements are the type of damping.
# Thus using lambda we iterate over the list of tuples and use rod number (x[0])
# to sort dampers.
self._dampers.sort(key=lambda x: x[0])
def _dampen_rates(self, time, *args, **kwargs):
for sys_id, damper in self._dampers:
damper.dampen_rates(self._systems[sys_id], time, *args, **kwargs)
class _Damper:
"""
Damper module private class
Attributes
----------
_sys_idx: int
_damper_cls: list
*args
Variable length argument list.
**kwargs
Arbitrary keyword arguments.
"""
def __init__(self, sys_idx: int):
"""
Parameters
----------
sys_idx: int
"""
self._sys_idx = sys_idx
self._damper_cls = None
self._args = ()
self._kwargs = {}
def using(self, damper_cls, *args, **kwargs):
"""
This method is a module to set which damper class is used to
enforce damping from user defined rod-like objects.
Parameters
----------
damper_cls : object
User defined damper class.
*args
Variable length argument list
**kwargs
Arbitrary keyword arguments.
Returns
-------
"""
assert issubclass(
damper_cls, DamperBase
), "{} is not a valid damper. Damper must be driven from DamperBase.".format(
damper_cls
)
self._damper_cls = damper_cls
self._args = args
self._kwargs = kwargs
return self
def id(self):
return self._sys_idx
def __call__(self, rod, *args, **kwargs):
"""Constructs a Damper class object after checks
Parameters
----------
args
kwargs
Returns
-------
"""
if not self._damper_cls:
raise RuntimeError(
"No damper provided to dampen rod id {0} at {1},"
"but damping was intended. Did you"
"forget to call the `using` method?".format(self.id(), rod)
)
try:
damper = self._damper_cls(*self._args, _system=rod, **self._kwargs)
return damper
except (TypeError, IndexError):
raise TypeError("Unable to construct damping class.\n")