FFT and harmonic balance#
HBMEquation: Harmonic balance for nonautonomous ODEs#
- class skhippr.cycles.hbm.HBMEquation(ode: AbstractODE, omega: float, fourier: Fourier, initial_guess: ndarray = None, period_k: float = 1, stability_method: AbstractStabilityHBM = None)#
HBMEquationis a subclass ofAbstractEquationwhich encodes the harmonic balance equations to find a periodic solution of a non-autonomousAbstractODEwith periodic excitation.This class computes a nonlinear harmonic balance residual in the frequency domain using a
Fourierobject. The resulting nonlinear harmonic balance equations in the frequency domain are then solved using the methods of the parentNewtonProblemclass.As the
HBMEquationis a subclass ofAbstractCycleEquation, attribute calls and updates are delegated to the underlyingAbstractODEwhenever applicable.Attributes:
ode:AbstractODEobject representing the non-autonomous ODE of which a periodic solution is sought.omega: Frequency of the system forcing.Fourierobject used to perform the FFT.X: Vector of Fourier coefficients of the periodic solution.period_k: The period time of the sought-after periodic solution isperiod_ktimes the forcing period given byomega.stability_method: The stability method.
- x_time() ndarray#
Return the time series of the solution at the FFT sample points as a
self.ode.n_dofxself.fourier.L_DFTarray.
- aft(X=None) ndarray#
Compute the HBM residual and its derivatives using the AFT (Alternating Frequency/Time) method.
- Parameters:
X (np.ndarray, optional) – State vector in the frequency domain. If None, uses self.X.
- Returns:
R – Residual vector in the frequency domain.
- Return type:
np.ndarray
- residual_function()#
Returns
self.aft(self.X)as the residual function of the HBM equations.
- closed_form_derivative(variable)#
Return the closed-form derivative of the residual function w.r.t. the variable. by Fourier transforming the corresponding derivatives in the time domain,evaluated at the samples.
- hill_matrix(real_formulation: bool = None) ndarray#
Return the Hill matrix, which is the derivative of the HBM equations w.r.t.
X.- Parameters:
real_formulation (bool, optional) – If True, returns the Hill matrix in real formulation, otherwise in complex formulation. If None, uses the value of
self.fourier.real_formulation.
- ode_coeffs() ndarray#
Extract and return the Fourier coefficients of the Jacobian matrix df/dx(x(t)) from the Hill matrix.
Note
In the real formulation, coefficients are computed according to Bayer et al. 2024, Eq.s (82)-(83) (see references), with the first N cos / sin coefficients appearing in the first row block.
Otherwise, the most centered coefficients are taken from the central row block .
- Returns:
A 3D array of shape (n_dof, n_dof, 2*N_HBM+1) containing the Fourier coefficients of df/dx(x(t))
- Return type:
np.ndarray
References
Bayer et al. 2024, https://doi.org/10.1016/j.ijnonlinmec.2024.104894
- ode_samples(fourier=None) ndarray#
Generate samples of the Jacobian matrix J(t) in time from the Hill matrix.
- Parameters:
fourier (Optional) – An object providing the matrix_inv_DFT method. If None, uses self.fourier.
- Returns:
The df/dx(x(t)) at the FFT samples.
- Return type:
np.ndarray
- stability_criterion(eigenvalues) bool#
The stability criterion for the HBM equations is that all Floquet multipliers must have a modulus less than 1. If the ode is autonomous, the Floquet multiplier corresponding to the phase freedom is removed from the stability criterion.
- exponential_decay_parameters(threshold=5e-15)#
Estimate the exponential decay of the Fourier coefficients of the Jacobian matrix J(t).
This method computes parameters
aandbsuch that the norm of thek-th Fourier coefficient of df/dx(x(t)) is bounded bymax(threshold, a * exp(-b * |k|)).Note
These decay parameters play a central role in the error bound of Bayer and Leine, 2025 (https://arxiv.org/pdf/2503.21318).
- Parameters:
threshold (float, optional) – The minimum threshold for considering the norm of the coefficients. Defaults to 5e-15.
- Returns:
np.ndarray – an array of shape (
m, 2) where each row contains a pair[a, b]for an exponential envelope which is exact at two Fourier coefficients and upperbounds the others.Warns –
- UserWarning: If the norm of the coefficients does not decay below the threshold within the
available harmonic range (
N_HBM), a warning is issued suggesting to increaseN_HBM.
- error_bound_fundamental_matrix(t: float | ndarray = None, _as=None, bs=None)#
Attempts to compute an error bound for the fundamental solution matrix at specified time(s)
t. For each time instant, the lowest bound produced by a combination of(a, b)is returned.Notes
If both
_asandbsare provided, exponential decay parameters are not computed from the Hill matrix and the given parameters are used directly.If only one of them is provided, all applicable exponential
decay parameter combinations are computed and the ones closest to the provided values are used. * If neither is provided, all possible combinations of decay parameters are considered. At each time instant, the combination of
(a, b)that produces the lowest bound is used.- Parameters:
t (float or np.ndarray, optional) – Time or array of times at which to evaluate the error bound. If None, uses the solution’s period.
_as (array_like, optional) – (Target) parameters for the exponential decay.
bs (array_like, optional) – (Target) parameters for the exponential decay.
- Returns:
E_bound – Array of error bounds evaluated at each time in
t.- Return type:
np.ndarray
HBMSystem: Treating autonomous and nonautonomous ODEs#
- class skhippr.cycles.hbm.HBMSystem(ode, omega, fourier, initial_guess: ndarray = None, period_k: float = 1, stability_method: AbstractStabilityHBM = None, harmo_anchor: int = 1, dof_anchor: int = 0)#
This subclass of
EquationSysteminstantiates aHBMEquationand considers it as the first equation. The Fourier coefficient vectorXis the first unknown.If the underlying ODE is autonomous, the frequency
omegaof the periodic solution is not known in advance and is appended to the unknowns. Correspondingly, aHBMPhaseAnchorequation is appended to the equations.
- class skhippr.cycles.hbm.HBMPhaseAnchor(fourier, X, harmo, dof)#
This class implements an anchor equation for the harmonic balance method (HBM) in autonomous systems to ensure that the phase of a specified degree of freedom and harmonic of the periodic solution does not change during the HBM solution procedure.
- Complex formulation:
exp(i*phi) = X+/X- = const
- Real formulation:
-tan(phi) = c_k/s_k = const
Hereby,
harmoanddofspecify the harmonic and degree of freedom for which the phase is anchored.- residual_function()#
Always returns zero.
- closed_form_derivative(variable)#
Return the anchor as derivative w.r.t
Xand zero otherwise.
Fourier: Fast Fourier transform methods#
- class skhippr.Fourier.Fourier(N_HBM: int, L_DFT: int, n_dof: int, real_formulation: bool = True)#
Methods for (Fast) Fourier Transform (FFT) and related operations in real or complex formulation.
Attributes:
n_dof: Number of states (degrees of freedom) of the considered signals.N_HBM: Largest harmonic to be considered in the Fourier series.L_DFT: Number of samples for the fast Fourier transform (FFT). Must be>= 2 * (N_HBM + 1)to avoid aliasing.real_formulation: Whether Fourier coefficients are returned in real or complex formulation.
Useful methods:
Notes
This class supports both real-valued and complex-valued formulations.
For the complex-valued formulation, Fourier coefficients are represented in increasing frequency order (from
-N_HBMtoN_HBM).For the real-valued formulation, the 0-th Fourier coefficient is stored first, then all cosine coefficients in increasing frequency order, then all sine coefficients in increasing frequency order.
- time_samples(omega: float, periods: float = 1) ndarray#
Generate a uniformly spaced vector of time samples starting at
0withL_DFTsamples per period.If
periodsis integer, the last sample isT*periods-dt.If
periodsis non-integer, it is rounded down to obtain an integer number of samples that are equally spaced at the DFT sampling frequency. The last sample lies in[T*periods-dt, T*periods).
- Parameters:
omega (float) – The angular frequency (in radians per unit time).
periods (float, optional) – Number of periods to sample. Defaults to 1. Can be non-integer.
- Returns:
1-D array of time samples.
- Return type:
np.ndarray
- DFT(x_samp: ndarray) ndarray#
Compute the Fourier coefficient vector of the input signal using
scipy.fft.fft.- Parameters:
x_samp (np.ndarray) – Input signal array of shape (
n_dof, …,L_DFT)- Returns:
Array containing the stacked Fourier coefficients with shape (
n_dof* (2*N_HBM+ 1 , …).- Return type:
np.ndarray
Notes
If
real_formulationisTrue, the real-valued Fourier coefficients are returned; otherwise, the complex-valued Fourier coefficients.
- inv_DFT(X: ndarray) ndarray#
Compute the inverse Discrete Fourier Transform (DFT) of the given Fourier coefficient vector.
This method reconstructs the time-domain samples from the provided Fourier coefficients.
- Parameters:
X (np.ndarray) – Fourier coefficient vector (as generated by
DFT()). First dimension must haven_dof* (2 *N_HBM+ 1) entries. May have more dimensions.- Returns:
Time-domain samples reconstructed from the Fourier coefficients, returned as an array of shape [
n_dof, …,L_DFT].- Return type:
np.ndarray
- matrix_DFT(A: ndarray) ndarray#
Compute the matrix discrete Fourier transform of samples of a square matrix, as required for the HBM Jacobian, using efficient scaling and FFT.
The result of this function is equivalent to
DFT_matrix@A_block@iDFT_matrix, whereA_blockis a block-diagonal matrix formed from the samples ofA, but the computation is carried out efficiently usingscipy.fft.fft.- Parameters:
A (np.ndarray) – Input array of shape (
n_dof,n_dof,L_DFT), collecting samples of the time-periodic matrix.- Returns:
The result of the matrix DFT operation, a square array of length
n_dof* (2 *N_HBM+ 1).- Return type:
np.ndarray
Notes
The
k-th column of the result is computed as the FFT of thek-th column ofA_block @iDFT_matrix.Due to the block-diagonal structure, this is achieved by scaling
A[:, :, l]byiDFT_small[k, l]for eachl.The resulting matrix has block-Toeplitz structure.
- matrix_inv_DFT(A: ndarray) ndarray#
Pseudo-inverse operation of
matrix_DFT()(up to aliasing).- Parameters:
A (np.ndarray) – The result of a matrix DFT operation, a square array of length
n_dof* (2 *N_HBM+ 1) with block-Toeplitz structure.- Returns:
array of shape (
n_dof,n_dof,L_DFT), collecting samples of the corresponding time-periodic matrix.- Return type:
np.ndarray
- derivative_coeffs(X: ndarray, omega: float = 1) ndarray#
Compute the Fourier coefficients of the derivative of a signal which is represented by Fourier coefficients.
- Parameters:
X (np.ndarray) – A 1-D array of shape
n_dof* (2 *N_HBM+ 1), containing the Fourier coefficients of the original signal.omega (float, optional) – The angular frequency to scale the derivative coefficients. Default is 1.
- Returns:
A 1-D array of the same shape as
X, containing the Fourier coefficients of the derivative of the signal.- Return type:
np.ndarray
- differentiate(x_samp: ndarray, omega: float) ndarray#
Compute the the derivative of a periodic signal in the frequency domain.
- Parameters:
x_samp (np.ndarray) – A 2-D array of shape (
n_dof,L_DFT), containing the samples of the original signal.omega (float, optional) – The angular frequency of the signal. Default is 1.
- Returns:
A 1-D array of the same shape as
x_samp, containing the dfferentiated signal.- Return type:
np.ndarray
- __replace__(**changes)#
Return a new instance of the Fourier class with updated attributes.
- Parameters:
**changes (dict) – Keyword arguments (arguments of
Fourier) specifying attribute values to replace in the new instance. If an attribute is not provided inchanges, its value from the current instance is used.- Returns:
A new instance of the Fourier class with the specified changes applied.
- Return type: