Skip to content

Commit b96a216

Browse files
committed
Implementing SAV bound
1 parent 251ea77 commit b96a216

4 files changed

Lines changed: 198 additions & 132 deletions

File tree

python/base_model.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import numpy as np
22

3+
34
class Model():
45
"""General Model class to pass to the SAVSolver.
56
"""
6-
def __init__(self, N = 10):
7+
8+
def __init__(self, N=10):
79
# Number of dofs
810
self.N = N
911
# Number of inputs
@@ -22,9 +24,9 @@ def __init__(self, N = 10):
2224
self.Enl = lambda q: (0.25 * np.sum(q**4)) * 1
2325
self.Fnl = lambda q: (q**3) * 1
2426
# Both functions are called at the same time in the solver,
25-
# in some cases it is then computationally interesting
27+
# in some cases it is then computationally interesting
2628
# to compute both in the same function.
2729
self.EandFnl = lambda q: (self.Enl(q), self.Fnl(q))
2830

2931
def setting(self):
30-
return {"Name": self.__class__.__name__, "N": self.N}
32+
return {"Name": self.__class__.__name__, "N": self.N}

python/plot_drift_JAES.py

Lines changed: 62 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
Generates figures of section "to drift or not to drift".
2222
"""
2323

24-
#%%
24+
# %%
2525
# System description
2626

2727
# Physical parameters
@@ -37,30 +37,32 @@
3737
T_60_1000 = 3
3838

3939
# Deduce missing physical parameters
40-
StringParams["T"], StringParams["l0"] = get_T_and_l0_from_f0_beta(f0, beta, StringParams)
41-
StringParams["eta_0"], StringParams["eta_1"] = get_etas_from_decays(T_60_0, T_60_1000, StringParams)
40+
StringParams["T"], StringParams["l0"] = get_T_and_l0_from_f0_beta(
41+
f0, beta, StringParams)
42+
StringParams["eta_0"], StringParams["eta_1"] = get_etas_from_decays(
43+
T_60_0, T_60_1000, StringParams)
4244

4345
print(StringParams)
4446

4547

4648
model = FD_string_model(44100, **StringParams)
4749

48-
modes = ["KC", "GE", "GE4"] # Nonlinear modes
50+
modes = ["KC", "GE", "GE4"] # Nonlinear modes
4951

50-
#%%
52+
# %%
5153
# Simulation parameters
5254
sr = 44100
5355
duration = 10
5456
kappa = 0.9
5557
lambda0s = [0, 1000]
56-
OF = 2 # Over-sampling factor for reference
58+
OF = 2 # Over-sampling factor for reference
5759

5860
# Deduce discretization from stability condition
5961
dt = 1 / sr
60-
model.recompute_stability(sr, kappa = kappa)
62+
model.recompute_stability(sr, kappa=kappa)
6163

6264

63-
#%%
65+
# %%
6466
# Initial conditions and excitation
6567

6668
# External force (applied at the middle of the string)
@@ -69,51 +71,64 @@ def Fext(t):
6971
width = 2e-3
7072
period = 500 * width
7173
out = np.zeros(1)
72-
out[0] = Amp * np.sin(np.pi * t / width) * (t%period < width)
74+
out[0] = Amp * np.sin(np.pi * t / width) * (t % period < width)
7375
return out
76+
77+
7478
q0 = np.zeros(model.N)
7579
u0 = np.zeros(model.N)
7680

7781

78-
#%% Run simulations and plot results
79-
fig, axs = plt.subplots(1 + 2*len(lambda0s), 1, figsize=set_size("JAES", height_ratio=0.6), sharex=True)
82+
# %% Run simulations and plot results
83+
fig, axs = plt.subplots(1 + 2*len(lambda0s), 1,
84+
figsize=set_size("JAES", height_ratio=0.6), sharex=True)
8085
linestyles = [":", "--", "-."]
8186
for i, lambda0 in enumerate(lambda0s):
8287

83-
for j, mode in enumerate(modes):
84-
model.NL_type = mode
85-
# Compute SAV solution
86-
solver = SAVSolver(model, sr, lambda0)
87-
88-
storage = STATE_STORAGE_CONFIG
89-
storage["Drift"] = True
90-
storage["q_idx"] = np.array([model.N//2 + 1])
91-
storage["p_idx"] = None
92-
93-
solver.integrate(q0, u0, Fext, duration, ConstantRmid=True, plotter_config=NO_PLOTTER_CONFIG, storage_config=storage)
94-
solver.storage.write(os.path.join(result_folder, f"{mode}/sr{sr}_lambda{lambda0}.h5"))
95-
96-
f0, _, _ = librosa.pyin(solver.storage.q[:, 0], fmin = 40, fmax = 200, sr = 44100, frame_length = 2048 * 4)
97-
write(os.path.join(result_folder, f"{mode}/sr{sr}_lambda{lambda0}.wav"), sr, solver.storage.q[:, 0] / np.max(np.abs(solver.storage.q[:, 0])))
98-
99-
if mode==modes[0] and i==0:
100-
axs[0].plot(solver.storage.t, [Fext(t) for t in solver.storage.t], color = "black", ls = linestyles[j])
101-
axs[0].set_ylabel(r"$f_{in}$ [N]")
102-
axs[2 * i+1].plot(np.linspace(0, duration, len(f0)), f0, label = mode, ls = linestyles[j])
103-
# Here, we divide espilon by the max observed nonlinear energy to get a relative measure
104-
print(solver.maxEnl)
105-
axs[2 * i+2].semilogy(solver.storage.t, np.abs(solver.storage.epsilon / solver.maxEnl), label = mode)
106-
107-
axs[2*i+1].set_ylabel(r"$f_0$ [Hz]")
108-
axs[2*i+1].set_ylim(80, 110)
109-
axs[2*i+2].set_ylabel(r"$\vert\epsilon_{rel}\vert$")
110-
axs[2*i+2].set_ylim([1e-4, 1.5e3])
111-
axs[2*i+2].set_yticks([1e-4, 1e-1, 1e2])
112-
axs[2*i+2].set_yticklabels([1e-4, 1e-1, 1e2])
113-
axs[2*i+1].text(0.8, 0.6, fr"$\lambda_0 = {lambda0} s^{-1}$", transform = axs[2*i+1].transAxes, color="red", bbox=dict(facecolor='white', edgecolor='black', boxstyle='round'))
114-
axs[2*i+2].text(0.8, 0.6, fr"$\lambda_0 = {lambda0} s^{-1}$", transform = axs[2*i+2].transAxes, color="red", bbox=dict(facecolor='white', edgecolor='black', boxstyle='round'))
115-
116-
axs[1].legend(loc = "lower center", frameon = True, fancybox = True, bbox_to_anchor = (0.5, 2.1), ncol=3)
88+
for j, mode in enumerate(modes):
89+
model.NL_type = mode
90+
# Compute SAV solution
91+
solver = SAVSolver(model, sr, lambda0)
92+
93+
storage = STATE_STORAGE_CONFIG
94+
storage["Drift"] = True
95+
storage["q_idx"] = np.array([model.N//2 + 1])
96+
storage["p_idx"] = None
97+
98+
solver.integrate(q0, u0, Fext, duration, ConstantRmid=True,
99+
plotter_config=NO_PLOTTER_CONFIG, storage_config=storage, BoundG=True)
100+
solver.storage.write(os.path.join(
101+
result_folder, f"{mode}/sr{sr}_lambda{lambda0}.h5"))
102+
103+
f0, _, _ = librosa.pyin(
104+
solver.storage.q[:, 0], fmin=40, fmax=200, sr=44100, frame_length=2048 * 4)
105+
write(os.path.join(result_folder, f"{mode}/sr{sr}_lambda{lambda0}.wav"),
106+
sr, solver.storage.q[:, 0] / np.max(np.abs(solver.storage.q[:, 0])))
107+
108+
if mode == modes[0] and i == 0:
109+
axs[0].plot(solver.storage.t, [Fext(t)
110+
for t in solver.storage.t], color="black", ls=linestyles[j])
111+
axs[0].set_ylabel(r"$f_{in}$ [N]")
112+
axs[2 * i+1].plot(np.linspace(0, duration, len(f0)),
113+
f0, label=mode, ls=linestyles[j])
114+
# Here, we divide espilon by the max observed nonlinear energy to get a relative measure
115+
print(solver.maxEnl)
116+
axs[2 * i+2].semilogy(solver.storage.t,
117+
np.abs(solver.storage.epsilon / solver.maxEnl), label=mode)
118+
119+
axs[2*i+1].set_ylabel(r"$f_0$ [Hz]")
120+
axs[2*i+1].set_ylim(80, 110)
121+
axs[2*i+2].set_ylabel(r"$\vert\epsilon_{rel}\vert$")
122+
axs[2*i+2].set_ylim([1e-4, 1.5e3])
123+
axs[2*i+2].set_yticks([1e-4, 1e-1, 1e2])
124+
axs[2*i+2].set_yticklabels([1e-4, 1e-1, 1e2])
125+
axs[2*i+1].text(0.8, 0.6, fr"$\lambda_0 = {lambda0} s^{-1}$", transform=axs[2*i+1].transAxes,
126+
color="red", bbox=dict(facecolor='white', edgecolor='black', boxstyle='round'))
127+
axs[2*i+2].text(0.8, 0.6, fr"$\lambda_0 = {lambda0} s^{-1}$", transform=axs[2*i+2].transAxes,
128+
color="red", bbox=dict(facecolor='white', edgecolor='black', boxstyle='round'))
129+
130+
axs[1].legend(loc="lower center", frameon=True, fancybox=True,
131+
bbox_to_anchor=(0.5, 2.1), ncol=3)
117132
axs[4].set_xlim(0, duration)
118133
axs[4].set_ylim(1e-8, 10)
119134
axs[4].set_xlabel(r"Time [s]")
@@ -124,4 +139,5 @@ def Fext(t):
124139
fig.align_ylabels(axs)
125140
fig.subplots_adjust(hspace=0.1, wspace=0.4)
126141
# Save figure
127-
fig.savefig(os.path.join(result_folder, f"test_drift_nl_force.pdf"), bbox_inches='tight')
142+
fig.savefig(os.path.join(result_folder, f"test_drift_nl_force.pdf"),
143+
bbox_inches='tight')

0 commit comments

Comments
 (0)