534 lines
11 KiB
Markdown
534 lines
11 KiB
Markdown
# API Diagramme PH - Spécifications Techniques
|
|
|
|
## Vue d'ensemble
|
|
|
|
API REST pour générer des diagrammes Pression-Enthalpie (PH) de réfrigérants et effectuer des calculs thermodynamiques frigorifiques avancés.
|
|
|
|
---
|
|
|
|
## Architecture Technique
|
|
|
|
### Stack Technologique
|
|
- **Framework**: FastAPI (Python 3.12+)
|
|
- **Bibliothèques thermodynamiques**: DLL/SO personnalisées (IPM_DLL)
|
|
- **Visualisation**: Matplotlib, Plotly
|
|
- **Déploiement**: Docker + AWS Elastic Beanstalk
|
|
- **Format de réponse**: JSON + images base64
|
|
|
|
### Réfrigérants supportés
|
|
R12, R22, R32, R134a, R290, R404A, R410A, R452A, R454A, R454B, R502, R507A, R513A, R515B, R744 (CO2), R1233zd, R1234ze
|
|
|
|
---
|
|
|
|
## Endpoints API
|
|
|
|
### 1. GET /api/v1/health
|
|
**Description**: Vérification de l'état de l'API
|
|
|
|
**Réponse**:
|
|
```json
|
|
{
|
|
"status": "healthy",
|
|
"version": "1.0.0",
|
|
"available_refrigerants": ["R134a", "R410A", ...]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 2. GET /api/v1/refrigerants
|
|
**Description**: Liste des réfrigérants disponibles
|
|
|
|
**Réponse**:
|
|
```json
|
|
{
|
|
"refrigerants": [
|
|
{
|
|
"name": "R134a",
|
|
"description": "HFC Refrigerant",
|
|
"pressure_range": {"min": 51325, "max": 4059280, "unit": "Pa"},
|
|
"temperature_range": {"min": -103.3, "max": 101.1, "unit": "°C"}
|
|
},
|
|
...
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 3. POST /api/v1/diagram/generate
|
|
**Description**: Génération d'un diagramme PH
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"refrigerant": "R134a",
|
|
"output_format": "plotly_json", // "matplotlib_png", "plotly_json", "plotly_html"
|
|
"points": [
|
|
{
|
|
"type": "PT", // "PT", "PX", "PH", "TSX"
|
|
"pressure": 500000, // Pa
|
|
"temperature": 5, // °C
|
|
"label": "Point 1",
|
|
"order": 1
|
|
},
|
|
{
|
|
"type": "PX",
|
|
"pressure": 1500000, // Pa
|
|
"quality": 1.0,
|
|
"label": "Point 2",
|
|
"order": 2
|
|
}
|
|
],
|
|
"diagram_options": {
|
|
"show_isotherms": true,
|
|
"isotherm_step": 10, // °C
|
|
"show_saturation_lines": true,
|
|
"title": "Custom Title (optional)",
|
|
"width": 1000,
|
|
"height": 800
|
|
}
|
|
}
|
|
```
|
|
|
|
**Réponse (format plotly_json)**:
|
|
```json
|
|
{
|
|
"success": true,
|
|
"refrigerant": "R134a",
|
|
"diagram_type": "PH",
|
|
"output_format": "plotly_json",
|
|
"data": {
|
|
"plotly_figure": {
|
|
"data": [...], // Plotly traces
|
|
"layout": {...} // Plotly layout
|
|
},
|
|
"points_calculated": [
|
|
{
|
|
"label": "Point 1",
|
|
"order": 1,
|
|
"pressure": 500000,
|
|
"temperature": 5,
|
|
"enthalpy": 250000,
|
|
"quality": 0.0,
|
|
"entropy": 1200,
|
|
"density": 1250
|
|
}
|
|
]
|
|
},
|
|
"metadata": {
|
|
"generated_at": "2025-10-18T12:30:00Z",
|
|
"computation_time_ms": 245
|
|
}
|
|
}
|
|
```
|
|
|
|
**Réponse (format matplotlib_png)**:
|
|
```json
|
|
{
|
|
"success": true,
|
|
"refrigerant": "R134a",
|
|
"diagram_type": "PH",
|
|
"output_format": "matplotlib_png",
|
|
"data": {
|
|
"image_base64": "iVBORw0KGgoAAAANSUhEUgAA...",
|
|
"mime_type": "image/png",
|
|
"points_calculated": [...]
|
|
},
|
|
"metadata": {...}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 4. POST /api/v1/calculations/cycle
|
|
**Description**: Calculs de cycle frigorifique complet (COP, puissance, rendement)
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"refrigerant": "R134a",
|
|
"cycle_type": "standard", // "standard", "economizer", "two_stage"
|
|
"points": {
|
|
"evaporator_outlet": {
|
|
"type": "PT",
|
|
"pressure": 200000,
|
|
"temperature": -10,
|
|
"superheat": 5 // °C (optionnel)
|
|
},
|
|
"compressor_outlet": {
|
|
"type": "PT",
|
|
"pressure": 1500000,
|
|
"temperature": 80
|
|
},
|
|
"condenser_outlet": {
|
|
"type": "PT",
|
|
"pressure": 1500000,
|
|
"temperature": 40,
|
|
"subcooling": 5 // °C (optionnel)
|
|
},
|
|
"expansion_valve_outlet": {
|
|
"type": "PX",
|
|
"pressure": 200000,
|
|
"quality": 0.25
|
|
}
|
|
},
|
|
"operating_conditions": {
|
|
"mass_flow_rate": 0.05, // kg/s
|
|
"volumetric_efficiency": 0.85,
|
|
"isentropic_efficiency": 0.75,
|
|
"mechanical_efficiency": 0.95
|
|
},
|
|
"economizer": { // Optionnel pour cycle avec économiseur
|
|
"enabled": false,
|
|
"intermediate_pressure": 600000,
|
|
"subcooling_gain": 10
|
|
}
|
|
}
|
|
```
|
|
|
|
**Réponse**:
|
|
```json
|
|
{
|
|
"success": true,
|
|
"refrigerant": "R134a",
|
|
"cycle_type": "standard",
|
|
"results": {
|
|
"cop": {
|
|
"cop_cooling": 3.85,
|
|
"cop_heating": 4.85,
|
|
"carnot_cop": 5.2,
|
|
"carnot_efficiency": 0.74
|
|
},
|
|
"capacities": {
|
|
"cooling_capacity": 12500, // W
|
|
"heating_capacity": 15750, // W
|
|
"compressor_power": 3250 // W
|
|
},
|
|
"energies": {
|
|
"evaporator_heat": 250000, // J/kg
|
|
"condenser_heat": 315000, // J/kg
|
|
"compressor_work": 65000 // J/kg
|
|
},
|
|
"efficiencies": {
|
|
"volumetric_efficiency": 0.85,
|
|
"isentropic_efficiency": 0.75,
|
|
"mechanical_efficiency": 0.95,
|
|
"overall_efficiency": 0.606
|
|
},
|
|
"mass_flow": {
|
|
"refrigerant_mass_flow": 0.05, // kg/s
|
|
"volume_flow_rate": 0.04 // m³/s
|
|
},
|
|
"cycle_points": [
|
|
{
|
|
"point_name": "evaporator_outlet",
|
|
"order": 1,
|
|
"pressure": 200000,
|
|
"temperature": -5,
|
|
"enthalpy": 390000,
|
|
"entropy": 1750,
|
|
"quality": 1.0,
|
|
"density": 8.5
|
|
},
|
|
{
|
|
"point_name": "compressor_outlet",
|
|
"order": 2,
|
|
"pressure": 1500000,
|
|
"temperature": 80,
|
|
"enthalpy": 455000,
|
|
"entropy": 1820,
|
|
"quality": null,
|
|
"density": 45.2
|
|
}
|
|
]
|
|
},
|
|
"diagram_data": {
|
|
"plotly_json": {...} // Diagramme PH du cycle
|
|
},
|
|
"metadata": {
|
|
"generated_at": "2025-10-18T12:30:00Z",
|
|
"computation_time_ms": 185
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 5. POST /api/v1/calculations/power
|
|
**Description**: Calcul de puissance entre deux points avec débit massique
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"refrigerant": "R134a",
|
|
"point_1": {
|
|
"type": "PT",
|
|
"pressure": 500000,
|
|
"temperature": 5
|
|
},
|
|
"point_2": {
|
|
"type": "PT",
|
|
"pressure": 1500000,
|
|
"temperature": 80
|
|
},
|
|
"mass_flow_rate": 0.05, // kg/s
|
|
"process_type": "compression" // "compression", "expansion", "heat_exchange"
|
|
}
|
|
```
|
|
|
|
**Réponse**:
|
|
```json
|
|
{
|
|
"success": true,
|
|
"refrigerant": "R134a",
|
|
"results": {
|
|
"power": 3250, // W
|
|
"enthalpy_difference": 65000, // J/kg
|
|
"entropy_difference": 70, // J/(kg·K)
|
|
"point_1": {
|
|
"pressure": 500000,
|
|
"temperature": 5,
|
|
"enthalpy": 390000,
|
|
"entropy": 1750
|
|
},
|
|
"point_2": {
|
|
"pressure": 1500000,
|
|
"temperature": 80,
|
|
"enthalpy": 455000,
|
|
"entropy": 1820
|
|
},
|
|
"mass_flow_rate": 0.05
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 6. POST /api/v1/properties/calculate
|
|
**Description**: Calcul des propriétés thermodynamiques à un point
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"refrigerant": "R134a",
|
|
"point": {
|
|
"type": "PT", // "PT", "PX", "PH", "TX"
|
|
"pressure": 500000,
|
|
"temperature": 5
|
|
}
|
|
}
|
|
```
|
|
|
|
**Réponse**:
|
|
```json
|
|
{
|
|
"success": true,
|
|
"refrigerant": "R134a",
|
|
"properties": {
|
|
"pressure": 500000, // Pa
|
|
"temperature": 5, // °C
|
|
"enthalpy": 390000, // J/kg
|
|
"entropy": 1750, // J/(kg·K)
|
|
"density": 1250, // kg/m³
|
|
"quality": 1.0, // 0-1 (null si surchauffe/sous-refroidissement)
|
|
"specific_volume": 0.0008, // m³/kg
|
|
"cp": 1050, // J/(kg·K)
|
|
"cv": 850, // J/(kg·K)
|
|
"viscosity": 0.00012, // Pa·s
|
|
"thermal_conductivity": 0.015, // W/(m·K)
|
|
"sound_velocity": 250, // m/s
|
|
"saturation_temperature": -10, // °C
|
|
"phase": "superheated_vapor" // "subcooled_liquid", "two_phase", "superheated_vapor"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 7. POST /api/v1/calculations/economizer
|
|
**Description**: Calculs spécifiques pour cycles avec économiseur
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"refrigerant": "R134a",
|
|
"main_cycle": {
|
|
"evaporator_pressure": 200000,
|
|
"condenser_pressure": 1500000,
|
|
"evaporator_superheat": 5,
|
|
"condenser_subcooling": 5
|
|
},
|
|
"economizer": {
|
|
"intermediate_pressure": 600000,
|
|
"flash_gas_quality": 0.3,
|
|
"subcooling_effectiveness": 0.8
|
|
},
|
|
"mass_flow_rate": 0.05,
|
|
"efficiencies": {
|
|
"isentropic_low_stage": 0.75,
|
|
"isentropic_high_stage": 0.75,
|
|
"volumetric": 0.85
|
|
}
|
|
}
|
|
```
|
|
|
|
**Réponse**:
|
|
```json
|
|
{
|
|
"success": true,
|
|
"refrigerant": "R134a",
|
|
"results": {
|
|
"performance": {
|
|
"cop": 4.2,
|
|
"cop_improvement": 9.1, // % vs standard cycle
|
|
"cooling_capacity": 13500,
|
|
"total_compressor_power": 3214
|
|
},
|
|
"mass_flows": {
|
|
"evaporator_flow": 0.05,
|
|
"economizer_flash_gas": 0.008,
|
|
"high_stage_flow": 0.058
|
|
},
|
|
"economizer_benefit": {
|
|
"subcooling_increase": 8, // °C
|
|
"enthalpy_reduction": 12000, // J/kg
|
|
"capacity_increase": 8.0 // %
|
|
},
|
|
"cycle_points": [...]
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 8. POST /api/v1/batch/calculate
|
|
**Description**: Calculs en batch pour plusieurs points ou configurations
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"refrigerant": "R134a",
|
|
"calculations": [
|
|
{
|
|
"id": "calc_1",
|
|
"type": "properties",
|
|
"point": {"type": "PT", "pressure": 500000, "temperature": 5}
|
|
},
|
|
{
|
|
"id": "calc_2",
|
|
"type": "power",
|
|
"point_1": {"type": "PT", "pressure": 500000, "temperature": 5},
|
|
"point_2": {"type": "PT", "pressure": 1500000, "temperature": 80},
|
|
"mass_flow_rate": 0.05
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Codes d'erreur
|
|
|
|
| Code | Description |
|
|
|------|-------------|
|
|
| 400 | Requête invalide (paramètres manquants ou invalides) |
|
|
| 404 | Réfrigérant non trouvé |
|
|
| 422 | Point thermodynamique hors limites |
|
|
| 500 | Erreur serveur (DLL, calcul) |
|
|
| 503 | Service temporairement indisponible |
|
|
|
|
**Format d'erreur**:
|
|
```json
|
|
{
|
|
"success": false,
|
|
"error": {
|
|
"code": "INVALID_REFRIGERANT",
|
|
"message": "Refrigerant R999 not found",
|
|
"details": {
|
|
"available_refrigerants": ["R134a", "R410A", ...]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Limites et Contraintes
|
|
|
|
### Rate Limiting
|
|
- 100 requêtes/minute par IP
|
|
- 1000 requêtes/heure par IP
|
|
|
|
### Taille des requêtes
|
|
- Max 100 points par diagramme
|
|
- Max 50 calculs par batch
|
|
- Timeout: 30 secondes par requête
|
|
|
|
### Précision des calculs
|
|
- Pression: ±0.1%
|
|
- Température: ±0.1 K
|
|
- Enthalpie: ±0.5%
|
|
|
|
---
|
|
|
|
## Exemples d'utilisation
|
|
|
|
### Python
|
|
```python
|
|
import requests
|
|
|
|
# Générer un diagramme PH
|
|
response = requests.post(
|
|
"https://api.diagramph.com/api/v1/diagram/generate",
|
|
json={
|
|
"refrigerant": "R134a",
|
|
"output_format": "plotly_json",
|
|
"points": [
|
|
{"type": "PT", "pressure": 500000, "temperature": 5, "order": 1},
|
|
{"type": "PT", "pressure": 1500000, "temperature": 80, "order": 2}
|
|
]
|
|
}
|
|
)
|
|
|
|
data = response.json()
|
|
```
|
|
|
|
### JavaScript/React
|
|
```javascript
|
|
const response = await fetch('https://api.diagramph.com/api/v1/diagram/generate', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({
|
|
refrigerant: 'R134a',
|
|
output_format: 'plotly_json',
|
|
points: [...]
|
|
})
|
|
});
|
|
|
|
const data = await response.json();
|
|
// Utiliser Plotly.react() pour afficher le graphique
|
|
```
|
|
|
|
### cURL
|
|
```bash
|
|
curl -X POST https://api.diagramph.com/api/v1/diagram/generate \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"refrigerant": "R134a",
|
|
"output_format": "matplotlib_png",
|
|
"points": [
|
|
{"type": "PT", "pressure": 500000, "temperature": 5}
|
|
]
|
|
}'
|
|
```
|
|
|
|
---
|
|
|
|
## Changelog
|
|
|
|
### Version 1.0.0 (2025-10)
|
|
- Endpoints de base pour diagrammes PH
|
|
- Calculs de cycles frigorifiques
|
|
- Support économiseur
|
|
- 17 réfrigérants supportés |