fmu_function.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 
26 #ifndef CASADI_FMU_FUNCTION_HPP
27 #define CASADI_FMU_FUNCTION_HPP
28 
29 #include "function_internal.hpp"
30 #include "fmu.hpp"
31 #include "finite_differences.hpp"
32 
34 
35 namespace casadi {
36 
37 // Forward declarations
38 class DaeBuilderInternal;
39 class FmuFunction;
40 struct InputStruct;
41 
42 // Memory object
43 struct CASADI_EXPORT FmuMemory : public FunctionMemory {
44  // Function object
45  const FmuFunction& self;
46  // Evaluation inputs
47  const double** arg;
48  // Evaluation outputs
49  double** res;
50  // Work vector for star coloring
51  casadi_int* star_iw;
52  // Extended Jacobian
53  double *jac_nz;
54  // Extended Hessian
55  double *hess_nz;
56  // Adjoint seeds, sensitivities being calculated
57  double *aseed, *asens, *pert_asens;
58  // Memory for Jacobian calculation
60  // Instance memory
61  void* instance;
62  // Additional (slave) memory objects
63  std::vector<FmuMemory*> slaves;
64  // Input and output buffers
65  std::vector<double> ibuf_, obuf_;
66  // Seeds, sensitivities
67  std::vector<double> seed_, sens_;
68  // Which entries have been changed
69  std::vector<bool> changed_;
70  // Which entries are being requested
71  std::vector<bool> requested_;
72  // Derivative with respect to
73  std::vector<size_t> wrt_;
74  // Current known/unknown variables
75  std::vector<size_t> id_in_, id_out_;
76  // Which perturbations are permitted
77  std::vector<bool> in_bounds_;
78  // Flip sign?
79  std::vector<bool> flip_;
80  // Value references
81  std::vector<unsigned int> vr_in_, vr_out_;
82  // Work vector (reals)
83  std::vector<double> v_in_, v_out_, d_in_, d_out_, fd_out_, v_pert_;
84  // Constructor
85  explicit FmuMemory(const FmuFunction& self) : self(self), instance(nullptr) {}
86 };
87 
89 enum class Parallelization {SERIAL, OPENMP, THREAD, NUMEL};
90 
92 CASADI_EXPORT std::string to_string(Parallelization v);
93 
94 // Types of inputs
95 enum class InputType {REG, FWD, ADJ, OUT, ADJ_OUT};
96 
97 // Input structure
98 struct CASADI_EXPORT InputStruct {
99  // Type of input
100  InputType type;
101  // Corresponding index in Fmu
102  size_t ind;
103  // Parse an input string
104  static InputStruct parse(const std::string& n, const Fmu* fmu,
105  std::vector<std::string>* name_in = 0,
106  std::vector<std::string>* name_out = 0);
107 };
108 
109 // Types of inputs
110 enum class OutputType {REG, FWD, ADJ, JAC, JAC_TRANS, JAC_ADJ_OUT, JAC_REG_ADJ, HESS};
111 
112 // Output structure
113 struct CASADI_EXPORT OutputStruct {
114  // Type of input
115  OutputType type;
116  // Output index in Fmu
117  size_t ind;
118  // With-respect-to index in Fmu
119  size_t wrt;
120  // Selection
121  size_t rbegin, rend, cbegin, cend;
122  // Parse an output string
123  static OutputStruct parse(const std::string& n, const Fmu* fmu,
124  std::vector<std::string>* name_in = 0,
125  std::vector<std::string>* name_out = 0);
126  // Constructor
127  OutputStruct() : ind(-1), wrt(-1), rbegin(-1), rend(-1), cbegin(-1), cend(-1) {}
128 };
129 
130 // Helper function
131 CASADI_EXPORT bool has_prefix(const std::string& s);
132 
133 // Split prefix
134 CASADI_EXPORT std::string pop_prefix(const std::string& s, std::string* rem = 0);
135 
136 class CASADI_EXPORT FmuFunction : public FunctionInternal {
137  public:
138  // FMU (shared between derivative expressions
139  Fmu fmu_;
140 
141  // Information about function inputs
142  std::vector<InputStruct> in_;
143 
144  // Information about function outputs
145  std::vector<OutputStruct> out_;
146 
147  // All Jacobian inputs and outputs
148  std::vector<size_t> jac_in_, jac_out_;
149 
150  // Nominal values for Jacobian inputs
151  std::vector<double> jac_nom_in_;
152 
153  // Sparsity of transpose (if needed)
154  std::vector<Sparsity> sp_trans_;
155  std::vector<casadi_int> sp_trans_map_;
156 
157  // What blocks exist?
158  bool has_jac_, has_fwd_, has_adj_, has_hess_;
159 
160  // User-set options
161  bool enable_ad_, validate_ad_, make_symmetric_, check_hessian_;
162  double step_, abstol_, reltol_;
163  bool print_progress_, new_jacobian_, new_forward_, new_hessian_, hessian_coloring_;
164  std::string validate_ad_file_;
165 
166  // FD method as an enum
167  FdMode fd_;
168 
169  // Types of parallelization
170  Parallelization parallelization_;
171 
172  // Stats from initialization
173  Dict init_stats_;
174 
178  FmuFunction(const std::string& name, const Fmu& fmu,
179  const std::vector<std::string>& name_in,
180  const std::vector<std::string>& name_out);
181 
185  ~FmuFunction() override;
186 
190  std::string class_name() const override { return "FmuFunction";}
191 
193 
196  static const Options options_;
197  const Options& get_options() const override { return options_;}
199 
201  void init(const Dict& opts) override;
202 
203  // Identify input and output schemes from FmuFunction inputs and outputs
204  static void identify_io(
205  std::vector<std::string>* scheme_in,
206  std::vector<std::string>* scheme_out,
207  const std::vector<std::string>& name_in,
208  const std::vector<std::string>& name_out);
209 
210  // Get sparsity pattern for extended Jacobian, Hessian
211  Sparsity jac_sp_, hess_sp_;
212 
213  // Graph coloring
214  Sparsity jac_colors_, hess_colors_;
215 
216  // Nonlinearly entering variables
217  std::vector<casadi_int> nonlin_;
218 
219  // Jacobian memory
221 
222  // Number of parallel tasks
223  casadi_int max_jac_tasks_, max_hess_tasks_, max_n_tasks_;
224 
226 
229  size_t get_n_in() override { return in_.size();}
230  size_t get_n_out() override {return out_.size();}
232 
234 
237  Sparsity get_sparsity_in(casadi_int i) override;
238  Sparsity get_sparsity_out(casadi_int i) override;
240 
242 
245  std::vector<double> get_nominal_in(casadi_int i) const override;
246  std::vector<double> get_nominal_out(casadi_int i) const override;
248 
249  // Evaluate numerically
250  int eval(const double** arg, double** res, casadi_int* iw, double* w, void* mem) const override;
251 
252  // Evaluate all tasks numerically, serially or in parallel
253  int eval_all(FmuMemory* m, casadi_int n_task,
254  bool need_nondiff, bool need_jac, bool need_fwd, bool need_adj, bool need_hess) const;
255 
256  // Evaluate numerically, single thread
257  int eval_task(FmuMemory* m, casadi_int task, casadi_int n_task,
258  bool need_nondiff, bool need_jac, bool need_fwd, bool need_adj, bool need_hess) const;
259 
260  // Remove NaNs from Hessian (necessary for star coloring approach)
261  void remove_nans(double *hess_nz, casadi_int* iw) const;
262 
263  // Check extended Hessian
264  void check_hessian(FmuMemory* m, const double *hess_nz, casadi_int* iw) const;
265 
266  // Make extended Hessian symmetric
267  void make_symmetric(double *hess_nz, casadi_int* iw) const;
268 
270 
273  bool has_jac_sparsity(casadi_int oind, casadi_int iind) const override;
274  Sparsity get_jac_sparsity(casadi_int oind, casadi_int iind, bool symmetric) const override;
276 
277  // Are all inputs/outputs regular?
278  bool all_regular() const;
279 
280  // Are all inputs/outputs vectors (i.e. not Jacobian or Hessian blocks)?
281  bool all_vectors() const;
282 
283  // Factory
284  Function factory(const std::string& name,
285  const std::vector<std::string>& s_in,
286  const std::vector<std::string>& s_out,
287  const Function::AuxOut& aux,
288  const Dict& opts) const override;
289 
291 
294  bool has_jacobian() const override;
295  Function get_jacobian(const std::string& name,
296  const std::vector<std::string>& inames,
297  const std::vector<std::string>& onames,
298  const Dict& opts) const override;
300 
302 
305  bool has_forward(casadi_int nfwd) const override;
306  Function get_forward(casadi_int nfwd, const std::string& name,
307  const std::vector<std::string>& inames,
308  const std::vector<std::string>& onames,
309  const Dict& opts) const override;
311 
313 
316  bool has_reverse(casadi_int nadj) const override;
317  Function get_reverse(casadi_int nadj, const std::string& name,
318  const std::vector<std::string>& inames,
319  const std::vector<std::string>& onames,
320  const Dict& opts) const override;
322 
326  void* alloc_mem() const override;
327 
331  int init_mem(void* mem) const override;
332 
336  void free_mem(void *mem) const override;
337 
339  Dict get_stats(void* mem) const override;
340 
344  void serialize_body(SerializingStream &s) const override;
345 
349  static ProtoFunction* deserialize(DeserializingStream& s) { return new FmuFunction(s); }
350 
354  void change_option(const std::string& option_name, const GenericType& option_value) override;
355 
356  protected:
360  explicit FmuFunction(DeserializingStream& s);
361 };
362 
363 } // namespace casadi
365 
366 #endif // CASADI_FMU_FUNCTION_HPP
std::map< std::string, std::vector< std::string > > AuxOut
Definition: function.hpp:395
The casadi namespace.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.