# Entropyk C FFI Bindings

Auto-generated C bindings for the Entropyk thermodynamic simulation library.

## Building

```bash
# Build the library (generates target/entropyk.h)
cargo build --release -p entropyk-c

# Output files:
# - target/release/libentropyk_ffi.a      (static library)
# - target/release/libentropyk_ffi.dylib  (macOS)
# - target/release/libentropyk_ffi.so     (Linux)
# - target/entropyk.h                     (C header)
```

## Usage

```c
#include "entropyk.h"
#include <stdint.h>

int main() {
    // Create a system
    EntropykSystem* sys = entropyk_system_create();
    
    // Create components
    double compressor_coeffs[10] = {0.85, 2.5, 500.0, 1500.0, -2.5, 1.8, 600.0, 1600.0, -3.0, 2.0};
    EntropykComponent* comp = entropyk_compressor_create(compressor_coeffs, 10);
    EntropykComponent* cond = entropyk_condenser_create(5000.0);
    EntropykComponent* valve = entropyk_expansion_valve_create();
    EntropykComponent* evap = entropyk_evaporator_create(3000.0);
    
    // Add components to system (returns node index, or UINT32_MAX on error)
    unsigned int comp_idx = entropyk_system_add_component(sys, comp);
    unsigned int cond_idx = entropyk_system_add_component(sys, cond);
    unsigned int valve_idx = entropyk_system_add_component(sys, valve);
    unsigned int evap_idx = entropyk_system_add_component(sys, evap);
    
    if (comp_idx == UINT32_MAX || cond_idx == UINT32_MAX || 
        valve_idx == UINT32_MAX || evap_idx == UINT32_MAX) {
        printf("Failed to add component\n");
        return 1;
    }
    
    // Connect components
    EntropykErrorCode err;
    err = entropyk_system_add_edge(sys, comp_idx, cond_idx);
    err = entropyk_system_add_edge(sys, cond_idx, valve_idx);
    err = entropyk_system_add_edge(sys, valve_idx, evap_idx);
    err = entropyk_system_add_edge(sys, evap_idx, comp_idx);
    
    // Finalize the system
    err = entropyk_system_finalize(sys);
    if (err != ENTROPYK_OK) {
        printf("Finalize error: %s\n", entropyk_error_string(err));
        return 1;
    }
    
    // Solve
    EntropykFallbackConfig config = {
        .newton = {100, 1e-6, false, 0},
        .picard = {500, 1e-4, 0.5}
    };
    
    EntropykSolverResult* result = NULL;
    err = entropyk_solve_fallback(sys, &config, &result);
    
    if (err == ENTROPYK_OK) {
        printf("Converged in %u iterations\n", entropyk_result_get_iterations(result));
        printf("Status: %d\n", entropyk_result_get_status(result));
    } else {
        printf("Solve error: %s\n", entropyk_error_string(err));
    }
    
    // Cleanup
    entropyk_result_free(result);
    entropyk_system_free(sys);
    
    return 0;
}
```

## Memory Management

### Ownership Rules

1. **Create functions** (`entropyk_*_create`) return ownership to caller
2. **Add component** transfers ownership to the system
3. **Solve functions** return ownership of result to caller
4. **Free functions** must be called on all owned pointers

### Pairs

| Create Function | Free Function |
|-----------------|---------------|
| `entropyk_system_create` | `entropyk_system_free` |
| `entropyk_compressor_create` | `entropyk_compressor_free` |
| `entropyk_condenser_create` | `entropyk_component_free` |
| `entropyk_evaporator_create` | `entropyk_component_free` |
| `entropyk_expansion_valve_create` | `entropyk_component_free` |
| `entropyk_economizer_create` | `entropyk_component_free` |
| `entropyk_pipe_create` | `entropyk_component_free` |
| `entropyk_solve_*` | `entropyk_result_free` |

## Error Codes

| Code | Description |
|------|-------------|
| `OK` | Success |
| `NON_CONVERGENCE` | Solver did not converge |
| `TIMEOUT` | Solver timed out |
| `CONTROL_SATURATION` | Control variable saturated |
| `FLUID_ERROR` | Fluid property error |
| `INVALID_STATE` | Invalid thermodynamic state |
| `VALIDATION_ERROR` | Validation failed |
| `NULL_POINTER` | Null pointer passed |
| `INVALID_ARGUMENT` | Invalid argument value |
| `NOT_FINALIZED` | System not finalized |
| `TOPOLOGY_ERROR` | Graph topology error |
| `COMPONENT_ERROR` | Component error |

## Thread Safety

- Each `EntropykSystem*` is independent and can be used from different threads
- The library is reentrant: concurrent calls with different systems are safe
- Do NOT share a single system across threads without synchronization

## HIL Integration

The library is designed for HIL (Hardware-In-the-Loop) testing with:
- Latency target: < 20ms round-trip
- No dynamic allocation in solve hot path
- C99/C++ compatible headers

## License

MIT OR Apache-2.0
