1#![allow(
10 clippy::missing_safety_doc,
11 clippy::too_many_arguments,
12 clippy::useless_conversion
13)]
14
15use ::std::ffi::CString;
16
17use crate::fmi3::{
18 ModelGetSetStates, ModelInstance, UserModel,
19 instance::{IntermediateUpdateClosure, LogMessageClosure, context::BasicContext},
20 traits::ModelGetSet,
21};
22
23use super::{Context, Model};
24
25use fmi::fmi3::CoSimulation;
26
27use ::fmi::fmi3::Fmi3Status;
28use fmi::fmi3::{Common, Fmi3Res, GetSet, ModelExchange, ScheduledExecution, binding};
29
30#[macro_export]
32macro_rules! checked_deref_me {
33 ($ptr:expr, $ty:ty) => {{
34 if ($ptr as *mut ::std::os::raw::c_void).is_null() {
35 eprintln!("Invalid FMU instance");
36 return ::fmi::fmi3::binding::fmi3Status_fmi3Error;
37 }
38 let instance = unsafe {
39 &mut *($ptr as *mut $crate::fmi3::ModelInstance<
40 $ty,
41 $crate::fmi3::instance::context::BasicContext<$ty>,
42 >)
43 };
44 instance
45 }};
46}
47
48#[macro_export]
50macro_rules! checked_deref_cs {
51 ($ptr:expr, $ty:ty) => {{
52 if ($ptr as *mut ::std::os::raw::c_void).is_null() {
53 eprintln!("Invalid FMU instance");
54 return ::fmi::fmi3::binding::fmi3Status_fmi3Error;
55 }
56 let instance = unsafe {
57 &mut *($ptr as *mut $crate::fmi3::ModelInstance<
58 $ty,
59 $crate::fmi3::instance::context::BasicContext<$ty>,
60 >)
61 };
62 instance
63 }};
64}
65
66#[macro_export]
69macro_rules! dispatch_by_instance_type {
70 ($ptr:expr, $ty:ty, $method:ident $(, $arg:expr)*) => {{
71 if ($ptr as *mut ::std::os::raw::c_void).is_null() {
72 eprintln!("Invalid FMU instance");
73 return ::fmi::fmi3::binding::fmi3Status_fmi3Error;
74 }
75
76 let instance_type = unsafe {
79 let temp = $ptr as *const $crate::fmi3::ModelInstance<$ty, $crate::fmi3::instance::context::BasicContext<$ty>>;
80 (*temp).instance_type
82 };
83
84 match instance_type {
85 fmi::InterfaceType::ModelExchange => {
86 let instance = unsafe {
87 &mut *($ptr as *mut $crate::fmi3::ModelInstance<$ty, $crate::fmi3::instance::context::BasicContext<$ty>>)
88 };
89 instance.$method($($arg),*)
90 }
91 fmi::InterfaceType::CoSimulation => {
92 let instance = unsafe {
93 &mut *($ptr as *mut $crate::fmi3::ModelInstance<$ty, $crate::fmi3::instance::context::BasicContext<$ty>>)
94 };
95 instance.$method($($arg),*)
96 }
97 fmi::InterfaceType::ScheduledExecution => {
98 let instance = unsafe {
99 &mut *($ptr as *mut $crate::fmi3::ModelInstance<$ty, $crate::fmi3::instance::context::BasicContext<$ty>>)
100 };
101 instance.$method($($arg),*)
102 }
103 }
104 }};
105}
106
107#[macro_export]
108macro_rules! wrapper_getset_functions {
109 ($type_name:ident, $fmi_type:ty, $get_method:ident, $set_method:ident) => {
110 $crate::paste::paste! {
111 unsafe extern "C" fn [<fmi3_get_ $type_name:snake>](
112 instance: binding::fmi3Instance,
113 value_references: *const binding::fmi3ValueReference,
114 n_value_references: usize,
115 values: *mut $fmi_type,
116 n_values: usize,
117 ) -> binding::fmi3Status {
118 if n_values < n_value_references {
120 eprintln!("FMI3: Array length mismatch in fmi3Get{}: value_references={}, values={}",
121 stringify!($type_name), n_value_references, n_values);
122 return ::fmi::fmi3::binding::fmi3Status_fmi3Error;
123 }
124
125 let value_refs = unsafe { std::slice::from_raw_parts(value_references, n_value_references) };
126 let values = unsafe { std::slice::from_raw_parts_mut(values, n_values) };
127
128 match $crate::dispatch_by_instance_type!(instance, Self, $get_method, value_refs, values) {
129 Ok(res) => {
130 let status: ::fmi::fmi3::Fmi3Status = res.into();
131 status.into()
132 }
133 Err(_) => binding::fmi3Status_fmi3Error,
134 }
135 }
136
137 unsafe extern "C" fn [<fmi3_set_ $type_name:snake>](
138 instance: binding::fmi3Instance,
139 value_references: *const binding::fmi3ValueReference,
140 n_value_references: usize,
141 values: *const $fmi_type,
142 n_values: usize,
143 ) -> binding::fmi3Status {
144 if n_values < n_value_references {
146 eprintln!("FMI3: Array length mismatch in fmi3Set{}: value_references={}, values={}",
147 stringify!($type_name), n_value_references, n_values);
148 return binding::fmi3Status_fmi3Error;
149 }
150
151 let value_refs = unsafe { std::slice::from_raw_parts(value_references, n_value_references) };
152 let values = unsafe { std::slice::from_raw_parts(values, n_values) };
153
154 match $crate::dispatch_by_instance_type!(instance, Self, $set_method, value_refs, values) {
155 Ok(res) => {
156 let status: ::fmi::fmi3::Fmi3Status = res.into();
157 status.into()
158 }
159 Err(_) => binding::fmi3Status_fmi3Error,
160 }
161 }
162 }
163 };
164}
165
166pub trait Fmi3Common: Model + UserModel + ModelGetSet<Self> + ModelGetSetStates + Sized
167where
168 Self: 'static,
169{
170 #[inline(always)]
171 unsafe fn fmi3_get_version() -> *const ::std::os::raw::c_char {
172 binding::fmi3Version.as_ptr() as *const _
173 }
174
175 #[inline(always)]
176 unsafe fn fmi3_set_debug_logging(
177 instance: binding::fmi3Instance,
178 logging_on: binding::fmi3Boolean,
179 n_categories: usize,
180 categories: *const binding::fmi3String,
181 ) -> binding::fmi3Status {
182 let categories = unsafe { std::slice::from_raw_parts(categories, n_categories) }
183 .iter()
184 .filter_map(|cat| unsafe { std::ffi::CStr::from_ptr(*cat) }.to_str().ok())
185 .collect::<::std::vec::Vec<_>>();
186 match dispatch_by_instance_type!(instance, Self, set_debug_logging, logging_on, &categories)
187 {
188 Ok(res) => {
189 let status: Fmi3Status = res.into();
190 status.into()
191 }
192 Err(_) => binding::fmi3Status_fmi3Error,
193 }
194 }
195
196 #[inline(always)]
197 unsafe extern "C" fn fmi3_instantiate_model_exchange(
198 instance_name: binding::fmi3String,
199 instantiation_token: binding::fmi3String,
200 resource_path: binding::fmi3String,
201 _visible: binding::fmi3Boolean,
202 logging_on: binding::fmi3Boolean,
203 _instance_environment: binding::fmi3InstanceEnvironment,
204 log_message: binding::fmi3LogMessageCallback,
205 ) -> binding::fmi3Instance {
206 let name = unsafe { ::std::ffi::CStr::from_ptr(instance_name) }
207 .to_string_lossy()
208 .into_owned();
209 let token = unsafe { ::std::ffi::CStr::from_ptr(instantiation_token) }.to_string_lossy();
210 let resource_path = ::std::path::PathBuf::from(
211 unsafe { ::std::ffi::CStr::from_ptr(resource_path) }
212 .to_string_lossy()
213 .into_owned(),
214 );
215
216 let log_message: LogMessageClosure = if let Some(cb) = log_message {
218 Box::new(
219 move |status: Fmi3Status, category: &str, args: std::fmt::Arguments<'_>| {
220 let category_c = CString::new(category).unwrap_or_default();
221 let message_c = CString::new(args.to_string()).unwrap_or_default();
222 unsafe {
223 cb(
224 std::ptr::null_mut() as binding::fmi3InstanceEnvironment,
225 status.into(),
226 category_c.as_ptr(),
227 message_c.as_ptr(),
228 )
229 };
230 },
231 )
232 } else {
233 Box::new(
234 move |status: Fmi3Status, category: &str, args: std::fmt::Arguments<'_>| {
235 let category_c = CString::new(category).unwrap_or_default();
236 let message_c = CString::new(args.to_string()).unwrap_or_default();
237 eprintln!(
238 "Log (status: {:?}, category: {}): {}",
239 status,
240 category_c.to_string_lossy(),
241 message_c.to_string_lossy()
242 );
243 },
244 )
245 };
246
247 if !Self::SUPPORTS_MODEL_EXCHANGE {
248 eprintln!("Model Exchange not supported by this FMU");
249 return ::std::ptr::null_mut();
250 }
251
252 let context = BasicContext::new(logging_on, log_message, resource_path, false, None);
253
254 match crate::fmi3::ModelInstance::<Self, BasicContext<Self>>::new(
255 name,
256 &token,
257 context,
258 fmi::InterfaceType::ModelExchange,
259 ) {
260 Ok(instance) => ::std::boxed::Box::into_raw(::std::boxed::Box::new(instance))
261 as binding::fmi3Instance,
262 Err(_) => {
263 eprintln!("Failed to instantiate FMU: invalid instantiation token");
264 ::std::ptr::null_mut()
265 }
266 }
267 }
268
269 #[inline(always)]
270 unsafe extern "C" fn fmi3_instantiate_co_simulation(
271 instance_name: binding::fmi3String,
272 instantiation_token: binding::fmi3String,
273 resource_path: binding::fmi3String,
274 _visible: binding::fmi3Boolean,
275 _logging_on: binding::fmi3Boolean,
276 _event_mode_used: binding::fmi3Boolean,
277 _early_return_allowed: binding::fmi3Boolean,
278 _required_intermediate_variables: *const binding::fmi3ValueReference,
279 _n_required_intermediate_variables: usize,
280 _instance_environment: binding::fmi3InstanceEnvironment,
281 _log_message: binding::fmi3LogMessageCallback,
282 intermediate_update: binding::fmi3IntermediateUpdateCallback,
283 ) -> binding::fmi3Instance {
284 let name = unsafe { ::std::ffi::CStr::from_ptr(instance_name) }
285 .to_string_lossy()
286 .into_owned();
287 let token = unsafe { ::std::ffi::CStr::from_ptr(instantiation_token) }.to_string_lossy();
288 let resource_path = ::std::path::PathBuf::from(
289 unsafe { ::std::ffi::CStr::from_ptr(resource_path) }
290 .to_string_lossy()
291 .into_owned(),
292 );
293
294 let intermediate_update: Option<IntermediateUpdateClosure> =
295 intermediate_update.map(|cb| {
296 let closure: IntermediateUpdateClosure = Box::new(
297 move |time: f64,
298 variable_set_requested: bool,
299 variable_get_allowed: bool,
300 step_finished: bool,
301 can_return_early: bool|
302 -> Option<f64> {
303 let mut early_return_requested: binding::fmi3Boolean = false.into();
304 let mut early_return_time: binding::fmi3Float64 = 0.0;
305 unsafe {
306 cb(
307 std::ptr::null_mut() as binding::fmi3InstanceEnvironment,
308 time,
309 variable_set_requested.into(),
310 variable_get_allowed.into(),
311 step_finished.into(),
312 can_return_early.into(),
313 &mut early_return_requested as *mut binding::fmi3Boolean,
314 &mut early_return_time as *mut binding::fmi3Float64,
315 )
316 };
317
318 if early_return_requested.into() {
319 Some(early_return_time)
320 } else {
321 None
322 }
323 },
324 );
325 closure
326 });
327
328 if !Self::SUPPORTS_CO_SIMULATION {
330 eprintln!("Co-Simulation not supported by this FMU");
331 return ::std::ptr::null_mut();
332 }
333
334 let logging_on = _logging_on.into();
335 let log_message: LogMessageClosure = if let Some(cb) = _log_message {
336 Box::new(
337 move |status: Fmi3Status, category: &str, args: std::fmt::Arguments<'_>| {
338 let category_c = CString::new(category).unwrap_or_default();
339 let message_c = CString::new(args.to_string()).unwrap_or_default();
340 unsafe {
341 cb(
342 std::ptr::null_mut() as binding::fmi3InstanceEnvironment,
343 status.into(),
344 category_c.as_ptr(),
345 message_c.as_ptr(),
346 )
347 };
348 },
349 )
350 } else {
351 Box::new(
352 move |status: Fmi3Status, category: &str, args: std::fmt::Arguments<'_>| {
353 let category_c = CString::new(category).unwrap_or_default();
354 let message_c = CString::new(args.to_string()).unwrap_or_default();
355 eprintln!(
356 "Log (status: {:?}, category: {}): {}",
357 status,
358 category_c.to_string_lossy(),
359 message_c.to_string_lossy()
360 );
361 },
362 )
363 };
364
365 let early_return_allowed = _early_return_allowed.into();
366 let context = BasicContext::new(
367 logging_on,
368 log_message,
369 resource_path,
370 early_return_allowed,
371 intermediate_update,
372 );
373
374 match crate::fmi3::ModelInstance::<Self, BasicContext<Self>>::new(
375 name,
376 &token,
377 context,
378 fmi::InterfaceType::CoSimulation,
379 ) {
380 Ok(instance) => ::std::boxed::Box::into_raw(::std::boxed::Box::new(instance))
381 as binding::fmi3Instance,
382 Err(_) => {
383 eprintln!("Failed to instantiate FMU: invalid instantiation token");
384 ::std::ptr::null_mut()
385 }
386 }
387 }
388
389 #[inline(always)]
390 unsafe fn fmi3_instantiate_scheduled_execution(
391 instance_name: binding::fmi3String,
392 instantiation_token: binding::fmi3String,
393 resource_path: binding::fmi3String,
394 _visible: binding::fmi3Boolean,
395 _logging_on: binding::fmi3Boolean,
396 _instance_environment: binding::fmi3InstanceEnvironment,
397 _log_message: binding::fmi3LogMessageCallback,
398 _clock_update: binding::fmi3ClockUpdateCallback,
399 _lock_preemption: binding::fmi3LockPreemptionCallback,
400 _unlock_preemption: binding::fmi3UnlockPreemptionCallback,
401 ) -> binding::fmi3Instance {
402 let _name = unsafe { ::std::ffi::CStr::from_ptr(instance_name) }
403 .to_string_lossy()
404 .into_owned();
405 let _token = unsafe { ::std::ffi::CStr::from_ptr(instantiation_token) }.to_string_lossy();
406 let _resource_path = ::std::path::PathBuf::from(
407 unsafe { ::std::ffi::CStr::from_ptr(resource_path) }
408 .to_string_lossy()
409 .into_owned(),
410 );
411
412 todo!("Scheduled-Execution not yet implemented");
413 }
414
415 #[inline(always)]
416 unsafe fn fmi3_free_instance(instance: binding::fmi3Instance) {
417 if instance.is_null() {
418 eprintln!("Invalid FMU instance");
419 return;
420 }
421
422 let instance_type = unsafe {
425 let temp = instance
426 as *const crate::fmi3::ModelInstance<
427 Self,
428 crate::fmi3::instance::context::BasicContext<Self>,
429 >;
430 (*temp).instance_type()
431 };
432
433 match instance_type {
435 fmi::InterfaceType::ModelExchange => {
436 let _this = unsafe {
437 ::std::boxed::Box::from_raw(
438 instance
439 as *mut crate::fmi3::ModelInstance<
440 Self,
441 crate::fmi3::instance::context::BasicContext<Self>,
442 >,
443 )
444 };
445 _this.context().log(
446 Fmi3Res::OK.into(),
447 Default::default(),
448 format_args!("{}: fmi3FreeInstance()", _this.instance_name()),
449 );
450 }
452 fmi::InterfaceType::CoSimulation => {
453 let _this = unsafe {
454 ::std::boxed::Box::from_raw(
455 instance
456 as *mut crate::fmi3::ModelInstance<
457 Self,
458 crate::fmi3::instance::context::BasicContext<Self>,
459 >,
460 )
461 };
462 _this.context().log(
463 Fmi3Res::OK.into(),
464 Default::default(),
465 format_args!("{}: fmi3FreeInstance()", _this.instance_name()),
466 );
467 }
469 fmi::InterfaceType::ScheduledExecution => {
470 eprintln!("Scheduled Execution not yet implemented");
472 }
473 }
474 }
475
476 #[inline(always)]
477 unsafe fn fmi3_enter_initialization_mode(
478 instance: binding::fmi3Instance,
479 tolerance_defined: binding::fmi3Boolean,
480 tolerance: binding::fmi3Float64,
481 start_time: binding::fmi3Float64,
482 stop_time_defined: binding::fmi3Boolean,
483 stop_time: binding::fmi3Float64,
484 ) -> binding::fmi3Status {
485 let tolerance = tolerance_defined.then_some(tolerance);
486 let stop_time = stop_time_defined.then_some(stop_time);
487 match dispatch_by_instance_type!(
488 instance,
489 Self,
490 enter_initialization_mode,
491 tolerance,
492 start_time,
493 stop_time
494 ) {
495 Ok(res) => {
496 let status: Fmi3Status = res.into();
497 status.into()
498 }
499 Err(_) => binding::fmi3Status_fmi3Error,
500 }
501 }
502
503 #[inline(always)]
504 unsafe fn fmi3_exit_initialization_mode(
505 instance: binding::fmi3Instance,
506 ) -> binding::fmi3Status {
507 match dispatch_by_instance_type!(instance, Self, exit_initialization_mode) {
508 Ok(res) => {
509 let status: Fmi3Status = res.into();
510 status.into()
511 }
512 Err(_) => binding::fmi3Status_fmi3Error,
513 }
514 }
515
516 #[inline(always)]
517 unsafe fn fmi3_enter_event_mode(instance: binding::fmi3Instance) -> binding::fmi3Status {
518 match dispatch_by_instance_type!(instance, Self, enter_event_mode) {
519 Ok(res) => {
520 let status: Fmi3Status = res.into();
521 status.into()
522 }
523 Err(_) => binding::fmi3Status_fmi3Error,
524 }
525 }
526
527 #[inline(always)]
528 unsafe fn fmi3_terminate(instance: binding::fmi3Instance) -> binding::fmi3Status {
529 match dispatch_by_instance_type!(instance, Self, terminate) {
530 Ok(res) => {
531 let status: Fmi3Status = res.into();
532 status.into()
533 }
534 Err(_) => binding::fmi3Status_fmi3Error,
535 }
536 }
537
538 #[inline(always)]
539 unsafe fn fmi3_reset(instance: binding::fmi3Instance) -> binding::fmi3Status {
540 match dispatch_by_instance_type!(instance, Self, reset) {
541 Ok(res) => {
542 let status: Fmi3Status = res.into();
543 status.into()
544 }
545 Err(_) => binding::fmi3Status_fmi3Error,
546 }
547 }
548
549 #[inline(always)]
551 unsafe fn fmi3_get_fmu_state(
552 _instance: binding::fmi3Instance,
553 _fmu_state: *mut binding::fmi3FMUState,
554 ) -> binding::fmi3Status {
555 todo!("FMU state not yet implemented");
556 }
557
558 #[inline(always)]
559 unsafe fn fmi3_set_fmu_state(
560 _instance: binding::fmi3Instance,
561 _fmu_state: binding::fmi3FMUState,
562 ) -> binding::fmi3Status {
563 todo!("FMU state not yet implemented");
564 }
565
566 #[inline(always)]
567 unsafe fn fmi3_free_fmu_state(
568 _instance: binding::fmi3Instance,
569 _fmu_state: *mut binding::fmi3FMUState,
570 ) -> binding::fmi3Status {
571 todo!("FMU state not yet implemented");
572 }
573
574 #[inline(always)]
575 unsafe fn fmi3_serialized_fmu_state_size(
576 _instance: binding::fmi3Instance,
577 _fmu_state: binding::fmi3FMUState,
578 _size: *mut usize,
579 ) -> binding::fmi3Status {
580 todo!("FMU state not yet implemented");
581 }
582
583 #[inline(always)]
584 unsafe fn fmi3_serialize_fmu_state(
585 _instance: binding::fmi3Instance,
586 _fmu_state: binding::fmi3FMUState,
587 _serialized_state: *mut binding::fmi3Byte,
588 _size: usize,
589 ) -> binding::fmi3Status {
590 todo!("FMU state not yet implemented");
591 }
592
593 #[inline(always)]
594 unsafe fn fmi3_deserialize_fmu_state(
595 _instance: binding::fmi3Instance,
596 _serialized_state: *const binding::fmi3Byte,
597 _size: usize,
598 _fmu_state: *mut binding::fmi3FMUState,
599 ) -> binding::fmi3Status {
600 todo!("FMU state not yet implemented");
601 }
602
603 #[inline(always)]
605 unsafe fn fmi3_get_directional_derivative(
606 _instance: binding::fmi3Instance,
607 _unknowns: *const binding::fmi3ValueReference,
608 _n_unknowns: usize,
609 _knowns: *const binding::fmi3ValueReference,
610 _n_knowns: usize,
611 _seed: *const binding::fmi3Float64,
612 _n_seed: usize,
613 _sensitivity: *mut binding::fmi3Float64,
614 _n_sensitivity: usize,
615 ) -> binding::fmi3Status {
616 todo!("Directional derivative not yet implemented");
618 }
619
620 #[inline(always)]
621 unsafe fn fmi3_get_adjoint_derivative(
622 _instance: binding::fmi3Instance,
623 _unknowns: *const binding::fmi3ValueReference,
624 _n_unknowns: usize,
625 _knowns: *const binding::fmi3ValueReference,
626 _n_knowns: usize,
627 _seed: *const binding::fmi3Float64,
628 _n_seed: usize,
629 _sensitivity: *mut binding::fmi3Float64,
630 _n_sensitivity: usize,
631 ) -> binding::fmi3Status {
632 todo!("Adjoint derivative not yet implemented");
634 }
635
636 #[inline(always)]
638 unsafe fn fmi3_enter_configuration_mode(
639 instance: binding::fmi3Instance,
640 ) -> binding::fmi3Status {
641 match dispatch_by_instance_type!(instance, Self, enter_configuration_mode) {
642 Ok(res) => {
643 let status: Fmi3Status = res.into();
644 status.into()
645 }
646 Err(_) => binding::fmi3Status_fmi3Error,
647 }
648 }
649
650 #[inline(always)]
651 unsafe fn fmi3_exit_configuration_mode(instance: binding::fmi3Instance) -> binding::fmi3Status {
652 match dispatch_by_instance_type!(instance, Self, exit_configuration_mode) {
653 Ok(res) => {
654 let status: Fmi3Status = res.into();
655 status.into()
656 }
657 Err(_) => binding::fmi3Status_fmi3Error,
658 }
659 }
660
661 #[inline(always)]
663 unsafe fn fmi3_get_interval_decimal(
664 _instance: binding::fmi3Instance,
665 _value_references: *const binding::fmi3ValueReference,
666 _n_value_references: usize,
667 _intervals: *mut binding::fmi3Float64,
668 _qualifiers: *mut binding::fmi3IntervalQualifier,
669 ) -> binding::fmi3Status {
670 todo!("Clock interval not yet implemented");
672 }
673
674 #[inline(always)]
675 unsafe fn fmi3_get_interval_fraction(
676 _instance: binding::fmi3Instance,
677 _value_references: *const binding::fmi3ValueReference,
678 _n_value_references: usize,
679 _counters: *mut binding::fmi3UInt64,
680 _resolutions: *mut binding::fmi3UInt64,
681 _qualifiers: *mut binding::fmi3IntervalQualifier,
682 ) -> binding::fmi3Status {
683 todo!("Clock interval not yet implemented");
685 }
686
687 #[inline(always)]
688 unsafe fn fmi3_get_shift_decimal(
689 _instance: binding::fmi3Instance,
690 _value_references: *const binding::fmi3ValueReference,
691 _n_value_references: usize,
692 _shifts: *mut binding::fmi3Float64,
693 ) -> binding::fmi3Status {
694 todo!("Clock interval not yet implemented");
696 }
697
698 #[inline(always)]
699 unsafe fn fmi3_get_shift_fraction(
700 _instance: binding::fmi3Instance,
701 _value_references: *const binding::fmi3ValueReference,
702 _n_value_references: usize,
703 _counters: *mut binding::fmi3UInt64,
704 _resolutions: *mut binding::fmi3UInt64,
705 ) -> binding::fmi3Status {
706 todo!("Clock interval not yet implemented");
708 }
709
710 #[inline(always)]
711 unsafe fn fmi3_set_interval_decimal(
712 _instance: binding::fmi3Instance,
713 _value_references: *const binding::fmi3ValueReference,
714 _n_value_references: usize,
715 _intervals: *const binding::fmi3Float64,
716 ) -> binding::fmi3Status {
717 todo!("Clock interval not yet implemented");
719 }
720
721 #[inline(always)]
722 unsafe fn fmi3_set_interval_fraction(
723 _instance: binding::fmi3Instance,
724 _value_references: *const binding::fmi3ValueReference,
725 _n_value_references: usize,
726 _counters: *const binding::fmi3UInt64,
727 _resolutions: *const binding::fmi3UInt64,
728 ) -> binding::fmi3Status {
729 todo!("Clock interval not yet implemented");
731 }
732
733 #[inline(always)]
734 unsafe fn fmi3_set_shift_decimal(
735 _instance: binding::fmi3Instance,
736 _value_references: *const binding::fmi3ValueReference,
737 _n_value_references: usize,
738 _shifts: *const binding::fmi3Float64,
739 ) -> binding::fmi3Status {
740 todo!("Clock interval not yet implemented");
742 }
743
744 #[inline(always)]
745 unsafe fn fmi3_set_shift_fraction(
746 _instance: binding::fmi3Instance,
747 _value_references: *const binding::fmi3ValueReference,
748 _n_value_references: usize,
749 _counters: *const binding::fmi3UInt64,
750 _resolutions: *const binding::fmi3UInt64,
751 ) -> binding::fmi3Status {
752 todo!("Clock interval not yet implemented");
754 }
755
756 #[inline(always)]
757 unsafe fn fmi3_evaluate_discrete_states(
758 _instance: binding::fmi3Instance,
759 ) -> binding::fmi3Status {
760 todo!("Discrete states not yet implemented");
762 }
763
764 #[inline(always)]
765 unsafe fn fmi3_update_discrete_states(
766 instance: binding::fmi3Instance,
767 discrete_states_need_update: *mut binding::fmi3Boolean,
768 terminate_simulation: *mut binding::fmi3Boolean,
769 nominals_of_continuous_states_changed: *mut binding::fmi3Boolean,
770 values_of_continuous_states_changed: *mut binding::fmi3Boolean,
771 next_event_time_defined: *mut binding::fmi3Boolean,
772 next_event_time: *mut binding::fmi3Float64,
773 ) -> binding::fmi3Status {
774 let mut event_flags = ::fmi::EventFlags::default();
775
776 if unsafe { *next_event_time_defined } {
778 event_flags.next_event_time = Some(unsafe { *next_event_time });
779 }
780
781 match dispatch_by_instance_type!(instance, Self, update_discrete_states, &mut event_flags) {
782 Ok(res) => {
783 unsafe {
784 *discrete_states_need_update = event_flags.discrete_states_need_update;
785 *terminate_simulation = event_flags.terminate_simulation;
786 *nominals_of_continuous_states_changed =
787 event_flags.nominals_of_continuous_states_changed;
788 *values_of_continuous_states_changed =
789 event_flags.values_of_continuous_states_changed;
790
791 if let Some(event_time) = event_flags.next_event_time {
792 *next_event_time_defined = true;
793 *next_event_time = event_time;
794 } else {
795 *next_event_time_defined = false;
796 *next_event_time = 0.0;
797 }
798 }
799
800 let status: Fmi3Status = res.into();
801 status.into()
802 }
803 Err(_) => binding::fmi3Status_fmi3Error,
804 }
805 }
806
807 wrapper_getset_functions!(Float64, binding::fmi3Float64, get_float64, set_float64);
808 wrapper_getset_functions!(Float32, binding::fmi3Float32, get_float32, set_float32);
809 wrapper_getset_functions!(Int64, binding::fmi3Int64, get_int64, set_int64);
810 wrapper_getset_functions!(Int32, binding::fmi3Int32, get_int32, set_int32);
811 wrapper_getset_functions!(Int16, binding::fmi3Int16, get_int16, set_int16);
812 wrapper_getset_functions!(Int8, binding::fmi3Int8, get_int8, set_int8);
813 wrapper_getset_functions!(UInt64, binding::fmi3UInt64, get_uint64, set_uint64);
814 wrapper_getset_functions!(UInt32, binding::fmi3UInt32, get_uint32, set_uint32);
815 wrapper_getset_functions!(UInt16, binding::fmi3UInt16, get_uint16, set_uint16);
816 wrapper_getset_functions!(UInt8, binding::fmi3UInt8, get_uint8, set_uint8);
817 wrapper_getset_functions!(Boolean, binding::fmi3Boolean, get_boolean, set_boolean);
818
819 #[inline(always)]
821 unsafe fn fmi3_get_string(
822 instance: binding::fmi3Instance,
823 value_references: *const binding::fmi3ValueReference,
824 n_value_references: usize,
825 values: *mut binding::fmi3String,
826 n_values: usize,
827 ) -> binding::fmi3Status {
828 if n_value_references != n_values {
829 eprintln!(
830 "FMI3: Array length mismatch in fmi3GetString: value_references={}, values={}",
831 n_value_references, n_values
832 );
833 return binding::fmi3Status_fmi3Error;
834 }
835
836 let value_refs =
837 unsafe { ::std::slice::from_raw_parts(value_references, n_value_references) };
838
839 let mut temp_strings = vec![::std::ffi::CString::default(); n_values];
841
842 match dispatch_by_instance_type!(instance, Self, get_string, value_refs, &mut temp_strings)
843 {
844 Ok(_) => {
845 let values_slice = unsafe { ::std::slice::from_raw_parts_mut(values, n_values) };
847 for (i, cstring) in temp_strings.iter().enumerate() {
848 values_slice[i] = cstring.as_ptr();
849 }
850 binding::fmi3Status_fmi3OK
851 }
852 Err(_) => binding::fmi3Status_fmi3Error,
853 }
854 }
855
856 #[inline(always)]
857 unsafe fn fmi3_set_string(
858 instance: binding::fmi3Instance,
859 value_references: *const binding::fmi3ValueReference,
860 n_value_references: usize,
861 values: *const binding::fmi3String,
862 n_values: usize,
863 ) -> binding::fmi3Status {
864 if n_value_references != n_values {
865 eprintln!(
866 "FMI3: Array length mismatch in fmi3SetString: value_references={}, values={}",
867 n_value_references, n_values
868 );
869 return binding::fmi3Status_fmi3Error;
870 }
871
872 let value_refs =
873 unsafe { ::std::slice::from_raw_parts(value_references, n_value_references) };
874 let string_ptrs = unsafe { ::std::slice::from_raw_parts(values, n_values) };
875
876 let mut temp_strings = Vec::with_capacity(n_values);
878 for &ptr in string_ptrs {
879 if ptr.is_null() {
880 temp_strings.push(CString::default());
881 } else {
882 let cstring = unsafe { ::std::ffi::CStr::from_ptr(ptr) }.to_owned();
883 temp_strings.push(cstring);
884 }
885 }
886
887 match dispatch_by_instance_type!(instance, Self, set_string, value_refs, &temp_strings) {
888 Ok(_) => binding::fmi3Status_fmi3OK,
889 Err(_) => binding::fmi3Status_fmi3Error,
890 }
891 }
892
893 #[inline(always)]
895 unsafe fn fmi3_get_binary(
896 instance: binding::fmi3Instance,
897 value_references: *const binding::fmi3ValueReference,
898 n_value_references: usize,
899 value_sizes: *mut usize,
900 values: *mut *mut binding::fmi3Byte,
901 n_values: usize,
902 ) -> binding::fmi3Status {
903 if n_value_references != n_values {
904 eprintln!(
905 "FMI3: Array length mismatch in fmi3GetBinary: value_references={}, values={}",
906 n_value_references, n_values
907 );
908 return binding::fmi3Status_fmi3Error;
909 }
910
911 let value_refs =
912 unsafe { ::std::slice::from_raw_parts(value_references, n_value_references) };
913 let sizes_slice = unsafe { ::std::slice::from_raw_parts_mut(value_sizes, n_values) };
914 let values_slice = unsafe { ::std::slice::from_raw_parts_mut(values, n_values) };
915
916 let mut temp_buffers: Vec<&mut [u8]> = Vec::with_capacity(n_values);
918 for i in 0..n_values {
919 if values_slice[i].is_null() || sizes_slice[i] == 0 {
920 temp_buffers.push(&mut []);
921 } else {
922 let buffer =
923 unsafe { ::std::slice::from_raw_parts_mut(values_slice[i], sizes_slice[i]) };
924 temp_buffers.push(buffer);
925 }
926 }
927
928 match dispatch_by_instance_type!(instance, Self, get_binary, value_refs, &mut temp_buffers)
929 {
930 Ok(actual_sizes) => {
931 for (i, &size) in actual_sizes.iter().enumerate() {
933 sizes_slice[i] = size;
934 }
935 binding::fmi3Status_fmi3OK
936 }
937 Err(_) => binding::fmi3Status_fmi3Error,
938 }
939 }
940
941 #[inline(always)]
942 unsafe fn fmi3_set_binary(
943 instance: binding::fmi3Instance,
944 value_references: *const binding::fmi3ValueReference,
945 n_value_references: usize,
946 value_sizes: *const usize,
947 values: *const *const binding::fmi3Byte,
948 n_values: usize,
949 ) -> binding::fmi3Status {
950 if n_value_references != n_values {
951 eprintln!(
952 "FMI3: Array length mismatch in fmi3SetBinary: value_references={}, values={}",
953 n_value_references, n_values
954 );
955 return binding::fmi3Status_fmi3Error;
956 }
957
958 let value_refs =
959 unsafe { ::std::slice::from_raw_parts(value_references, n_value_references) };
960 let sizes_slice = unsafe { ::std::slice::from_raw_parts(value_sizes, n_values) };
961 let values_slice = unsafe { ::std::slice::from_raw_parts(values, n_values) };
962
963 let mut temp_buffers: Vec<&[u8]> = Vec::with_capacity(n_values);
965 for i in 0..n_values {
966 if values_slice[i].is_null() || sizes_slice[i] == 0 {
967 temp_buffers.push(&[]);
968 } else {
969 let buffer =
970 unsafe { ::std::slice::from_raw_parts(values_slice[i], sizes_slice[i]) };
971 temp_buffers.push(buffer);
972 }
973 }
974
975 match dispatch_by_instance_type!(instance, Self, set_binary, value_refs, &temp_buffers) {
976 Ok(_) => binding::fmi3Status_fmi3OK,
977 Err(_) => binding::fmi3Status_fmi3Error,
978 }
979 }
980
981 #[inline(always)]
983 unsafe fn fmi3_get_clock(
984 instance: binding::fmi3Instance,
985 value_references: *const binding::fmi3ValueReference,
986 n_value_references: usize,
987 values: *mut binding::fmi3Clock,
988 ) -> binding::fmi3Status {
989 let value_refs =
990 unsafe { ::std::slice::from_raw_parts(value_references, n_value_references) };
991 let values_slice = unsafe { ::std::slice::from_raw_parts_mut(values, n_value_references) };
992 match dispatch_by_instance_type!(instance, Self, get_clock, value_refs, values_slice) {
993 Ok(res) => {
994 let status: Fmi3Status = res.into();
995 status.into()
996 }
997 Err(_) => binding::fmi3Status_fmi3Error,
998 }
999 }
1000
1001 #[inline(always)]
1002 unsafe fn fmi3_set_clock(
1003 instance: binding::fmi3Instance,
1004 value_references: *const binding::fmi3ValueReference,
1005 n_value_references: usize,
1006 values: *const binding::fmi3Clock,
1007 ) -> binding::fmi3Status {
1008 let value_refs =
1009 unsafe { ::std::slice::from_raw_parts(value_references, n_value_references) };
1010 let values_slice = unsafe { ::std::slice::from_raw_parts(values, n_value_references) };
1011 match dispatch_by_instance_type!(instance, Self, set_clock, value_refs, values_slice) {
1012 Ok(res) => {
1013 let status: Fmi3Status = res.into();
1014 status.into()
1015 }
1016 Err(_) => binding::fmi3Status_fmi3Error,
1017 }
1018 }
1019
1020 #[inline(always)]
1022 unsafe fn fmi3_get_number_of_variable_dependencies(
1023 instance: binding::fmi3Instance,
1024 value_reference: binding::fmi3ValueReference,
1025 n_dependencies: *mut usize,
1026 ) -> binding::fmi3Status {
1027 match dispatch_by_instance_type!(
1028 instance,
1029 Self,
1030 get_number_of_variable_dependencies,
1031 value_reference
1032 ) {
1033 Ok(res) => {
1034 unsafe {
1035 *n_dependencies = res;
1036 }
1037 binding::fmi3Status_fmi3OK
1038 }
1039 Err(_) => binding::fmi3Status_fmi3Error,
1040 }
1041 }
1042
1043 #[inline(always)]
1044 unsafe fn fmi3_get_variable_dependencies(
1045 instance: binding::fmi3Instance,
1046 dependent: binding::fmi3ValueReference,
1047 element_indices_of_dependent: *mut usize,
1048 independents: *mut binding::fmi3ValueReference,
1049 element_indices_of_independents: *mut usize,
1050 dependency_kinds: *mut binding::fmi3DependencyKind,
1051 n_dependencies: usize,
1052 ) -> binding::fmi3Status {
1053 let dependent_vr = dependent.into();
1055
1056 match dispatch_by_instance_type!(instance, Self, get_variable_dependencies, dependent_vr) {
1058 Ok(dependencies) => {
1059 if dependencies.len() > n_dependencies {
1061 eprintln!(
1062 "Buffer too small: {} dependencies returned but only {} allocated",
1063 dependencies.len(),
1064 n_dependencies
1065 );
1066 return binding::fmi3Status_fmi3Error;
1067 }
1068
1069 for (i, dep) in dependencies.iter().enumerate() {
1071 if i >= n_dependencies {
1072 break; }
1074
1075 unsafe {
1076 *element_indices_of_dependent.add(i) = dep.dependent_element_index;
1078
1079 *independents.add(i) = dep.independent.into();
1081
1082 *element_indices_of_independents.add(i) = dep.independent_element_index;
1084
1085 *dependency_kinds.add(i) = dep.dependency_kind;
1087 }
1088 }
1089
1090 binding::fmi3Status_fmi3OK
1091 }
1092 Err(e) => {
1093 eprintln!("Failed to get variable dependencies: {:?}", e);
1094 Fmi3Status::from(e).into()
1095 }
1096 }
1097 }
1098}
1099
1100pub trait Fmi3ModelExchange: Fmi3Common + ModelGetSetStates
1102where
1103 ModelInstance<Self, BasicContext<Self>>: fmi::fmi3::ModelExchange,
1104{
1105 #[inline(always)]
1106 unsafe fn fmi3_enter_continuous_time_mode(
1107 instance: binding::fmi3Instance,
1108 ) -> binding::fmi3Status {
1109 match dispatch_by_instance_type!(instance, Self, enter_continuous_time_mode) {
1110 Ok(res) => {
1111 let status: Fmi3Status = res.into();
1112 status.into()
1113 }
1114 Err(_) => binding::fmi3Status_fmi3Error,
1115 }
1116 }
1117
1118 #[inline(always)]
1119 unsafe fn fmi3_completed_integrator_step(
1120 instance: binding::fmi3Instance,
1121 no_set_fmu_state_prior: binding::fmi3Boolean,
1122 enter_event_mode: *mut binding::fmi3Boolean,
1123 terminate_simulation: *mut binding::fmi3Boolean,
1124 ) -> binding::fmi3Status {
1125 let mut enter_event = false;
1126 let mut terminate = false;
1127 match dispatch_by_instance_type!(
1128 instance,
1129 Self,
1130 completed_integrator_step,
1131 no_set_fmu_state_prior,
1132 &mut enter_event,
1133 &mut terminate
1134 ) {
1135 Ok(_) => {
1136 unsafe {
1137 *enter_event_mode = enter_event;
1138 *terminate_simulation = terminate;
1139 }
1140 binding::fmi3Status_fmi3OK
1141 }
1142 Err(_) => binding::fmi3Status_fmi3Error,
1143 }
1144 }
1145
1146 #[inline(always)]
1147 unsafe fn fmi3_set_time(
1148 instance: binding::fmi3Instance,
1149 time: binding::fmi3Float64,
1150 ) -> binding::fmi3Status {
1151 match dispatch_by_instance_type!(instance, Self, set_time, time) {
1152 Ok(res) => {
1153 let status: Fmi3Status = res.into();
1154 status.into()
1155 }
1156 Err(_) => binding::fmi3Status_fmi3Error,
1157 }
1158 }
1159
1160 #[inline(always)]
1161 unsafe fn fmi3_set_continuous_states(
1162 instance: binding::fmi3Instance,
1163 continuous_states: *const binding::fmi3Float64,
1164 n_continuous_states: usize,
1165 ) -> binding::fmi3Status {
1166 let states =
1167 unsafe { ::std::slice::from_raw_parts(continuous_states, n_continuous_states) };
1168 match dispatch_by_instance_type!(instance, Self, set_continuous_states, states) {
1169 Ok(res) => {
1170 let status: Fmi3Status = res.into();
1171 status.into()
1172 }
1173 Err(_) => binding::fmi3Status_fmi3Error,
1174 }
1175 }
1176
1177 #[inline(always)]
1178 unsafe fn fmi3_get_continuous_state_derivatives(
1179 instance: binding::fmi3Instance,
1180 derivatives: *mut binding::fmi3Float64,
1181 n_continuous_states: usize,
1182 ) -> binding::fmi3Status {
1183 let derivs = unsafe { ::std::slice::from_raw_parts_mut(derivatives, n_continuous_states) };
1184 match dispatch_by_instance_type!(instance, Self, get_continuous_state_derivatives, derivs) {
1185 Ok(res) => {
1186 let status: Fmi3Status = res.into();
1187 status.into()
1188 }
1189 Err(_) => binding::fmi3Status_fmi3Error,
1190 }
1191 }
1192
1193 #[inline(always)]
1194 unsafe fn fmi3_get_event_indicators(
1195 instance: binding::fmi3Instance,
1196 event_indicators: *mut binding::fmi3Float64,
1197 n_event_indicators: usize,
1198 ) -> binding::fmi3Status {
1199 let indicators =
1200 unsafe { ::std::slice::from_raw_parts_mut(event_indicators, n_event_indicators) };
1201 match dispatch_by_instance_type!(instance, Self, get_event_indicators, indicators) {
1202 Ok(_) => binding::fmi3Status_fmi3OK,
1203 Err(_) => binding::fmi3Status_fmi3Error,
1204 }
1205 }
1206
1207 #[inline(always)]
1208 unsafe fn fmi3_get_continuous_states(
1209 instance: binding::fmi3Instance,
1210 continuous_states: *mut binding::fmi3Float64,
1211 n_continuous_states: usize,
1212 ) -> binding::fmi3Status {
1213 let states =
1214 unsafe { ::std::slice::from_raw_parts_mut(continuous_states, n_continuous_states) };
1215 match dispatch_by_instance_type!(instance, Self, get_continuous_states, states) {
1216 Ok(res) => {
1217 let status: Fmi3Status = res.into();
1218 status.into()
1219 }
1220 Err(_) => binding::fmi3Status_fmi3Error,
1221 }
1222 }
1223
1224 #[inline(always)]
1225 unsafe fn fmi3_get_nominals_of_continuous_states(
1226 instance: binding::fmi3Instance,
1227 nominals: *mut binding::fmi3Float64,
1228 n_continuous_states: usize,
1229 ) -> binding::fmi3Status {
1230 let nominals = unsafe { ::std::slice::from_raw_parts_mut(nominals, n_continuous_states) };
1231 match dispatch_by_instance_type!(
1232 instance,
1233 Self,
1234 get_nominals_of_continuous_states,
1235 nominals
1236 ) {
1237 Ok(res) => {
1238 let status: Fmi3Status = res.into();
1239 status.into()
1240 }
1241 Err(_) => binding::fmi3Status_fmi3Error,
1242 }
1243 }
1244
1245 #[inline(always)]
1246 unsafe fn fmi3_get_number_of_event_indicators(
1247 instance: binding::fmi3Instance,
1248 n_event_indicators: *mut usize,
1249 ) -> binding::fmi3Status {
1250 match dispatch_by_instance_type!(instance, Self, get_number_of_event_indicators) {
1251 Ok(n) => {
1252 unsafe {
1253 *n_event_indicators = n;
1254 }
1255 binding::fmi3Status_fmi3OK
1256 }
1257 Err(_) => binding::fmi3Status_fmi3Error,
1258 }
1259 }
1260
1261 #[inline(always)]
1262 unsafe fn fmi3_get_number_of_continuous_states(
1263 instance: binding::fmi3Instance,
1264 n_continuous_states: *mut usize,
1265 ) -> binding::fmi3Status {
1266 match dispatch_by_instance_type!(instance, Self, get_number_of_continuous_states) {
1267 Ok(n) => {
1268 unsafe {
1269 *n_continuous_states = n;
1270 }
1271 binding::fmi3Status_fmi3OK
1272 }
1273 Err(_) => binding::fmi3Status_fmi3Error,
1274 }
1275 }
1276}
1277
1278pub trait Fmi3CoSimulation: Fmi3Common + ModelGetSetStates
1280where
1281 ModelInstance<Self, BasicContext<Self>>: fmi::fmi3::CoSimulation,
1282{
1283 #[inline(always)]
1284 unsafe fn fmi3_enter_step_mode(instance: binding::fmi3Instance) -> binding::fmi3Status {
1285 match dispatch_by_instance_type!(instance, Self, enter_step_mode) {
1286 Ok(res) => {
1287 let status: Fmi3Status = res.into();
1288 status.into()
1289 }
1290 Err(_) => binding::fmi3Status_fmi3Error,
1291 }
1292 }
1293
1294 #[inline(always)]
1295 unsafe fn fmi3_get_output_derivatives(
1296 instance: binding::fmi3Instance,
1297 value_references: *const binding::fmi3ValueReference,
1298 n_value_references: usize,
1299 orders: *const binding::fmi3Int32,
1300 values: *mut binding::fmi3Float64,
1301 n_values: usize,
1302 ) -> binding::fmi3Status {
1303 let value_refs =
1304 unsafe { ::std::slice::from_raw_parts(value_references, n_value_references) };
1305 let orders_slice = unsafe { ::std::slice::from_raw_parts(orders, n_value_references) };
1306 let values_slice = unsafe { ::std::slice::from_raw_parts_mut(values, n_values) };
1307 match dispatch_by_instance_type!(
1308 instance,
1309 Self,
1310 get_output_derivatives,
1311 value_refs,
1312 orders_slice,
1313 values_slice
1314 ) {
1315 Ok(res) => {
1316 let status: Fmi3Status = res.into();
1317 status.into()
1318 }
1319 Err(_) => binding::fmi3Status_fmi3Error,
1320 }
1321 }
1322
1323 #[inline(always)]
1324 unsafe fn fmi3_do_step(
1325 instance: binding::fmi3Instance,
1326 current_communication_point: binding::fmi3Float64,
1327 communication_step_size: binding::fmi3Float64,
1328 no_set_fmu_state_prior_to_current_point: binding::fmi3Boolean,
1329 event_handling_needed: *mut binding::fmi3Boolean,
1330 terminate_simulation: *mut binding::fmi3Boolean,
1331 early_return: *mut binding::fmi3Boolean,
1332 last_successful_time: *mut binding::fmi3Float64,
1333 ) -> binding::fmi3Status {
1334 let mut event_handling_needed_tmp = false;
1336 let mut terminate_simulation_tmp = false;
1337 let mut early_return_tmp = false;
1338 let mut last_successful_time_tmp = 0.0;
1339
1340 let event_handling_needed = unsafe {
1341 if event_handling_needed.is_null() {
1342 &mut event_handling_needed_tmp
1343 } else {
1344 &mut *event_handling_needed
1345 }
1346 };
1347 let terminate_simulation = unsafe {
1348 if terminate_simulation.is_null() {
1349 &mut terminate_simulation_tmp
1350 } else {
1351 &mut *terminate_simulation
1352 }
1353 };
1354 let early_return = unsafe {
1355 if early_return.is_null() {
1356 &mut early_return_tmp
1357 } else {
1358 &mut *early_return
1359 }
1360 };
1361 let last_successful_time = unsafe {
1362 if last_successful_time.is_null() {
1363 &mut last_successful_time_tmp
1364 } else {
1365 &mut *last_successful_time
1366 }
1367 };
1368
1369 match dispatch_by_instance_type!(
1370 instance,
1371 Self,
1372 do_step,
1373 current_communication_point,
1374 communication_step_size,
1375 no_set_fmu_state_prior_to_current_point,
1376 event_handling_needed,
1377 terminate_simulation,
1378 early_return,
1379 last_successful_time
1380 ) {
1381 Ok(res) => {
1382 let status: Fmi3Status = res.into();
1383 status.into()
1384 }
1385 Err(e) => fmi::fmi3::Fmi3Status::from(e).into(),
1386 }
1387 }
1388}
1389
1390pub trait Fmi3ScheduledExecution: Fmi3Common + ModelGetSetStates
1391where
1392 ModelInstance<Self, BasicContext<Self>>: fmi::fmi3::ScheduledExecution,
1393{
1394 #[inline(always)]
1395 unsafe fn fmi3_activate_model_partition(
1396 instance: binding::fmi3Instance,
1397 clock_reference: binding::fmi3ValueReference,
1398 activation_time: binding::fmi3Float64,
1399 ) -> binding::fmi3Status {
1400 match dispatch_by_instance_type!(
1401 instance,
1402 Self,
1403 activate_model_partition,
1404 clock_reference.into(),
1405 activation_time
1406 ) {
1407 Ok(res) => {
1408 let status: Fmi3Status = res.into();
1409 status.into()
1410 }
1411 Err(e) => fmi::fmi3::Fmi3Status::from(e).into(),
1412 }
1413 }
1414}
1415
1416impl<T> Fmi3Common for T where T: Model + UserModel + ModelGetSet<Self> + ModelGetSetStates + 'static
1418{}
1419
1420impl<T> Fmi3ModelExchange for T
1421where
1422 T: Model + UserModel + Fmi3Common + ModelGetSetStates + 'static,
1423 ModelInstance<T, BasicContext<T>>: fmi::fmi3::ModelExchange,
1424{
1425}
1426
1427impl<T> Fmi3CoSimulation for T
1428where
1429 T: Model + ModelGetSetStates + UserModel + Fmi3Common + 'static,
1430 ModelInstance<T, BasicContext<T>>: fmi::fmi3::CoSimulation,
1431{
1432}
1433
1434impl<T> Fmi3ScheduledExecution for T where
1435 T: Model + UserModel + ModelGetSetStates + Fmi3Common + 'static
1436{
1437}