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