1#![doc=include_str!( "../README.md")]
2#![doc = document_features::document_features!()]
4#![deny(unsafe_code)]
5#![deny(clippy::all)]
6
7use arrow::array::RecordBatch;
8use fmi::schema::{MajorVersion, traits::FmiModelDescription};
9use sim::SimStats;
10
11pub mod options;
12pub mod sim;
13
14#[derive(Debug, thiserror::Error)]
16pub enum Error {
17 #[error(transparent)]
18 FmiError(#[from] fmi::Error),
19
20 #[error(transparent)]
21 SolverError(#[from] sim::solver::SolverError),
22
23 #[error(transparent)]
24 ArrowError(#[from] arrow::error::ArrowError),
25
26 #[error(transparent)]
27 Other(#[from] anyhow::Error),
28}
29
30pub fn simulate(options: &options::FmiSimOptions) -> Result<(RecordBatch, SimStats), Error> {
35 let mini_descr = fmi::import::peek_descr_path(&options.model)?;
36 let version = mini_descr.major_version().map_err(fmi::Error::from)?;
37
38 log::debug!("Loaded {mini_descr:?}");
39
40 let input_data = options
42 .input_file
43 .as_ref()
44 .inspect(|p| log::debug!("Reading input data from {}", p.display()))
45 .map(sim::util::read_csv_file)
46 .transpose()?;
47
48 match version {
49 MajorVersion::FMI1 => Err(fmi::Error::UnsupportedFmiVersion(version).into()),
50
51 #[cfg(feature = "fmi2")]
52 MajorVersion::FMI2 => {
53 let import: fmi::fmi2::import::Fmi2Import = fmi::import::from_path(&options.model)?;
54 sim::simulate_with(input_data, &options.interface, import)
55 }
56
57 #[cfg(feature = "fmi3")]
58 MajorVersion::FMI3 => {
59 let import: fmi::fmi3::import::Fmi3Import = fmi::import::from_path(&options.model)?;
60 sim::simulate_with(input_data, &options.interface, import)
61 }
62 }
63}