fmu_impl.hpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 #ifndef CASADI_FMU_IMPL_HPP
26 #define CASADI_FMU_IMPL_HPP
27 
28 #include "fmu.hpp"
29 #include "importer.hpp"
30 #include "shared_object.hpp"
31 #include "resource.hpp"
32 
34 
35 namespace casadi {
36 
37 // Memory for event iteration
38 struct EventMemory {
39  bool discrete_states_need_update;
40  bool terminate_simulation;
41  bool nominals_of_continuous_states_changed;
42  bool values_of_continuous_states_changed;
43  bool next_event_time_defined;
44  double next_event_time;
45 };
46 
47 // Forward declarations
48 class DaeBuilderInternal;
49 struct FmuMemory;
50 struct InputStruct;
51 
60 class CASADI_EXPORT FmuInternal : public SharedObjectInternal {
61  friend class Fmu;
62  public:
63  // Constructor
64  FmuInternal(const std::string& name,
65  const std::vector<std::string>& scheme_in, const std::vector<std::string>& scheme_out,
66  const std::map<std::string, std::vector<size_t>>& scheme, const std::vector<std::string>& aux);
67 
69  ~FmuInternal() override;
70 
71  // Initialize
72  virtual void init(const DaeBuilderInternal* dae);
73 
74  // Set C API functions
75  virtual void load_functions() = 0;
76 
77  // Enter initialization mode
78  virtual int enter_initialization_mode(void* instance) const = 0;
79 
80  // Exit initialization mode
81  virtual int exit_initialization_mode(void* instance) const = 0;
82 
83  // Enter continuous-time mode
84  virtual int enter_continuous_time_mode(void* instance) const = 0;
85 
86  // Update discrete states
87  virtual int update_discrete_states(void* instance, EventMemory* eventmem) const = 0;
88 
89  // Set real values
90  virtual int set_real(void* instance, const unsigned int* vr, size_t n_vr,
91  const double* values, size_t n_values) const = 0;
92 
93  // Get/evaluate real values
94  virtual int get_real(void* instance, const unsigned int* vr, size_t n_vr,
95  double* values, size_t n_values) const = 0;
96 
97  // Forward mode AD
98  virtual int get_directional_derivative(void* instance, const unsigned int* vr_out, size_t n_out,
99  const unsigned int* vr_in, size_t n_in, const double* seed, size_t n_seed,
100  double* sensitivity, size_t n_sensitivity) const = 0;
101 
102  // Reverse mode AD
103  virtual int get_adjoint_derivative(void* instance, const unsigned int* vr_out, size_t n_out,
104  const unsigned int* vr_in, size_t n_in, const double* seed, size_t n_seed,
105  double* sensitivity, size_t n_sensitivity) const;
106 
107  // Copy values set in DaeBuilder to FMU
108  virtual int set_values(void* instance) const = 0;
109 
110  // Retrieve auxilliary variables from FMU
111  virtual int get_aux(void* instance) = 0;
112 
113  // Finalize
114  void finalize();
115 
119  void disp(std::ostream& stream, bool more) const override;
120 
124  size_t n_in() const { return iind_.size();}
125 
129  size_t n_out() const { return oind_.size();}
130 
131  // Index lookup for input
132  size_t index_in(const std::string& n) const;
133 
134  // Index lookup for output
135  size_t index_out(const std::string& n) const;
136 
137  // Get Jacobian sparsity for a subset of inputs and outputs
138  Sparsity jac_sparsity(const std::vector<size_t>& osub, const std::vector<size_t>& isub) const;
139 
140  // Get Hessian sparsity for a subset of inputs
141  Sparsity hess_sparsity(const std::vector<size_t>& r, const std::vector<size_t>& c) const;
142 
144 
147  std::vector<double> all_nominal_in(size_t i) const;
148  std::vector<double> all_nominal_out(size_t i) const;
150 
151  // Print description of an input
152  std::string desc_in(FmuMemory* m, size_t id, bool more = true) const;
153 
154  // Name of system, per the FMI specification
155  virtual std::string system_infix() const = 0;
156 
157  // DLL suffix, per the FMI specification
158  static std::string dll_suffix();
159 
160  // Load an FMI function
161  template<typename T>
162  T* load_function(const std::string& symname);
163 
164  // Iteration to update discrete states
165  int discrete_states_iter(void* instance) const;
166 
170  int init_mem(FmuMemory* m) const;
171 
172  // New memory object
173  virtual void* instantiate() const = 0;
174 
175  // Free FMU instance
176  virtual void free_instance(void* c) const = 0;
177 
178  // Set value
179  void set(FmuMemory* m, size_t ind, const double* value) const;
180 
181  // Request the calculation of a variable
182  void request(FmuMemory* m, size_t ind) const;
183 
184  // Calculate all requested variables
185  int eval(FmuMemory* m) const;
186 
187  // Get a calculated variable
188  void get(FmuMemory* m, size_t id, double* value) const;
189 
190  // Set forward seeds
191  void set_fwd(FmuMemory* m, casadi_int nseed,
192  const casadi_int* id, const double* v) const;
193 
194  // Set all forward seeds for a single input
195  void set_fwd(FmuMemory* m, size_t ind, const double* v) const;
196 
197  // Request the calculation of forward sensitivities
198  void request_fwd(FmuMemory* m, casadi_int nsens, const casadi_int* id,
199  const casadi_int* wrt_id) const;
200 
201  // Request the calculation of all forward sensitivities for an output
202  void request_fwd(FmuMemory* m, casadi_int ind) const;
203 
204  // Calculate forward directional derivatives
205  int eval_fwd(FmuMemory* m, bool independent_seeds) const;
206 
207  // Calculate forward directional derivatives using AD
208  int eval_ad(FmuMemory* m) const;
209 
210  // Calculate forward directional derivatives using FD
211  int eval_fd(FmuMemory* m, bool independent_seeds) const;
212 
213  // Get forward sensitivities
214  void get_fwd(FmuMemory* m, casadi_int nsens,
215  const casadi_int* id, double* v) const;
216 
217  // Get the forward sensitivities for a single output
218  void get_fwd(FmuMemory* m, size_t ind, double* v) const;
219 
220  // Set adjoint seeds
221  void set_adj(FmuMemory* m, casadi_int nseed,
222  const casadi_int* id, const double* v) const;
223 
224  // Set all adjoint seeds for a single output
225  void set_adj(FmuMemory* m, size_t ind, const double* v) const;
226 
227  // Request the calculation of adjoint sensitivities
228  void request_adj(FmuMemory* m, casadi_int nsens, const casadi_int* id,
229  const casadi_int* wrt_id) const;
230 
231  // Request the calculation of all adjoint sensitivities for an input
232  void request_adj(FmuMemory* m, casadi_int ind) const;
233 
234  // Calculate adjoint sensitivities
235  int eval_adj(FmuMemory* m) const;
236 
237  // Get adjoint sensitivities
238  void get_adj(FmuMemory* m, casadi_int nsens,
239  const casadi_int* id, double* v) const;
240 
241  // Get the adjoint sensitivities for a single input
242  void get_adj(FmuMemory* m, size_t ind, double* v) const;
243 
244  // Gather forward sensitivities
245  void gather_fwd(FmuMemory* m) const;
246 
247  // Gather adjoint sensitivities
248  void gather_adj(FmuMemory* m) const;
249 
250  // Gather user inputs and outputs
251  void gather_io(FmuMemory* m) const;
252 
256  virtual void get_stats(FmuMemory* m, Dict* stats,
257  const std::vector<std::string>& name_in, const InputStruct* in) const = 0;
258 
259  void serialize(SerializingStream& s) const;
260 
261  virtual void serialize_type(SerializingStream& s) const;
262  virtual void serialize_body(SerializingStream& s) const;
263 
264  static FmuInternal* deserialize(DeserializingStream& s);
265 
266  protected:
267  explicit FmuInternal(DeserializingStream& s);
268 
269  // Resource holding unzipped data (notably DLL)
270  // Must come before li_, because of destructor order
271  Resource resource_;
272 
274  std::string name_;
275 
276  // IO scheme
277  std::vector<std::string> scheme_in_, scheme_out_;
278  std::map<std::string, std::vector<size_t>> scheme_;
279 
280  // Auxilliary outputs
281  std::vector<std::string> aux_;
282 
283  // Path to the FMU resource directory
284  std::string resource_loc_;
285 
286  // Tolerance
287  double fmutol_;
288 
289  // Instance name
290  std::string instance_name_;
291 
292  // GUID / instantiation_token
293  std::string instantiation_token_;
294 
295  // Logging?
296  bool logging_on_;
297 
298  // Number of event indicators
299  casadi_int number_of_event_indicators_;
300 
301  // Does the FMU declare analytic derivatives support?
302  bool provides_directional_derivatives_, provides_adjoint_derivatives_;
303 
304  // Does the FMU declare restrictions on instantiation?
305  bool can_be_instantiated_only_once_per_process_;
306 
308  Importer li_;
309 
310  // Mapping from scheme variable to and from FMU variable indices
311  std::vector<size_t> iind_, iind_map_, oind_, oind_map_;
312 
313  // Is there an independent variable?
314  bool has_independent_;
315 
316  // Meta information about the input/output variable subsets
317  std::vector<double> nominal_in_, nominal_out_;
318  std::vector<double> min_in_, min_out_;
319  std::vector<double> max_in_, max_out_;
320  std::vector<std::string> vn_in_, vn_out_;
321  std::vector<unsigned int> vr_in_, vr_out_;
322 
323  // Numerical values for inputs
324  std::vector<double> value_in_;
325 
326  // Reduced space indices for all inputs and outputs
327  std::vector<std::vector<size_t>> ired_, ored_;
328 
329  // Sparsity pattern for extended Jacobian, Hessian
330  Sparsity jac_sp_, hess_sp_;
331 };
332 
333 template<typename T>
334 T* FmuInternal::load_function(const std::string& symname) {
335  // Load the function
336  signal_t f = li_.get_function(symname);
337  // Ensure that it was found
338  casadi_assert(f != 0, "Cannot retrieve '" + symname + "'");
339  // Return function with the right type
340  return reinterpret_cast<T*>(f);
341 }
342 
343 } // namespace casadi
344 
346 
347 #endif // CASADI_FMU_IMPL_HPP
The casadi namespace.
Definition: archiver.hpp:32
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.