Source code for vivyd.excitation.excitation_group

from ..core import is_taichi_used, ti_or_fallback as ti, TaichiCompatible
from ..typing import arrf64
from .excitation import Excitation

from numpy import asarray, zeros


[docs] @ti.data_oriented class ExcitationGroup(TaichiCompatible): """ A class for representing a group of excitations. More importantly, this class provides a handle comprising all the excitations in the group, which can then be passed to the solver in order to have better control of the model's excitations. Parameters ---------- *excitations : Excitation One or more `Excitation` objects representing the group of excitations. """ def __init__(self, *excitations: Excitation): self._excitations = tuple(excitations) self._n = len(self._excitations)
[docs] def __call__(self, t: float) -> arrf64: """Shorthand for :meth:`interpolate`.""" return self.interpolate(t)
[docs] def interpolate(self, t: float) -> arrf64: """ Interpolate the excitations in the group at a given time `t`. Parameters ---------- t : float The time at which to interpolate the excitations. Returns ------- arrf64 The interpolated excitations at time `t`. Each element in the array is the interpolated value of the corresponding excitation in the group. """ if is_taichi_used(): _call = self._call_taichi else: _call = self._call_python return _call(t)
def _call_python(self, t: float) -> arrf64: return asarray([excitation(t) for excitation in self._excitations]) def _call_taichi(self, t: float) -> arrf64: out = zeros(self._n, dtype=float) self._call_taichi_kernel(t, out) return out @ti.func def _call_taichi_func(self, t: float): n = ti.static(self._n) out = ti.Vector.zero(ti.f64, n) for i in ti.static(range(n)): out[i] = self._excitations[i]._call_taichi_func(t) return out @ti.kernel def _call_taichi_kernel( self, t: float, out: ti.types.ndarray(dtype=ti.f64, ndim=1) # type: ignore ): out_ = self._call_taichi_func(t) for i in range(ti.static(self._n)): out[i] = out_[i] @property def handle(self): """Get the handle for this excitation group, which can be passed to the solver.""" return self._call_taichi_func if is_taichi_used() else self._call_python