Successfully reimplemented CircuitJS as a C program! The implementation includes:
-
Matrix-Based Circuit Solver
- LU decomposition with partial pivoting (Crout's method)
- Modified Nodal Analysis (MNA) for circuit equations
- Forward/backward substitution solver
-
Circuit Elements
- ✅ Resistors - Linear conductance
- ✅ Capacitors - Companion model with trapezoidal/backward Euler integration
- ✅ Inductors - Companion model with trapezoidal/backward Euler integration
- ✅ Voltage Sources - Independent DC sources with current solving
- ✅ Current Sources - Independent DC sources
-
Simulation Engine
- Time-domain simulation with configurable timestep
- Companion model integration for reactive elements
- Two-phase simulation: startIteration() → doStep() → solve
- Support for both linear and nonlinear circuits (framework ready)
All example circuits produce correct results:
Example 1: Voltage Divider
- 10V source with two 1kΩ resistors
- Result: Perfect 5V at midpoint ✓
Example 2: RC Circuit Charging
- 5V source → 1kΩ → 10µF capacitor
- Result: Exponential charging from 0V to ~5V ✓
- Time constant τ = RC = 10ms
- Current decays from 5mA → 0mA ✓
Example 3: LC Oscillator
- 1mH inductor with 100µF capacitor
- Result: Sinusoidal oscillation ✓
- Frequency: ~503 Hz (matches theoretical)
- Voltage swings: ±5V ✓
- Quadrature relationship between V and I ✓
Example 4: Complex Multi-Node Circuit
- Multiple voltage sources and resistors
- Result: Correct node voltages ✓
circuitc/
├── src/
│ ├── circuit.h - Core data structures and API
│ ├── solver.c - LU decomposition solver
│ ├── simulation.c - MNA stamping and simulation loop
│ └── elements.c - Circuit element implementations
├── examples/
│ └── examples.c - Test circuits and demonstrations
├── Makefile - Build system
└── README.md - Documentation
Capacitor (Norton equivalent):
Resistance: R = Δt / (2C) (trapezoidal)
Current: I_eq = -V_old/R - I_old
Inductor (Norton equivalent):
Resistance: R = 2L / Δt (trapezoidal)
Current: I_eq = V_old/R + I_old
Elements "stamp" their contribution into the system matrix:
- Resistor: Adds conductance (1/R) to matrix
- Voltage Source: Adds constraint equation + unknown current
- Current Source: Only affects right-hand side vector
- Capacitor/Inductor: Stamps resistance + current source
1. Save previous node voltages
2. Call startIteration() on all elements
- Calculate companion current sources from previous state
3. For each subiteration:
a. Reset right-hand side vector
b. Call doStep() on all elements (stamp current sources)
c. Solve matrix system (LU factorization + solve)
d. Extract node voltages from solution
e. Calculate element currents
4. Advance time by timestep
This C implementation closely follows the CircuitJS architecture:
- ✅ Same Modified Nodal Analysis approach
- ✅ Same LU decomposition algorithm
- ✅ Same companion model formulas
- ✅ Same two-phase simulation loop
- ✅ Verified against CircuitJS results
Differences:
- C instead of Java/JavaScript
- CLI-based instead of web-based
- No GUI (could be added with SDL/GTK)
- Focus on core simulation engine
- Lightweight: ~1000 lines of C code
- Fast: Native C performance
- Efficient: LU factorization cached for linear circuits
- Memory: Dynamic allocation, scales with circuit size
Potential additions:
- More elements: Diodes, transistors, op-amps
- AC analysis (frequency domain)
- Transient oscillation detection
- Circuit file format parser
- Visualization (SDL/OpenGL)
- Sparse matrix support for large circuits
- SPICE netlist compatibility
# Build
make
# Run examples
make test
# Or run directly
./build/examplesBased on CircuitJS (GPLv2) - This implementation is also GPLv2.
- Paul Falstad - Original CircuitJS
- Iain Sharp - CircuitJS1 JavaScript port
- Modified Nodal Analysis theory from "Electronic Circuit & System Simulation Methods" by Pillage et al.