- 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.
200 lines
5.3 KiB
Rust
200 lines
5.3 KiB
Rust
//! System lifecycle FFI functions.
|
|
//!
|
|
//! Provides opaque pointer wrappers for `entropyk_solver::System`.
|
|
|
|
use std::os::raw::c_uint;
|
|
|
|
use crate::components::EntropykComponent;
|
|
use crate::error::EntropykErrorCode;
|
|
|
|
/// Opaque handle to a thermodynamic system.
|
|
///
|
|
/// Create with `entropyk_system_create()`.
|
|
/// MUST call `entropyk_system_free()` when done.
|
|
#[repr(C)]
|
|
pub struct EntropykSystem {
|
|
_private: [u8; 0],
|
|
}
|
|
|
|
impl EntropykSystem {
|
|
fn from_inner(inner: entropyk_solver::System) -> *mut Self {
|
|
Box::into_raw(Box::new(inner)) as *mut Self
|
|
}
|
|
}
|
|
|
|
/// Create a new thermodynamic system.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// Pointer to the new system, or null on allocation failure.
|
|
///
|
|
/// # Ownership
|
|
///
|
|
/// Caller owns the returned pointer. MUST call `entropyk_system_free()` when done.
|
|
#[no_mangle]
|
|
pub extern "C" fn entropyk_system_create() -> *mut EntropykSystem {
|
|
let system = entropyk_solver::System::new();
|
|
EntropykSystem::from_inner(system)
|
|
}
|
|
|
|
/// Free a system created by `entropyk_system_create()`.
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// - `system` must be a valid pointer returned by `entropyk_system_create()`, or null
|
|
/// - After this call, `system` is invalid and must not be used
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn entropyk_system_free(system: *mut EntropykSystem) {
|
|
if !system.is_null() {
|
|
drop(Box::from_raw(system as *mut entropyk_solver::System));
|
|
}
|
|
}
|
|
|
|
/// Add a component to the system.
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// - `system`: The system (must not be null)
|
|
/// - `component`: The component to add (must not be null)
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// Node index on success, or `UINT32_MAX` (0xFFFFFFFF) on error.
|
|
/// Use this index for `entropyk_system_add_edge()`.
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// - `system` must be a valid pointer
|
|
/// - `component` must be a valid pointer
|
|
/// - After this call, `component` is consumed and must not be used again
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn entropyk_system_add_component(
|
|
system: *mut EntropykSystem,
|
|
component: *mut EntropykComponent,
|
|
) -> c_uint {
|
|
const ERROR_INDEX: c_uint = u32::MAX;
|
|
|
|
if system.is_null() || component.is_null() {
|
|
return ERROR_INDEX;
|
|
}
|
|
|
|
let sys = &mut *(system as *mut entropyk_solver::System);
|
|
let comp_ptr = component as *mut Box<dyn entropyk_components::Component>;
|
|
let comp = Box::from_raw(comp_ptr);
|
|
|
|
let node_index = sys.add_component(*comp);
|
|
node_index.index() as c_uint
|
|
}
|
|
|
|
/// Add a flow edge from source to target node.
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// - `system`: The system (must not be null)
|
|
/// - `from`: Source node index (returned by `entropyk_system_add_component`)
|
|
/// - `to`: Target node index (returned by `entropyk_system_add_component`)
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// - `ENTROPYK_OK` on success
|
|
/// - `ENTROPYK_NULL_POINTER` if system is null
|
|
/// - `ENTROPYK_TOPOLOGY_ERROR` if edge cannot be added
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// `system` must be a valid pointer.
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn entropyk_system_add_edge(
|
|
system: *mut EntropykSystem,
|
|
from: c_uint,
|
|
to: c_uint,
|
|
) -> EntropykErrorCode {
|
|
if system.is_null() {
|
|
return EntropykErrorCode::EntropykNullPointer;
|
|
}
|
|
|
|
let sys = &mut *(system as *mut entropyk_solver::System);
|
|
let src = petgraph::graph::NodeIndex::new(from as usize);
|
|
let tgt = petgraph::graph::NodeIndex::new(to as usize);
|
|
|
|
match sys.add_edge(src, tgt) {
|
|
Ok(_) => EntropykErrorCode::EntropykOk,
|
|
Err(e) => EntropykErrorCode::from(e),
|
|
}
|
|
}
|
|
|
|
/// Finalize the system for solving.
|
|
///
|
|
/// Must be called before any solve function.
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// - `system`: The system (must not be null)
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// - `ENTROPYK_OK` on success
|
|
/// - `ENTROPYK_NULL_POINTER` if system is null
|
|
/// - `ENTROPYK_TOPOLOGY_ERROR` if topology is invalid
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// `system` must be a valid pointer.
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn entropyk_system_finalize(
|
|
system: *mut EntropykSystem,
|
|
) -> EntropykErrorCode {
|
|
if system.is_null() {
|
|
return EntropykErrorCode::EntropykNullPointer;
|
|
}
|
|
|
|
let sys = &mut *(system as *mut entropyk_solver::System);
|
|
|
|
match sys.finalize() {
|
|
Ok(_) => EntropykErrorCode::EntropykOk,
|
|
Err(e) => EntropykErrorCode::from(e),
|
|
}
|
|
}
|
|
|
|
/// Get the number of components (nodes) in the system.
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// `system` must be a valid pointer or null.
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn entropyk_system_node_count(system: *const EntropykSystem) -> c_uint {
|
|
if system.is_null() {
|
|
return 0;
|
|
}
|
|
let sys = &*(system as *const entropyk_solver::System);
|
|
sys.node_count() as c_uint
|
|
}
|
|
|
|
/// Get the number of edges in the system.
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// `system` must be a valid pointer or null.
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn entropyk_system_edge_count(system: *const EntropykSystem) -> c_uint {
|
|
if system.is_null() {
|
|
return 0;
|
|
}
|
|
let sys = &*(system as *const entropyk_solver::System);
|
|
sys.edge_count() as c_uint
|
|
}
|
|
|
|
/// Get the length of the state vector (after finalization).
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// `system` must be a valid pointer or null.
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn entropyk_system_state_vector_len(system: *const EntropykSystem) -> c_uint {
|
|
if system.is_null() {
|
|
return 0;
|
|
}
|
|
let sys = &*(system as *const entropyk_solver::System);
|
|
sys.state_vector_len() as c_uint
|
|
}
|