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 {
45 };
46 
47 // Forward declarations
48 class DaeBuilderInternal;
49 class FmuFunction;
50 struct FmuMemory;
51 struct InputStruct;
52 
61 class CASADI_EXPORT FmuInternal : public SharedObjectInternal {
62  friend class Fmu;
63  public:
64  // Constructor
65  FmuInternal(const std::string& name,
66  const std::vector<std::string>& scheme_in, const std::vector<std::string>& scheme_out,
67  const std::map<std::string, std::vector<size_t>>& scheme, const std::vector<std::string>& aux);
68 
70  ~FmuInternal() override;
71 
72  // Initialize
73  virtual void init(const DaeBuilderInternal* dae);
74 
75  // Set C API functions
76  virtual void load_functions() = 0;
77 
78  // Enter initialization mode
79  virtual int enter_initialization_mode(void* instance) const = 0;
80 
81  // Exit initialization mode
82  virtual int exit_initialization_mode(void* instance) const = 0;
83 
84  // Enter continuous-time mode
85  virtual int enter_continuous_time_mode(void* instance) const = 0;
86 
87  // Update discrete states
88  virtual int update_discrete_states(void* instance, EventMemory* eventmem) const = 0;
89 
90  virtual int get_derivatives(void* instance, double* derivatives, size_t nx) const = 0;
91 
92  // Set real values
93  virtual int set_real(void* instance, const unsigned int* vr, size_t n_vr,
94  const double* values, size_t n_values) const = 0;
95 
96  // Get/evaluate real values
97  virtual int get_real(void* instance, const unsigned int* vr, size_t n_vr,
98  double* values, size_t n_values) const = 0;
99 
100  // Forward mode AD
101  virtual int get_directional_derivative(void* instance, const unsigned int* vr_out, size_t n_out,
102  const unsigned int* vr_in, size_t n_in, const double* seed, size_t n_seed,
103  double* sensitivity, size_t n_sensitivity) const = 0;
104 
105  // Reverse mode AD
106  virtual int get_adjoint_derivative(void* instance, const unsigned int* vr_out, size_t n_out,
107  const unsigned int* vr_in, size_t n_in, const double* seed, size_t n_seed,
108  double* sensitivity, size_t n_sensitivity) const;
109 
110  // Copy values set in DaeBuilder to FMU
111  virtual int set_values(void* instance) const = 0;
112 
113  // Retrieve auxilliary variables from FMU
114  virtual int get_aux(void* instance) = 0;
115 
116  // Finalize
117  virtual void finalize();
118 
122  void disp(std::ostream& stream, bool more) const override;
123 
127  size_t n_in() const { return iind_.size();}
128 
132  size_t n_out() const { return oind_.size();}
133 
134  // Index lookup for input
135  size_t index_in(const std::string& n) const;
136 
137  // Index lookup for output
138  size_t index_out(const std::string& n) const;
139 
140  // Get Jacobian sparsity for a subset of inputs and outputs
141  Sparsity jac_sparsity(const std::vector<size_t>& osub, const std::vector<size_t>& isub) const;
142 
143  // Get Hessian sparsity for a subset of inputs
144  Sparsity hess_sparsity(const std::vector<size_t>& r, const std::vector<size_t>& c) const;
145 
147 
150  std::vector<double> all_nominal_in(size_t i) const;
151  std::vector<double> all_nominal_out(size_t i) const;
153 
154  // Print description of an input
155  std::string desc_in(FmuMemory* m, size_t id, bool more = true) const;
156 
157  // Name of system, per the FMI specification
158  virtual std::string system_infix() const = 0;
159 
160  // DLL suffix, per the FMI specification
161  static std::string dll_suffix();
162 
163  // Load an FMI function
164  template<typename T>
165  T* load_function(const std::string& symname);
166 
167  // Iteration to update discrete states
168  int discrete_states_iter(void* instance) const;
169 
173  virtual int init_mem(FmuMemory* m) const;
174 
178  virtual FmuMemory* alloc_mem(const FmuFunction& f) const = 0;
179 
183  virtual void free_mem(void *mem) const = 0;
184 
185  // New memory object
186  virtual void* instantiate() const = 0;
187 
188  // Free FMU instance
189  virtual void free_instance(void* c) const = 0;
190 
191  // Set value
192  void set(FmuMemory* m, size_t ind, const double* value) const;
193 
194  // Request the calculation of a variable
195  void request(FmuMemory* m, size_t ind) const;
196 
197  // Calculate all requested variables
198  int eval(FmuMemory* m) const;
199 
200  // Get a calculated variable
201  void get(FmuMemory* m, size_t id, double* value) const;
202 
203  // Set forward seeds
204  void set_fwd(FmuMemory* m, casadi_int nseed,
205  const casadi_int* id, const double* v) const;
206 
207  // Set all forward seeds for a single input
208  void set_fwd(FmuMemory* m, size_t ind, const double* v) const;
209 
210  // Request the calculation of forward sensitivities
211  void request_fwd(FmuMemory* m, casadi_int nsens, const casadi_int* id,
212  const casadi_int* wrt_id) const;
213 
214  // Request the calculation of all forward sensitivities for an output
215  void request_fwd(FmuMemory* m, casadi_int ind) const;
216 
217  // Calculate forward directional derivatives
218  int eval_fwd(FmuMemory* m, bool independent_seeds) const;
219 
220  // Calculate forward directional derivatives using AD
221  int eval_ad(FmuMemory* m) const;
222 
223  // Calculate forward directional derivatives using FD
224  int eval_fd(FmuMemory* m, bool independent_seeds) const;
225 
226  // Get forward sensitivities
227  void get_fwd(FmuMemory* m, casadi_int nsens,
228  const casadi_int* id, double* v) const;
229 
230  // Get the forward sensitivities for a single output
231  void get_fwd(FmuMemory* m, size_t ind, double* v) const;
232 
233  // Set adjoint seeds
234  void set_adj(FmuMemory* m, casadi_int nseed,
235  const casadi_int* id, const double* v) const;
236 
237  // Set all adjoint seeds for a single output
238  void set_adj(FmuMemory* m, size_t ind, const double* v) const;
239 
240  // Request the calculation of adjoint sensitivities
241  void request_adj(FmuMemory* m, casadi_int nsens, const casadi_int* id,
242  const casadi_int* wrt_id) const;
243 
244  // Request the calculation of all adjoint sensitivities for an input
245  void request_adj(FmuMemory* m, casadi_int ind) const;
246 
247  // Calculate adjoint sensitivities
248  int eval_adj(FmuMemory* m) const;
249 
250  // Get adjoint sensitivities
251  void get_adj(FmuMemory* m, casadi_int nsens,
252  const casadi_int* id, double* v) const;
253 
254  // Get the adjoint sensitivities for a single input
255  void get_adj(FmuMemory* m, size_t ind, double* v) const;
256 
257  // Gather forward sensitivities
258  void gather_fwd(FmuMemory* m) const;
259 
260  // Gather adjoint sensitivities
261  void gather_adj(FmuMemory* m) const;
262 
263  // Gather user inputs and outputs
264  void gather_io(FmuMemory* m) const;
265 
269  virtual void get_stats(FmuMemory* m, Dict* stats,
270  const std::vector<std::string>& name_in, const InputStruct* in) const = 0;
271 
272  void serialize(SerializingStream& s) const;
273 
274  virtual void serialize_type(SerializingStream& s) const;
275  virtual void serialize_body(SerializingStream& s) const;
276 
277  static FmuInternal* deserialize(DeserializingStream& s);
278 
279  protected:
280  explicit FmuInternal(DeserializingStream& s);
281 
282  // Resource holding unzipped data (notably DLL)
283  // Must come before li_, because of destructor order
285 
287  std::string name_;
288 
289  // IO scheme
290  std::vector<std::string> scheme_in_, scheme_out_;
291  std::map<std::string, std::vector<size_t>> scheme_;
292 
293  // Auxilliary outputs
294  std::vector<std::string> aux_;
295 
296  // Path to the FMU resource directory
297  std::string resource_loc_;
298 
299  // Tolerance
300  double fmutol_;
301 
302  // Instance name
303  std::string instance_name_;
304 
305  // GUID / instantiation_token
306  std::string instantiation_token_;
307 
308  // Logging?
310 
311  // Number of event indicators
313 
314  // Does the FMU declare analytic derivatives support?
315  bool provides_directional_derivatives_, provides_adjoint_derivatives_;
316 
317  // Does the FMU declare restrictions on instantiation?
319 
322 
323  // Mapping from scheme variable to and from FMU variable indices
324  std::vector<size_t> iind_, iind_map_, oind_, oind_map_;
325 
326  // Is there an independent variable?
328 
329  // Meta information about the input/output variable subsets
330  std::vector<double> nominal_in_, nominal_out_;
331  std::vector<double> min_in_, min_out_;
332  std::vector<double> max_in_, max_out_;
333  std::vector<std::string> vn_in_, vn_out_;
334  std::vector<unsigned int> vr_in_, vr_out_;
335 
336  // Numerical values for inputs
337  std::vector<double> value_in_;
338 
339  // Reduced space indices for all inputs and outputs
340  std::vector<std::vector<size_t>> ired_, ored_;
341 
342  // Sparsity pattern for extended Jacobian, Hessian
343  Sparsity jac_sp_, hess_sp_;
344 
350 
351  size_t nx_;
352  // Instead of set_real+get_real, do set_real+get_real+get_derivatives+get_real
354 };
355 
356 template<typename T>
357 T* FmuInternal::load_function(const std::string& symname) {
358  // Load the function
359  signal_t f = li_.get_function(symname);
360  // Ensure that it was found
361  casadi_assert(f != 0, "Cannot retrieve '" + symname + "'");
362  // Return function with the right type
363  return reinterpret_cast<T*>(f);
364 }
365 
366 } // namespace casadi
367 
369 
370 #endif // CASADI_FMU_IMPL_HPP
Helper class for Serialization.
Interface to binary FMU.
Definition: fmu_impl.hpp:61
bool warning_fired_values_of_continuous_states_changed_
Definition: fmu_impl.hpp:348
std::string instantiation_token_
Definition: fmu_impl.hpp:306
std::vector< double > max_in_
Definition: fmu_impl.hpp:332
bool warning_fired_next_event_time_defined_
Definition: fmu_impl.hpp:349
std::string name_
Instance name.
Definition: fmu_impl.hpp:287
virtual int get_directional_derivative(void *instance, const unsigned int *vr_out, size_t n_out, const unsigned int *vr_in, size_t n_in, const double *seed, size_t n_seed, double *sensitivity, size_t n_sensitivity) const =0
bool provides_adjoint_derivatives_
Definition: fmu_impl.hpp:315
bool warning_fired_nominals_of_continuous_states_changed_
Definition: fmu_impl.hpp:347
virtual void free_instance(void *c) const =0
std::vector< size_t > iind_
Definition: fmu_impl.hpp:324
std::vector< std::vector< size_t > > ired_
Definition: fmu_impl.hpp:340
std::vector< std::string > aux_
Definition: fmu_impl.hpp:294
std::map< std::string, std::vector< size_t > > scheme_
Definition: fmu_impl.hpp:291
virtual int get_aux(void *instance)=0
bool warning_fired_terminate_simulation_
Definition: fmu_impl.hpp:346
bool warning_fired_discrete_states_need_update_
Definition: fmu_impl.hpp:345
virtual int get_real(void *instance, const unsigned int *vr, size_t n_vr, double *values, size_t n_values) const =0
std::vector< std::string > vn_in_
Definition: fmu_impl.hpp:333
virtual void load_functions()=0
virtual int update_discrete_states(void *instance, EventMemory *eventmem) const =0
virtual void get_stats(FmuMemory *m, Dict *stats, const std::vector< std::string > &name_in, const InputStruct *in) const =0
Get stats.
std::vector< unsigned int > vr_in_
Definition: fmu_impl.hpp:334
virtual void * instantiate() const =0
virtual int exit_initialization_mode(void *instance) const =0
virtual int set_values(void *instance) const =0
bool can_be_instantiated_only_once_per_process_
Definition: fmu_impl.hpp:318
virtual void free_mem(void *mem) const =0
Free memory block.
T * load_function(const std::string &symname)
Definition: fmu_impl.hpp:357
size_t n_in() const
Get the number of scheme inputs.
Definition: fmu_impl.hpp:127
std::vector< double > nominal_in_
Definition: fmu_impl.hpp:330
std::string resource_loc_
Definition: fmu_impl.hpp:297
std::vector< double > min_in_
Definition: fmu_impl.hpp:331
std::vector< double > value_in_
Definition: fmu_impl.hpp:337
virtual int set_real(void *instance, const unsigned int *vr, size_t n_vr, const double *values, size_t n_values) const =0
casadi_int number_of_event_indicators_
Definition: fmu_impl.hpp:312
Importer li_
DLL.
Definition: fmu_impl.hpp:321
virtual int get_derivatives(void *instance, double *derivatives, size_t nx) const =0
size_t n_out() const
Get the number of scheme outputs.
Definition: fmu_impl.hpp:132
virtual int enter_continuous_time_mode(void *instance) const =0
virtual int enter_initialization_mode(void *instance) const =0
virtual FmuMemory * alloc_mem(const FmuFunction &f) const =0
Create memory block.
std::vector< std::string > scheme_in_
Definition: fmu_impl.hpp:290
std::string instance_name_
Definition: fmu_impl.hpp:303
virtual std::string system_infix() const =0
Interface to binary FMU.
Definition: fmu.hpp:62
Importer.
Definition: importer.hpp:86
signal_t get_function(const std::string &symname)
Get a function pointer for numerical evaluation.
Definition: importer.cpp:79
RAII class for reading from a zip file.
Definition: resource.hpp:44
Helper class for Serialization.
General sparsity class.
Definition: sparsity.hpp:106
The casadi namespace.
Definition: archiver.cpp:28
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
void(* signal_t)(void)
Function pointer types for the C API.
bool discrete_states_need_update
Definition: fmu_impl.hpp:39
bool next_event_time_defined
Definition: fmu_impl.hpp:43
double next_event_time
Definition: fmu_impl.hpp:44
bool nominals_of_continuous_states_changed
Definition: fmu_impl.hpp:41
bool values_of_continuous_states_changed
Definition: fmu_impl.hpp:42