1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
use std::fmt::Display;
#[derive(Default, Debug, Clone, clap::ValueEnum)]
pub enum SolverArg {
/// Euler solver
#[clap(name = "euler")]
#[default]
Euler,
}
#[derive(Default, Debug, clap::Args)]
/// Perform a ModelExchange simulation
pub struct ModelExchangeOptions {
#[command(flatten)]
pub common: CommonOptions,
/// The solver to use
#[arg(long, default_value = "euler")]
pub solver: SolverArg,
}
#[derive(Default, Debug, clap::Args)]
/// Perform a CoSimulation simulation
pub struct CoSimulationOptions {
#[command(flatten)]
pub common: CommonOptions,
/// Use event mode
#[arg(long)]
pub event_mode_used: bool,
/// Support early-return in Co-Simulation.
#[arg(long)]
pub early_return_allowed: bool,
}
#[derive(Debug, clap::Subcommand)]
pub enum Interface {
#[cfg(feature = "me")]
#[command(alias = "me")]
ModelExchange(ModelExchangeOptions),
#[cfg(feature = "cs")]
#[command(alias = "cs")]
CoSimulation(CoSimulationOptions),
/// Perform a ScheduledExecution simulation
#[cfg(feature = "se")]
ScheduledExecution(CommonOptions),
}
impl Default for Interface {
fn default() -> Self {
// if only CS is enabled, use CS as default
#[cfg(all(not(feature = "me"), feature = "cs"))]
{
Self::CoSimulation(Default::default())
}
// if both ME and CS are enabled, use CS as default
#[cfg(all(feature = "me", feature = "cs"))]
{
Self::CoSimulation(Default::default())
}
// if only ME is enabled, use ME as default
#[cfg(all(feature = "me", not(feature = "cs")))]
{
Self::ModelExchange(Default::default())
}
}
}
impl Display for Interface {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
#[cfg(feature = "me")]
Self::ModelExchange(_) => write!(f, "ModelExchange"),
#[cfg(feature = "cs")]
Self::CoSimulation(_) => write!(f, "CoSimulation"),
#[cfg(feature = "se")]
Self::ScheduledExecution(_) => write!(f, "ScheduledExecution"),
}
}
}
#[derive(Default, Debug, clap::Args)]
pub struct CommonOptions {
/// File containing initial serialized FMU state.
#[arg(long)]
pub initial_fmu_state_file: Option<std::path::PathBuf>,
/// File to write final serialized FMU state.
#[arg(long)]
pub final_fmu_state_file: Option<std::path::PathBuf>,
/// List of initial values to set before simulation starts. The format is
/// "variableName=value", where variableName is the name of the variable and value is the
/// value to set. The value must be of the same type as the variable. The variable name must
/// be a valid FMI variable name, i.e. it must be a valid identifier and it must be unique.
#[arg(short = 'v')]
pub initial_values: Vec<String>,
/// Print also left limit values at event points to the output file to investigate event
/// behaviour. Default is to only print values after event handling.
#[arg(short = 'd')]
pub print_left_limit: bool,
/// Print all variables to the output file. Default is to only print outputs.
#[arg(long = "print-all")]
pub print_all_variables: bool,
/// For ME simulation: Decides step size to use in forward Euler.
/// For CS simulation: Decides communication step size for the stepping.
/// Observe that if a small stepSize is used the number of saved outputs will still be limited
/// by the number of output points. Default is to calculated a step size from the number of
/// output points. See the -n option for how the number of outputs is set.
#[arg(long = "ss")]
pub step_size: Option<f64>,
#[arg(long = "output-interval")]
pub output_interval: Option<f64>,
/// Maximum number of output points. "-n 0" means output at every step and the number of
/// outputs are decided by the -h option. Observe that no interpolation is used, output points
/// are taken at the steps.
#[arg(short = 'n', default_value = "500")]
pub num_steps: usize,
/// Simulation start time, default is to use information from 'DefaultExperiment' as specified
/// in the model description XML.
#[arg(short = 's')]
pub start_time: Option<f64>,
/// Simulation stop time, default is to use information from 'DefaultExperiment' as specified
/// in the model description XML.
#[arg(short = 'f')]
pub stop_time: Option<f64>,
/// Relative tolerance
#[arg(long)]
pub tolerance: Option<f64>,
}
/// Simulate an FMU
#[derive(Default, Debug, clap::Parser)]
#[command(version, about)]
pub struct FmiSimOptions {
/// Which FMI interface to use
#[command(subcommand)]
pub interface: Interface,
/// The FMU model to read
#[arg(long)]
pub model: std::path::PathBuf,
/// Name of the CSV file name with input data.
#[arg(short = 'i', long)]
pub input_file: Option<std::path::PathBuf>,
/// Simulation result output CSV file name. Default is to use standard output.
#[arg(short = 'o', long)]
pub output_file: Option<std::path::PathBuf>,
/// Separator to be used in CSV input/output.
#[arg(short = 'c', default_value = ",")]
pub separator: char,
/// Mangle variable names to avoid quoting (needed for some CSV importing applications, but not
/// according to the CrossCheck rules).
#[arg(short = 'm')]
pub mangle_names: bool,
}