-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path01_basic_oscillator.cpp
More file actions
128 lines (101 loc) · 5.22 KB
/
01_basic_oscillator.cpp
File metadata and controls
128 lines (101 loc) · 5.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// =============================================================================
// FEEN Tutorial 01: Basic Oscillator
// =============================================================================
// Learn: How to create and simulate a simple resonator
// Concepts: Monostable mode, energy decay, SNR tracking
// =============================================================================
#include <iostream>
#include <iomanip>
#include <feen/resonator.h>
using namespace feen;
int main() {
std::cout << "=== FEEN Tutorial 01: Basic Oscillator ===\n\n";
// -------------------------------------------------------------------------
// Step 1: Configure the resonator
// -------------------------------------------------------------------------
std::cout << "[Step 1] Configuring a 1 kHz resonator...\n";
ResonatorConfig config;
config.name = "my_first_oscillator";
config.frequency_hz = 1000.0; // 1 kHz resonant frequency
config.q_factor = 200.0; // Quality factor (higher = less damping)
config.beta = 1e-4; // Positive beta = monostable mode
std::cout << " Frequency: " << config.frequency_hz << " Hz\n";
std::cout << " Q-factor: " << config.q_factor << "\n";
std::cout << " Mode: Monostable (single stable state)\n\n";
// -------------------------------------------------------------------------
// Step 2: Create the resonator
// -------------------------------------------------------------------------
std::cout << "[Step 2] Creating resonator...\n";
Resonator osc(config);
// Calculate theoretical decay time
double decay_time = config.q_factor / (M_PI * config.frequency_hz);
std::cout << " Expected decay time: " << decay_time * 1000.0 << " ms\n\n";
// -------------------------------------------------------------------------
// Step 3: Inject initial energy
// -------------------------------------------------------------------------
std::cout << "[Step 3] Injecting initial energy...\n";
double initial_amplitude = 1.0;
osc.inject(initial_amplitude);
double E0 = osc.total_energy();
std::cout << " Initial energy: " << std::scientific << E0 << " J\n";
std::cout << " Initial SNR: " << std::fixed << osc.snr() << "\n\n";
// -------------------------------------------------------------------------
// Step 4: Simulate evolution
// -------------------------------------------------------------------------
std::cout << "[Step 4] Simulating 200 ms of evolution...\n\n";
double dt = 1e-6; // 1 microsecond timestep
int steps_per_snapshot = 50000; // Every 50 ms
std::cout << std::setw(10) << "Time (ms)"
<< std::setw(20) << "Energy (J)"
<< std::setw(15) << "Energy (%)"
<< std::setw(15) << "SNR\n";
std::cout << std::string(60, '-') << "\n";
for (int i = 0; i <= 200000; i++) {
osc.tick(dt);
// Print snapshot every 50 ms
if (i % steps_per_snapshot == 0) {
double t_ms = i * dt * 1000.0;
double E = osc.total_energy();
double E_percent = (E / E0) * 100.0;
double snr = osc.snr();
std::cout << std::fixed << std::setprecision(1)
<< std::setw(10) << t_ms
<< std::scientific << std::setprecision(3)
<< std::setw(20) << E
<< std::fixed << std::setprecision(1)
<< std::setw(15) << E_percent
<< std::setprecision(0)
<< std::setw(15) << snr << "\n";
}
}
std::cout << "\n";
// -------------------------------------------------------------------------
// Step 5: Analysis
// -------------------------------------------------------------------------
std::cout << "[Step 5] Analysis...\n";
double final_energy = osc.total_energy();
double energy_ratio = final_energy / E0;
std::cout << " Energy retained: " << std::fixed << std::setprecision(1)
<< (energy_ratio * 100.0) << "%\n";
if (osc.snr() > MIN_READABLE_SNR) {
std::cout << " ✓ Signal still readable (SNR = "
<< std::setprecision(0) << osc.snr() << " > "
<< MIN_READABLE_SNR << ")\n";
} else {
std::cout << " ✗ Signal degraded below readability threshold\n";
}
std::cout << "\n";
// -------------------------------------------------------------------------
// Key Takeaways
// -------------------------------------------------------------------------
std::cout << "=== Key Takeaways ===\n";
std::cout << "• Higher Q-factor = slower energy decay\n";
std::cout << "• Energy decays exponentially as exp(-πf₀t/Q)\n";
std::cout << "• SNR determines how long information remains readable\n";
std::cout << "• Monostable resonators are ideal for analog storage\n";
std::cout << "\n";
std::cout << "Next: Try changing Q-factor and observe decay rate!\n";
std::cout << " Higher Q (500, 1000) → longer memory\n";
std::cout << " Lower Q (50, 100) → faster decay\n";
return 0;
}