Upload 3 files
Browse files- README.md +238 -13
- circuit_calculator.py +331 -0
- requirements.txt +4 -0
README.md
CHANGED
|
@@ -1,13 +1,238 @@
|
|
| 1 |
-
---
|
| 2 |
-
title:
|
| 3 |
-
emoji: ⚡
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
-
sdk: gradio
|
| 7 |
-
sdk_version: 5.47.2
|
| 8 |
-
app_file: app.py
|
| 9 |
-
pinned: false
|
| 10 |
-
license: mit
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: DC Circuit Analysis Calculator
|
| 3 |
+
emoji: ⚡
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: green
|
| 6 |
+
sdk: gradio
|
| 7 |
+
sdk_version: 5.47.2
|
| 8 |
+
app_file: app.py
|
| 9 |
+
pinned: false
|
| 10 |
+
license: mit
|
| 11 |
+
short_description: DC circuit analysis calculator with AI explanations
|
| 12 |
+
---
|
| 13 |
+
|
| 14 |
+
# ⚡ DC Circuit Analysis Calculator
|
| 15 |
+
|
| 16 |
+
A deterministic, first-principles electrical engineering calculator for series-parallel DC circuit analysis with AI-powered result explanations. This tool performs electrical engineering calculations and provides detailed, human-readable explanations of the mathematical results.
|
| 17 |
+
|
| 18 |
+
## 🎯 Overview
|
| 19 |
+
|
| 20 |
+
This calculator solves one of the most fundamental problems in electrical engineering: analyzing a series-parallel DC circuit with resistors. The implementation follows classical circuit theory and provides:
|
| 21 |
+
|
| 22 |
+
- **Deterministic calculations** based on first principles
|
| 23 |
+
- **Comprehensive validation** of input parameters
|
| 24 |
+
- **Detailed numerical results** with all intermediate calculations
|
| 25 |
+
- **AI-powered explanations** that contextualize the mathematical results
|
| 26 |
+
- **Power analysis** for component safety and efficiency
|
| 27 |
+
- **Professional-grade interface** built with Gradio
|
| 28 |
+
|
| 29 |
+
## ⚡ Engineering Scope
|
| 30 |
+
|
| 31 |
+
### Problem Definition
|
| 32 |
+
Analyze a DC circuit with the topology: Voltage Source → R1 (series) → [R2, R3] (parallel) → R4 (series)
|
| 33 |
+
|
| 34 |
+
### Assumptions
|
| 35 |
+
- DC steady-state conditions
|
| 36 |
+
- Ideal voltage source (no internal resistance)
|
| 37 |
+
- Ideal resistors (no parasitic effects)
|
| 38 |
+
- Linear circuit behavior
|
| 39 |
+
- No temperature effects on resistance
|
| 40 |
+
|
| 41 |
+
### Input Parameters
|
| 42 |
+
|
| 43 |
+
#### Voltage Source
|
| 44 |
+
- **Voltage (V):** DC voltage source (0.1-1000 V)
|
| 45 |
+
|
| 46 |
+
#### Series Resistors
|
| 47 |
+
- **R1 Resistance (Ω):** First series resistor (1-1,000,000 Ω)
|
| 48 |
+
- **R1 Power Rating (W):** Power rating for R1 (0.01-1000 W)
|
| 49 |
+
- **R4 Resistance (Ω):** Second series resistor (1-1,000,000 Ω)
|
| 50 |
+
- **R4 Power Rating (W):** Power rating for R4 (0.01-1000 W)
|
| 51 |
+
|
| 52 |
+
#### Parallel Resistors
|
| 53 |
+
- **R2 Resistance (Ω):** First parallel resistor (1-1,000,000 Ω)
|
| 54 |
+
- **R2 Power Rating (W):** Power rating for R2 (0.01-1000 W)
|
| 55 |
+
- **R3 Resistance (Ω):** Second parallel resistor (1-1,000,000 Ω)
|
| 56 |
+
- **R3 Power Rating (W):** Power rating for R3 (0.01-1000 W)
|
| 57 |
+
|
| 58 |
+
### Valid Ranges
|
| 59 |
+
All input parameters include comprehensive validation with engineering-reasonable limits to prevent unrealistic calculations.
|
| 60 |
+
|
| 61 |
+
## 🧮 Mathematical Foundation
|
| 62 |
+
|
| 63 |
+
### Equivalent Resistance Calculation
|
| 64 |
+
For the series-parallel circuit:
|
| 65 |
+
|
| 66 |
+
**Series Resistance:**
|
| 67 |
+
```
|
| 68 |
+
R_series = R1 + R4
|
| 69 |
+
```
|
| 70 |
+
|
| 71 |
+
**Parallel Resistance:**
|
| 72 |
+
```
|
| 73 |
+
R_parallel = 1 / (1/R2 + 1/R3)
|
| 74 |
+
```
|
| 75 |
+
|
| 76 |
+
**Total Resistance:**
|
| 77 |
+
```
|
| 78 |
+
R_total = R_series + R_parallel
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
### Current and Voltage Analysis
|
| 82 |
+
**Total Current:**
|
| 83 |
+
```
|
| 84 |
+
I_total = V_source / R_total
|
| 85 |
+
```
|
| 86 |
+
|
| 87 |
+
**Series Resistors:**
|
| 88 |
+
- Current: I_total (same for R1 and R4)
|
| 89 |
+
- Voltage drops: V_R1 = I_total × R1, V_R4 = I_total × R4
|
| 90 |
+
|
| 91 |
+
**Parallel Resistors:**
|
| 92 |
+
- Voltage: V_parallel = I_total × R_parallel
|
| 93 |
+
- Currents: I_R2 = V_parallel / R2, I_R3 = V_parallel / R3
|
| 94 |
+
|
| 95 |
+
### Power Analysis
|
| 96 |
+
**Power Dissipation:**
|
| 97 |
+
```
|
| 98 |
+
P = V² / R = I² × R = V × I
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
**Power Balance:**
|
| 102 |
+
```
|
| 103 |
+
P_total = V_source × I_total = P_R1 + P_R2 + P_R3 + P_R4
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
## 🚀 Usage
|
| 107 |
+
|
| 108 |
+
### Local Development
|
| 109 |
+
|
| 110 |
+
1. **Install dependencies:**
|
| 111 |
+
```bash
|
| 112 |
+
pip install -r requirements.txt
|
| 113 |
+
```
|
| 114 |
+
|
| 115 |
+
2. **Run the application:**
|
| 116 |
+
```bash
|
| 117 |
+
python app.py
|
| 118 |
+
```
|
| 119 |
+
|
| 120 |
+
3. **Open in browser:**
|
| 121 |
+
Navigate to `http://localhost:7860`
|
| 122 |
+
|
| 123 |
+
### Hugging Face Spaces
|
| 124 |
+
|
| 125 |
+
The application is deployed as a public Hugging Face Space and can be accessed directly through the web interface.
|
| 126 |
+
|
| 127 |
+
## 📊 Output Structure
|
| 128 |
+
|
| 129 |
+
The calculator provides two main outputs:
|
| 130 |
+
|
| 131 |
+
### 1. Numerical Results Panel
|
| 132 |
+
- Total resistance, current, and power
|
| 133 |
+
- Individual resistor analysis (voltage, current, power)
|
| 134 |
+
- Series and parallel section analysis
|
| 135 |
+
- Power distribution and efficiency
|
| 136 |
+
|
| 137 |
+
### 2. AI Explanation Panel
|
| 138 |
+
- Human-readable interpretation of results
|
| 139 |
+
- Safety assessment with power rating analysis
|
| 140 |
+
- Engineering recommendations
|
| 141 |
+
- Technical details and methodology notes
|
| 142 |
+
- Design optimization suggestions
|
| 143 |
+
|
| 144 |
+
## 🔍 Example Calculations
|
| 145 |
+
|
| 146 |
+
### Basic Circuit (12V, 100Ω+50Ω series, 200Ω||300Ω parallel)
|
| 147 |
+
- **Total Resistance:** 220.0 Ω
|
| 148 |
+
- **Total Current:** 0.055 A
|
| 149 |
+
- **Total Power:** 0.655 W
|
| 150 |
+
- **All Components Safe:** Yes
|
| 151 |
+
|
| 152 |
+
### High Power Circuit (24V, 50Ω+25Ω series, 100Ω||150Ω parallel)
|
| 153 |
+
- **Total Resistance:** 110.0 Ω
|
| 154 |
+
- **Total Current:** 0.218 A
|
| 155 |
+
- **Total Power:** 5.236 W
|
| 156 |
+
- **All Components Safe:** Yes
|
| 157 |
+
|
| 158 |
+
### Low Voltage Circuit (3.3V, 220Ω+330Ω series, 470Ω||680Ω parallel)
|
| 159 |
+
- **Total Resistance:** 686.2 Ω
|
| 160 |
+
- **Total Current:** 0.005 A
|
| 161 |
+
- **Total Power:** 0.016 W
|
| 162 |
+
- **All Components Safe:** Yes
|
| 163 |
+
|
| 164 |
+
## 🛠️ Technical Implementation
|
| 165 |
+
|
| 166 |
+
### Backend Architecture
|
| 167 |
+
- **`circuit_calculator.py`:** Core calculation engine with deterministic algorithms
|
| 168 |
+
- **`app.py`:** Gradio interface with input validation and result formatting
|
| 169 |
+
- **Structured output:** JSON-based results with comprehensive metadata
|
| 170 |
+
|
| 171 |
+
### Key Features
|
| 172 |
+
- **Input validation:** Comprehensive range checking and error handling
|
| 173 |
+
- **Modular design:** Separate classes for resistors, circuit configuration, and analysis
|
| 174 |
+
- **Error handling:** Graceful failure with detailed error messages
|
| 175 |
+
- **Extensibility:** Easy to add new circuit topologies or components
|
| 176 |
+
|
| 177 |
+
### AI Integration
|
| 178 |
+
The explanation system uses a template-based approach that:
|
| 179 |
+
- Analyzes circuit results
|
| 180 |
+
- Provides contextual engineering interpretation
|
| 181 |
+
- Offers design recommendations
|
| 182 |
+
- Explains safety implications
|
| 183 |
+
- Suggests optimization opportunities
|
| 184 |
+
|
| 185 |
+
## 📚 Educational Value
|
| 186 |
+
|
| 187 |
+
This calculator serves as an excellent learning tool for:
|
| 188 |
+
- **Engineering students** learning circuit analysis
|
| 189 |
+
- **Practicing engineers** needing quick circuit calculations
|
| 190 |
+
- **Educators** demonstrating Ohm's Law and Kirchhoff's Laws
|
| 191 |
+
- **Anyone** interested in understanding electrical circuits
|
| 192 |
+
|
| 193 |
+
## ⚠️ Important Disclaimers
|
| 194 |
+
|
| 195 |
+
1. **Educational Purpose:** This tool is designed for educational and preliminary design purposes only.
|
| 196 |
+
|
| 197 |
+
2. **Professional Use:** For final circuit design, always consult a licensed electrical engineer.
|
| 198 |
+
|
| 199 |
+
3. **Limitations:** The calculator assumes:
|
| 200 |
+
- DC steady-state conditions
|
| 201 |
+
- Ideal components
|
| 202 |
+
- Linear behavior
|
| 203 |
+
- No temperature effects
|
| 204 |
+
|
| 205 |
+
4. **Validation:** While comprehensive input validation is provided, users should verify results for critical applications.
|
| 206 |
+
|
| 207 |
+
## 🔧 Development
|
| 208 |
+
|
| 209 |
+
### Project Structure
|
| 210 |
+
```
|
| 211 |
+
├── app.py # Gradio interface
|
| 212 |
+
├── circuit_calculator.py # Core calculation engine
|
| 213 |
+
├── requirements.txt # Python dependencies
|
| 214 |
+
└── README.md # This documentation
|
| 215 |
+
```
|
| 216 |
+
|
| 217 |
+
### Adding New Features
|
| 218 |
+
The modular design makes it easy to extend:
|
| 219 |
+
- Add new circuit topologies
|
| 220 |
+
- Implement AC analysis
|
| 221 |
+
- Add reactive components (capacitors, inductors)
|
| 222 |
+
- Enhance the explanation system
|
| 223 |
+
|
| 224 |
+
## 📄 License
|
| 225 |
+
|
| 226 |
+
This project is open source and available under the MIT License.
|
| 227 |
+
|
| 228 |
+
## 🤝 Contributing
|
| 229 |
+
|
| 230 |
+
Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests.
|
| 231 |
+
|
| 232 |
+
## 📞 Support
|
| 233 |
+
|
| 234 |
+
For questions or support, please open an issue in the project repository.
|
| 235 |
+
|
| 236 |
+
---
|
| 237 |
+
|
| 238 |
+
**Built with ❤️ for the engineering community**
|
circuit_calculator.py
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
DC Circuit Analysis Calculator
|
| 3 |
+
A deterministic, first-principles electrical engineering calculator for series-parallel resistor circuits.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import math
|
| 7 |
+
from typing import Dict, Any, List, Tuple
|
| 8 |
+
from dataclasses import dataclass
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
@dataclass
|
| 12 |
+
class Resistor:
|
| 13 |
+
"""Represents a resistor in the circuit"""
|
| 14 |
+
name: str
|
| 15 |
+
resistance: float # Ohms
|
| 16 |
+
power_rating: float # Watts (optional)
|
| 17 |
+
|
| 18 |
+
def current_through(self, voltage: float) -> float:
|
| 19 |
+
"""Calculate current through this resistor (Amperes)"""
|
| 20 |
+
return voltage / self.resistance if self.resistance > 0 else 0
|
| 21 |
+
|
| 22 |
+
def power_dissipated(self, voltage: float) -> float:
|
| 23 |
+
"""Calculate power dissipated by this resistor (Watts)"""
|
| 24 |
+
return (voltage ** 2) / self.resistance if self.resistance > 0 else 0
|
| 25 |
+
|
| 26 |
+
def voltage_drop(self, current: float) -> float:
|
| 27 |
+
"""Calculate voltage drop across this resistor (Volts)"""
|
| 28 |
+
return current * self.resistance
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
@dataclass
|
| 32 |
+
class CircuitConfiguration:
|
| 33 |
+
"""Configuration of the circuit topology"""
|
| 34 |
+
voltage_source: float # Volts
|
| 35 |
+
series_resistors: List[Resistor] # Resistors in series
|
| 36 |
+
parallel_branches: List[List[Resistor]] # Each inner list is a parallel branch
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
class DCCircuitAnalyzer:
|
| 40 |
+
"""Deterministic calculator for DC circuit analysis"""
|
| 41 |
+
|
| 42 |
+
def __init__(self, config: CircuitConfiguration):
|
| 43 |
+
self.config = config
|
| 44 |
+
self._validate_inputs()
|
| 45 |
+
|
| 46 |
+
def _validate_inputs(self) -> None:
|
| 47 |
+
"""Validate all input parameters are within reasonable ranges"""
|
| 48 |
+
errors = []
|
| 49 |
+
|
| 50 |
+
# Voltage source validation
|
| 51 |
+
if self.config.voltage_source <= 0 or self.config.voltage_source > 1000:
|
| 52 |
+
errors.append("Voltage source must be between 0 and 1000 V")
|
| 53 |
+
|
| 54 |
+
# Series resistors validation
|
| 55 |
+
for i, resistor in enumerate(self.config.series_resistors):
|
| 56 |
+
if resistor.resistance <= 0 or resistor.resistance > 1000000:
|
| 57 |
+
errors.append(f"Series resistor {i+1} resistance must be between 0 and 1,000,000 Ohms")
|
| 58 |
+
if resistor.power_rating <= 0 or resistor.power_rating > 1000:
|
| 59 |
+
errors.append(f"Series resistor {i+1} power rating must be between 0 and 1000 Watts")
|
| 60 |
+
|
| 61 |
+
# Parallel branches validation
|
| 62 |
+
for branch_idx, branch in enumerate(self.config.parallel_branches):
|
| 63 |
+
if not branch: # Empty branch
|
| 64 |
+
errors.append(f"Parallel branch {branch_idx+1} cannot be empty")
|
| 65 |
+
for resistor_idx, resistor in enumerate(branch):
|
| 66 |
+
if resistor.resistance <= 0 or resistor.resistance > 1000000:
|
| 67 |
+
errors.append(f"Parallel branch {branch_idx+1}, resistor {resistor_idx+1} resistance must be between 0 and 1,000,000 Ohms")
|
| 68 |
+
if resistor.power_rating <= 0 or resistor.power_rating > 1000:
|
| 69 |
+
errors.append(f"Parallel branch {branch_idx+1}, resistor {resistor_idx+1} power rating must be between 0 and 1000 Watts")
|
| 70 |
+
|
| 71 |
+
if errors:
|
| 72 |
+
raise ValueError("Input validation failed:\n" + "\n".join(errors))
|
| 73 |
+
|
| 74 |
+
def calculate_equivalent_resistance(self) -> float:
|
| 75 |
+
"""Calculate total equivalent resistance of the circuit (Ohms)"""
|
| 76 |
+
# Calculate series resistance
|
| 77 |
+
series_resistance = sum(r.resistance for r in self.config.series_resistors)
|
| 78 |
+
|
| 79 |
+
# Calculate parallel branch resistances
|
| 80 |
+
parallel_resistances = []
|
| 81 |
+
for branch in self.config.parallel_branches:
|
| 82 |
+
if branch: # Non-empty branch
|
| 83 |
+
branch_resistance = sum(r.resistance for r in branch)
|
| 84 |
+
parallel_resistances.append(branch_resistance)
|
| 85 |
+
|
| 86 |
+
# Calculate equivalent parallel resistance
|
| 87 |
+
if parallel_resistances:
|
| 88 |
+
parallel_equivalent = 1 / sum(1/r for r in parallel_resistances)
|
| 89 |
+
else:
|
| 90 |
+
parallel_equivalent = 0
|
| 91 |
+
|
| 92 |
+
# Total equivalent resistance
|
| 93 |
+
return series_resistance + parallel_equivalent
|
| 94 |
+
|
| 95 |
+
def calculate_total_current(self) -> float:
|
| 96 |
+
"""Calculate total current from voltage source (Amperes)"""
|
| 97 |
+
total_resistance = self.calculate_equivalent_resistance()
|
| 98 |
+
return self.config.voltage_source / total_resistance if total_resistance > 0 else 0
|
| 99 |
+
|
| 100 |
+
def calculate_series_analysis(self) -> Dict[str, Any]:
|
| 101 |
+
"""Analyze series resistors"""
|
| 102 |
+
total_current = self.calculate_total_current()
|
| 103 |
+
series_analysis = {
|
| 104 |
+
"total_resistance": sum(r.resistance for r in self.config.series_resistors),
|
| 105 |
+
"total_current": total_current,
|
| 106 |
+
"total_power": 0,
|
| 107 |
+
"resistors": []
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
for resistor in self.config.series_resistors:
|
| 111 |
+
voltage_drop = resistor.voltage_drop(total_current)
|
| 112 |
+
power_dissipated = resistor.power_dissipated(voltage_drop)
|
| 113 |
+
series_analysis["total_power"] += power_dissipated
|
| 114 |
+
|
| 115 |
+
series_analysis["resistors"].append({
|
| 116 |
+
"name": resistor.name,
|
| 117 |
+
"resistance": resistor.resistance,
|
| 118 |
+
"voltage_drop": voltage_drop,
|
| 119 |
+
"current": total_current,
|
| 120 |
+
"power_dissipated": power_dissipated,
|
| 121 |
+
"power_utilization": (power_dissipated / resistor.power_rating * 100) if resistor.power_rating > 0 else 0
|
| 122 |
+
})
|
| 123 |
+
|
| 124 |
+
return series_analysis
|
| 125 |
+
|
| 126 |
+
def calculate_parallel_analysis(self) -> Dict[str, Any]:
|
| 127 |
+
"""Analyze parallel branches"""
|
| 128 |
+
# Calculate voltage across parallel section
|
| 129 |
+
series_resistance = sum(r.resistance for r in self.config.series_resistors)
|
| 130 |
+
total_resistance = self.calculate_equivalent_resistance()
|
| 131 |
+
parallel_resistance = total_resistance - series_resistance
|
| 132 |
+
|
| 133 |
+
total_current = self.calculate_total_current()
|
| 134 |
+
voltage_across_parallel = total_current * parallel_resistance
|
| 135 |
+
|
| 136 |
+
parallel_analysis = {
|
| 137 |
+
"voltage_across_parallel": voltage_across_parallel,
|
| 138 |
+
"branches": []
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
for branch_idx, branch in enumerate(self.config.parallel_branches):
|
| 142 |
+
if not branch:
|
| 143 |
+
continue
|
| 144 |
+
|
| 145 |
+
branch_resistance = sum(r.resistance for r in branch)
|
| 146 |
+
branch_current = voltage_across_parallel / branch_resistance if branch_resistance > 0 else 0
|
| 147 |
+
|
| 148 |
+
branch_analysis = {
|
| 149 |
+
"branch_number": branch_idx + 1,
|
| 150 |
+
"total_resistance": branch_resistance,
|
| 151 |
+
"current": branch_current,
|
| 152 |
+
"power": 0,
|
| 153 |
+
"resistors": []
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
for resistor in branch:
|
| 157 |
+
voltage_drop = resistor.voltage_drop(branch_current)
|
| 158 |
+
power_dissipated = resistor.power_dissipated(voltage_drop)
|
| 159 |
+
branch_analysis["power"] += power_dissipated
|
| 160 |
+
|
| 161 |
+
branch_analysis["resistors"].append({
|
| 162 |
+
"name": resistor.name,
|
| 163 |
+
"resistance": resistor.resistance,
|
| 164 |
+
"voltage_drop": voltage_drop,
|
| 165 |
+
"current": branch_current,
|
| 166 |
+
"power_dissipated": power_dissipated,
|
| 167 |
+
"power_utilization": (power_dissipated / resistor.power_rating * 100) if resistor.power_rating > 0 else 0
|
| 168 |
+
})
|
| 169 |
+
|
| 170 |
+
parallel_analysis["branches"].append(branch_analysis)
|
| 171 |
+
|
| 172 |
+
return parallel_analysis
|
| 173 |
+
|
| 174 |
+
def calculate_power_analysis(self) -> Dict[str, Any]:
|
| 175 |
+
"""Calculate total power consumption and efficiency"""
|
| 176 |
+
total_current = self.calculate_total_current()
|
| 177 |
+
total_power = self.config.voltage_source * total_current
|
| 178 |
+
|
| 179 |
+
series_analysis = self.calculate_series_analysis()
|
| 180 |
+
parallel_analysis = self.calculate_parallel_analysis()
|
| 181 |
+
|
| 182 |
+
# Calculate power distribution
|
| 183 |
+
series_power = series_analysis["total_power"]
|
| 184 |
+
parallel_power = sum(branch["power"] for branch in parallel_analysis["branches"])
|
| 185 |
+
|
| 186 |
+
return {
|
| 187 |
+
"total_power_supplied": total_power,
|
| 188 |
+
"total_power_consumed": series_power + parallel_power,
|
| 189 |
+
"series_power": series_power,
|
| 190 |
+
"parallel_power": parallel_power,
|
| 191 |
+
"efficiency_percent": ((series_power + parallel_power) / total_power * 100) if total_power > 0 else 0,
|
| 192 |
+
"power_balance_error": abs(total_power - (series_power + parallel_power))
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
def check_power_ratings(self) -> Dict[str, Any]:
|
| 196 |
+
"""Check if any resistors exceed their power ratings"""
|
| 197 |
+
warnings = []
|
| 198 |
+
critical_issues = []
|
| 199 |
+
|
| 200 |
+
# Check series resistors
|
| 201 |
+
series_analysis = self.calculate_series_analysis()
|
| 202 |
+
for resistor_data in series_analysis["resistors"]:
|
| 203 |
+
if resistor_data["power_utilization"] > 100:
|
| 204 |
+
critical_issues.append(f"Series resistor {resistor_data['name']} exceeds power rating: {resistor_data['power_utilization']:.1f}%")
|
| 205 |
+
elif resistor_data["power_utilization"] > 80:
|
| 206 |
+
warnings.append(f"Series resistor {resistor_data['name']} near power limit: {resistor_data['power_utilization']:.1f}%")
|
| 207 |
+
|
| 208 |
+
# Check parallel resistors
|
| 209 |
+
parallel_analysis = self.calculate_parallel_analysis()
|
| 210 |
+
for branch in parallel_analysis["branches"]:
|
| 211 |
+
for resistor_data in branch["resistors"]:
|
| 212 |
+
if resistor_data["power_utilization"] > 100:
|
| 213 |
+
critical_issues.append(f"Parallel resistor {resistor_data['name']} exceeds power rating: {resistor_data['power_utilization']:.1f}%")
|
| 214 |
+
elif resistor_data["power_utilization"] > 80:
|
| 215 |
+
warnings.append(f"Parallel resistor {resistor_data['name']} near power limit: {resistor_data['power_utilization']:.1f}%")
|
| 216 |
+
|
| 217 |
+
return {
|
| 218 |
+
"warnings": warnings,
|
| 219 |
+
"critical_issues": critical_issues,
|
| 220 |
+
"all_safe": len(critical_issues) == 0,
|
| 221 |
+
"has_warnings": len(warnings) > 0
|
| 222 |
+
}
|
| 223 |
+
|
| 224 |
+
def perform_analysis(self) -> Dict[str, Any]:
|
| 225 |
+
"""Perform complete circuit analysis and return structured results"""
|
| 226 |
+
try:
|
| 227 |
+
# Basic calculations
|
| 228 |
+
total_resistance = self.calculate_equivalent_resistance()
|
| 229 |
+
total_current = self.calculate_total_current()
|
| 230 |
+
|
| 231 |
+
# Detailed analysis
|
| 232 |
+
series_analysis = self.calculate_series_analysis()
|
| 233 |
+
parallel_analysis = self.calculate_parallel_analysis()
|
| 234 |
+
power_analysis = self.calculate_power_analysis()
|
| 235 |
+
safety_check = self.check_power_ratings()
|
| 236 |
+
|
| 237 |
+
# Create structured output
|
| 238 |
+
results = {
|
| 239 |
+
"analysis_type": "DC Series-Parallel Circuit Analysis",
|
| 240 |
+
"status": "success",
|
| 241 |
+
"circuit_configuration": {
|
| 242 |
+
"voltage_source_V": self.config.voltage_source,
|
| 243 |
+
"series_resistors": [
|
| 244 |
+
{"name": r.name, "resistance_ohms": r.resistance, "power_rating_W": r.power_rating}
|
| 245 |
+
for r in self.config.series_resistors
|
| 246 |
+
],
|
| 247 |
+
"parallel_branches": [
|
| 248 |
+
[
|
| 249 |
+
{"name": r.name, "resistance_ohms": r.resistance, "power_rating_W": r.power_rating}
|
| 250 |
+
for r in branch
|
| 251 |
+
]
|
| 252 |
+
for branch in self.config.parallel_branches
|
| 253 |
+
]
|
| 254 |
+
},
|
| 255 |
+
"equivalent_circuit": {
|
| 256 |
+
"total_resistance_ohms": total_resistance,
|
| 257 |
+
"total_current_A": total_current,
|
| 258 |
+
"total_power_W": power_analysis["total_power_supplied"]
|
| 259 |
+
},
|
| 260 |
+
"series_analysis": series_analysis,
|
| 261 |
+
"parallel_analysis": parallel_analysis,
|
| 262 |
+
"power_analysis": power_analysis,
|
| 263 |
+
"safety_analysis": safety_check,
|
| 264 |
+
"validation": {
|
| 265 |
+
"circuit_valid": total_resistance > 0,
|
| 266 |
+
"power_balance_acceptable": power_analysis["power_balance_error"] < 0.001,
|
| 267 |
+
"all_resistors_safe": safety_check["all_safe"]
|
| 268 |
+
}
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
return results
|
| 272 |
+
|
| 273 |
+
except Exception as e:
|
| 274 |
+
return {
|
| 275 |
+
"analysis_type": "DC Series-Parallel Circuit Analysis",
|
| 276 |
+
"status": "error",
|
| 277 |
+
"error_message": str(e),
|
| 278 |
+
"circuit_configuration": {
|
| 279 |
+
"voltage_source_V": self.config.voltage_source,
|
| 280 |
+
"series_resistors": [
|
| 281 |
+
{"name": r.name, "resistance_ohms": r.resistance, "power_rating_W": r.power_rating}
|
| 282 |
+
for r in self.config.series_resistors
|
| 283 |
+
],
|
| 284 |
+
"parallel_branches": [
|
| 285 |
+
[
|
| 286 |
+
{"name": r.name, "resistance_ohms": r.resistance, "power_rating_W": r.power_rating}
|
| 287 |
+
for r in branch
|
| 288 |
+
]
|
| 289 |
+
for branch in self.config.parallel_branches
|
| 290 |
+
]
|
| 291 |
+
}
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
|
| 295 |
+
def create_sample_circuit() -> Dict[str, Any]:
|
| 296 |
+
"""Create a sample circuit for testing"""
|
| 297 |
+
# Create a simple series-parallel circuit
|
| 298 |
+
# Voltage source -> R1 (series) -> [R2, R3] (parallel) -> R4 (series)
|
| 299 |
+
|
| 300 |
+
series_resistors = [
|
| 301 |
+
Resistor("R1", 100, 0.25), # 100 ohms, 0.25W
|
| 302 |
+
Resistor("R4", 50, 0.5) # 50 ohms, 0.5W
|
| 303 |
+
]
|
| 304 |
+
|
| 305 |
+
parallel_branches = [
|
| 306 |
+
[Resistor("R2", 200, 0.25)], # Branch 1: 200 ohms, 0.25W
|
| 307 |
+
[Resistor("R3", 300, 0.25)] # Branch 2: 300 ohms, 0.25W
|
| 308 |
+
]
|
| 309 |
+
|
| 310 |
+
config = CircuitConfiguration(
|
| 311 |
+
voltage_source=12.0, # 12V battery
|
| 312 |
+
series_resistors=series_resistors,
|
| 313 |
+
parallel_branches=parallel_branches
|
| 314 |
+
)
|
| 315 |
+
|
| 316 |
+
analyzer = DCCircuitAnalyzer(config)
|
| 317 |
+
return analyzer.perform_analysis()
|
| 318 |
+
|
| 319 |
+
|
| 320 |
+
if __name__ == "__main__":
|
| 321 |
+
# Test the calculator
|
| 322 |
+
results = create_sample_circuit()
|
| 323 |
+
print("Sample Circuit Analysis Results:")
|
| 324 |
+
print(f"Status: {results['status']}")
|
| 325 |
+
if results['status'] == 'success':
|
| 326 |
+
print(f"Total Resistance: {results['equivalent_circuit']['total_resistance_ohms']:.2f} Ohms")
|
| 327 |
+
print(f"Total Current: {results['equivalent_circuit']['total_current_A']:.3f} A")
|
| 328 |
+
print(f"Total Power: {results['equivalent_circuit']['total_power_W']:.3f} W")
|
| 329 |
+
print(f"All Resistors Safe: {results['validation']['all_resistors_safe']}")
|
| 330 |
+
else:
|
| 331 |
+
print(f"Error: {results['error_message']}")
|
requirements.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio>=5.47.2
|
| 2 |
+
numpy>=1.21.0
|
| 3 |
+
matplotlib>=3.5.0
|
| 4 |
+
pandas>=1.3.0
|