Sepehr fa480ed303 feat: implement mass balance validation for Story 7.1
- Added port_mass_flows to Component trait and implements for core components.
- Added System::check_mass_balance and integrated it into the solver.
- Restored connect methods for ExpansionValve, Compressor, and Pipe to fix integration tests.
- Updated Python and C bindings for validation errors.
- Updated sprint status and story documentation.
2026-02-21 23:21:34 +01:00

179 lines
6.3 KiB
C

/**
* Simple refrigeration cycle example for Entropyk C FFI.
*
* Demonstrates:
* - System lifecycle (create/free)
* - Component creation (compressor, condenser, valve, evaporator)
* - System topology (add components, add edges, finalize)
* - Solving (fallback solver)
* - Result retrieval
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "entropyk.h"
int main() {
printf("Entropyk C FFI Example - Simple Refrigeration Cycle\n");
printf("===================================================\n\n");
/* 1. Create the system */
EntropykSystem* sys = entropyk_system_create();
if (!sys) {
printf("ERROR: Failed to create system\n");
return 1;
}
printf("Created system\n");
/* 2. Create components */
double compressor_coeffs[10] = {
0.85, /* m1: mass flow coefficient */
2.5, /* m2: mass flow exponent for suction pressure */
500.0, /* m3: mass flow coefficient for superheat */
1500.0, /* m4: power coefficient */
-2.5, /* m5: power exponent */
1.8, /* m6: power exponent */
600.0, /* m7: additional power coefficient */
1600.0, /* m8: additional power coefficient */
-3.0, /* m9: power exponent */
2.0 /* m10: power exponent */
};
EntropykComponent* comp = entropyk_compressor_create(compressor_coeffs, 10);
EntropykComponent* cond = entropyk_condenser_create(5000.0); /* 5 kW/K */
EntropykComponent* valve = entropyk_expansion_valve_create();
EntropykComponent* evap = entropyk_evaporator_create(3000.0); /* 3 kW/K */
if (!comp || !cond || !valve || !evap) {
printf("ERROR: Failed to create components\n");
entropyk_system_free(sys);
return 1;
}
printf("Created 4 components: compressor, condenser, valve, evaporator\n");
/* 3. Add components to system (transfers ownership, returns node index) */
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("ERROR: Failed to add component to system\n");
entropyk_system_free(sys);
return 1;
}
printf("Added components: comp=%u, cond=%u, valve=%u, evap=%u\n",
comp_idx, cond_idx, valve_idx, evap_idx);
/* 4. Connect components (simple cycle: comp -> cond -> valve -> evap -> comp) */
EntropykErrorCode err;
err = entropyk_system_add_edge(sys, comp_idx, cond_idx);
if (err != ENTROPYK_OK) {
printf("ERROR: Failed to add edge comp->cond: %s\n", entropyk_error_string(err));
entropyk_system_free(sys);
return 1;
}
err = entropyk_system_add_edge(sys, cond_idx, valve_idx);
if (err != ENTROPYK_OK) {
printf("ERROR: Failed to add edge cond->valve: %s\n", entropyk_error_string(err));
entropyk_system_free(sys);
return 1;
}
err = entropyk_system_add_edge(sys, valve_idx, evap_idx);
if (err != ENTROPYK_OK) {
printf("ERROR: Failed to add edge valve->evap: %s\n", entropyk_error_string(err));
entropyk_system_free(sys);
return 1;
}
err = entropyk_system_add_edge(sys, evap_idx, comp_idx);
if (err != ENTROPYK_OK) {
printf("ERROR: Failed to add edge evap->comp: %s\n", entropyk_error_string(err));
entropyk_system_free(sys);
return 1;
}
printf("Connected components in cycle\n");
printf("System: %u nodes, %u edges\n",
entropyk_system_node_count(sys),
entropyk_system_edge_count(sys));
/* 5. Finalize the system */
err = entropyk_system_finalize(sys);
if (err != ENTROPYK_OK) {
printf("ERROR: Failed to finalize system: %s\n", entropyk_error_string(err));
entropyk_system_free(sys);
return 1;
}
printf("System finalized (state vector length: %u)\n",
entropyk_system_state_vector_len(sys));
/* 6. Configure and run solver */
EntropykFallbackConfig config = {
.newton = {
.max_iterations = 100,
.tolerance = 1e-6,
.line_search = false,
.timeout_ms = 0
},
.picard = {
.max_iterations = 500,
.tolerance = 1e-4,
.relaxation = 0.5
}
};
EntropykSolverResult* result = NULL;
err = entropyk_solve_fallback(sys, &config, &result);
/* 7. Check results */
if (err == ENTROPYK_OK && result != NULL) {
EntropykConvergenceStatus status = entropyk_result_get_status(result);
unsigned int iterations = entropyk_result_get_iterations(result);
double residual = entropyk_result_get_residual(result);
printf("\n=== Solver Results ===\n");
printf("Status: %s\n",
status == CONVERGED ? "CONVERGED" :
status == CONVERGED_TIMED_OUT ? "TIMED_OUT" :
status == CONVERGED_CONTROL_SATURATION ? "CONTROL_SATURATION" : "UNKNOWN");
printf("Iterations: %u\n", iterations);
printf("Final residual: %.2e\n", residual);
/* Get state vector */
unsigned int len = 0;
entropyk_result_get_state_vector(result, NULL, &len);
if (len > 0) {
double* state = (double*)malloc(len * sizeof(double));
if (state) {
entropyk_result_get_state_vector(result, state, &len);
printf("State vector[%u]: [", len);
for (unsigned int i = 0; i < (len < 6 ? len : 6); i++) {
printf("%.2f", state[i]);
if (i < len - 1) printf(", ");
}
if (len > 6) printf(", ...");
printf("]\n");
free(state);
}
}
entropyk_result_free(result);
} else {
printf("\n=== Solver Failed ===\n");
printf("Error: %s\n", entropyk_error_string(err));
}
/* 8. Cleanup */
entropyk_system_free(sys);
printf("\nCleanup complete.\n");
return (err == ENTROPYK_OK) ? 0 : 1;
}